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.c b/src/386.c index cb78c4e..48522c9 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" @@ -13,56 +12,15 @@ #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; - -int inscounts[256]; -uint32_t oldpc2; - -int trap; - - - -extern int cpl_override; - -int has_fpu; -extern int fpucount; -uint16_t rds; -uint16_t ea_rseg; - -int is486; -int cgate32; - - - -uint8_t romext[32768]; -uint8_t *ram,*rom; - -uint32_t rmdat32; -#define rmdat rmdat32 -#define fetchdat rmdat32 -uint32_t backupregs[16]; -extern int oddeven; -int inttype; - - -uint32_t oldcs2; -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; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; if (cpu_rm == 4) { uint8_t sib = rmdat >> 8; @@ -89,8 +47,7 @@ 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 = &_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); @@ -103,8 +60,7 @@ 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 = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } if (cpu_mod == 1) { @@ -135,8 +91,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(); } @@ -158,8 +113,7 @@ 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 = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } cpu_state.eaaddr &= 0xFFFF; } @@ -182,19 +136,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 @@ -203,13 +145,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; @@ -222,42 +157,31 @@ 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) { - /* 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; - oldcpl=CPL; cpu_state.op32 = use32; -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); if (!cpu_state.abrt) - { - trap = 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 %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,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); @@ -265,29 +189,17 @@ dontprint=0; break; } - if (!use32) cpu_state.pc &= 0xffff; - if (cpu_state.abrt) { 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); 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); @@ -306,20 +218,19 @@ dontprint=0; { flags_rebuild(); // oldpc=pc; -// oldcs=CS; if (msw&1) { pmodeint(1,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)); } @@ -327,7 +238,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; @@ -337,7 +247,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) @@ -353,14 +263,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; - oxpc=cpu_state.pc; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); // if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc); @@ -381,7 +290,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.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.c b/src/386_common.c new file mode 100644 index 0000000..df19e14 --- /dev/null +++ b/src/386_common.c @@ -0,0 +1,249 @@ +#include "ibm.h" +#include "x86.h" +#include "386_common.h" +#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; + +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; + +uint32_t pccache; +uint8_t *pccache2; + +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_common.h b/src/386_common.h index 3401257..80da16d 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -1,21 +1,19 @@ -extern uint16_t ea_rseg; +#ifndef _386_COMMON_H_ +#define _386_COMMON_H_ -#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 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 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 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 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 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,26 +24,35 @@ int checkio(int port); } \ } -#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \ - { \ - int tempi = checkio(port); \ - if (cpu_state.abrt) break; \ - if (tempi) \ - { \ - x86gpf(NULL,0); \ - break; \ - } \ - } +#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))) \ + 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; \ @@ -59,7 +66,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; \ @@ -124,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++; @@ -156,32 +174,30 @@ 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() { 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); + return readmemw(easeg,cpu_state.eaaddr); } 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); + 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,24 +218,20 @@ 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 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 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 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); #define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++ #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 - -#define rmdat rmdat32 -#define fetchdat rmdat32 - -void x86_int(int num); +#endif diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 2ccc1dd..eaa2041 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -2,12 +2,12 @@ #include #include #include "ibm.h" -#include "386.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" #include "mem.h" #include "codegen.h" +#include "codegen_backend.h" #include "cpu.h" #include "fdc.h" #include "nmi.h" @@ -18,59 +18,18 @@ #define CPU_BLOCK_END() cpu_block_end = 1 -uint32_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 inscounts[256]; -uint32_t oldpc2; - -int trap; - - - -int cpl_override=0; - -int has_fpu; -int fpucount=0; -uint16_t rds; -uint16_t ea_rseg; - -int is486; -int cgate32; - - -uint8_t romext[32768]; -uint8_t *ram,*rom; - -uint32_t rmdat32; -uint32_t backupregs[16]; -int oddeven=0; -int inttype; - - -uint32_t oldcs2; -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; easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; if (cpu_rm == 4) { uint8_t sib = rmdat >> 8; @@ -97,8 +56,7 @@ 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 = &_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); @@ -111,8 +69,7 @@ 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 = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } if (cpu_mod == 1) { @@ -143,8 +100,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(); } @@ -166,8 +122,7 @@ 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 = &_ss; + cpu_state.ea_seg = &cpu_state.seg_ss; } cpu_state.eaaddr &= 0xFFFF; } @@ -186,151 +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,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-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - } - - flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=cpu_state.pc; - 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,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-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - } - - flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=cpu_state.pc; - 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),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.pc = new_pc; - loadcs(new_cs); - oxpc=cpu_state.pc; - - 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. @@ -416,89 +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 = readmemb386l(0, 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)); -} - -int xout=0; - - -#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(); -} - -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) @@ -506,7 +233,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)) && !(cpu_state.flags & T_FLAG)) //#define CACHE_ON() 0 static int cycles_main = 0; @@ -518,7 +245,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,424 +254,389 @@ void exec386_dynarec(int cycs) cycles += cyc_period; cycles_start = cycles; - timer_start_period(cycles << TIMER_SHIFT); -// output=3; - while (cycles>0) - { - oldcs = CS; - cpu_state.oldpc = cpu_state.pc; - oldcpl = CPL; - 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*/ + 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*/ { - oldcs=CS; - cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; - 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 = &_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 = 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 (!use32) cpu_state.pc &= 0xffff; - - 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_hash[hash]; - int valid_block = 0; - trap = 0; - - if (block && !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; + 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]); + + 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->endpc); - 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->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP) - { - /*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; - } - } + if (((cs + cpu_state.pc) >> 12) != pccache) + CPU_BLOCK_END(); - if (valid_block && block->was_recompiled) - { - 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; - code(); -inrecomp=0; - if (!use32) cpu_state.pc &= 0xffff; -// 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) - { - oldcs=CS; - cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; - cpu_state.op32 = use32; - - cpu_state.ea_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 = 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; - } - - 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 - 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) - { - oldcs=CS; - cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; - cpu_state.op32 = use32; - - cpu_state.ea_seg = &_ds; - cpu_state.ssegs = 0; - - codegen_endpc = (cs + cpu_state.pc) + 8; - fetchdat = fastreadl(cs + cpu_state.pc); - - if (!cpu_state.abrt) - { - trap = 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; - } - - 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 - 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; - } -// 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; - CS = oldcs; - 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) - { - - flags_rebuild(); -// oldpc=pc; -// oldcs=CS; - if (msw&1) - { - pmodeint(1,0); } else { - writememw(ss,(SP-2)&0xFFFF,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.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); + 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); + 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); + 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) + { + /*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 + ((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); + 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_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 + 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 = cs+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; + + 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) + { + 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); + + 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 (((cs+cpu_state.pc) - start_pc) >= max_block_size) + 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 = cs+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; + + 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) + { + 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); + + 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 (((cs+cpu_state.pc) - start_pc) >= max_block_size) + 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; - oldcs = CS; -// 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 ((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 { - 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; - oxpc=cpu_state.pc; + 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)); } } + 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; + cpu_state.pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + } + } + } } - } - 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/386_dynarec_ops.c b/src/386_dynarec_ops.c index 5be12c1..249909f 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,14 +14,10 @@ #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; 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; @@ -37,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; @@ -48,8 +42,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++; 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) @@ -57,7 +51,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) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) #include "386_ops.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/808x.c b/src/808x.c index 4602a8a..af45bf4 100644 --- a/src/808x.c +++ b/src/808x.c @@ -25,45 +25,49 @@ #include "x87.h" #include "paths.h" -int xt_cpu_multi; +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 memcycs; -int nopageerrors=0; +static uint32_t oldds; +uint32_t oldss; -void FETCHCOMPLETE(); +static int nextcyc=0; +static int memcycs; -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); +static int cycdiff; +static void FETCHCOMPLETE(); -#undef readmemb -#undef readmemw -uint8_t readmemb(uint32_t a) +#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint) + +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); + if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s+a); else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); } @@ -76,48 +80,28 @@ 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) +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 writememwl(uint32_t seg, uint32_t addr, uint16_t val); -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); + 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); - else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v; -} -uint16_t oldcs; -int oldcpl; - -int tempc; -uint8_t opcode; -uint16_t pc2,pc3; -int noint=0; - -int output=0; - -int shadowbios=0; - -int ins=0; //#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; @@ -202,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; @@ -343,9 +327,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]; @@ -442,7 +426,7 @@ static inline void seteaw(uint16_t val) /*Flags*/ uint8_t znptable8[256]; -uint16_t znptable16[65536]; +static uint16_t znptable16[65536]; void makeznptable() { @@ -489,10 +473,6 @@ void makeznptable() // makemod1table(); } -int timetolive=0; - -extern uint32_t oldcs2; -extern uint32_t oldpc2; int indump = 0; @@ -509,7 +489,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);*/ @@ -538,10 +517,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(readmembl(c+0x80000000),f); } fclose(f); pclog("Dumping done\n"); @@ -580,22 +559,22 @@ 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("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); + 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\n",cpu_state.oldpc); 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,_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); @@ -616,17 +595,14 @@ 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; stack32=0; - cpu_hasCX8 = 0; // i86_Reset(); // cs=0xFFFF0; msw=0; @@ -637,7 +613,7 @@ void resetx86() cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; - eflags=0; + cpu_state.eflags=0; cgate32=0; if (AT) { @@ -653,17 +629,15 @@ void resetx86() } idt.base = 0; idt.limit = is386 ? 0x03FF : 0xFFFF; - flags=2; + 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; - memset(inscounts, 0, sizeof(inscounts)); x86seg_reset(); codegen_reset(); x86_was_reset = 1; @@ -686,9 +660,8 @@ 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) { loadcs(0xF000); @@ -702,142 +675,186 @@ void softresetx86() rammask = 0xfffff; } //rammask=0xFFFFFFFF; - flags=2; + cpu_state.flags=2; idt.base = 0; idt.limit = is386 ? 0x03FF : 0xFFFF; + EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; x86seg_reset(); + flushmmucache(); x86_was_reset = 1; } 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; -void clockhardware() + +/*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; + +static 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; @@ -845,7 +862,7 @@ static int takeint = 0; int firstrepcycle=1; -void rep(int fv) +static void rep(int fv) { uint8_t temp; int c=CX; @@ -892,8 +909,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; } @@ -906,8 +923,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(); @@ -924,8 +941,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(); @@ -937,43 +954,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); @@ -983,8 +1000,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(); @@ -999,8 +1016,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(); @@ -1014,8 +1031,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; } @@ -1026,8 +1043,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; } @@ -1035,37 +1052,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: @@ -1084,13 +1101,9 @@ void rep(int fv) } -int inhlt=0; -uint16_t lastpc,lastcs; -int firstrepcycle; -int skipnextprint=0; +static int inhlt=0; +static int skipnextprint=0; -int instime=0; -//#if 0 void execx86(int cycs) { uint8_t temp,temp2; @@ -1108,25 +1121,20 @@ void execx86(int cycs) // return; while (cycles>0) { -// 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); + uint8_t opcode; + cycdiff=cycles; - timer_start_period(cycles*xt_cpu_multi); current_diff = 0; cycles-=nextcyc; // if (instime) pclog("Cycles %i %i\n",cycles,cycdiff); nextcyc=0; // if (output) printf("CLOCK %i %i\n",cycdiff,cycles); fetchclocks=0; - oldcs=CS; 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 +1143,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++; // } @@ -1205,7 +1213,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; @@ -1215,7 +1223,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 +1232,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 +1241,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 +1250,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; @@ -1268,7 +1276,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; @@ -1327,7 +1335,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; @@ -1392,7 +1400,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; @@ -1403,7 +1411,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 +1420,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 +1429,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 +1438,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 +1465,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 +1540,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 +1565,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 +1574,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 +1583,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 +1592,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 +1619,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 +1680,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 +1724,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 +1840,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 +1859,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 +1871,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 +1902,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 +1916,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 +1935,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 +1969,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 +1991,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 +2004,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 +2023,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 +2031,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*/ @@ -2098,20 +2108,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); @@ -2171,22 +2181,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 +2226,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 +2250,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; @@ -2360,14 +2370,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; @@ -2408,13 +2418,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)); @@ -2423,15 +2433,13 @@ void execx86(int cycs) cycles-=72; break; case 0xCD: /*INT*/ - lastpc=cpu_state.pc; - lastcs=CS; 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 +2456,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 +2468,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 +2562,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 +2665,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 +2682,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 +2723,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 +2776,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 +2803,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 +2818,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 +2865,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 +2912,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 +2937,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 +2954,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*/ @@ -3057,7 +3067,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"); @@ -3070,7 +3080,7 @@ void execx86(int cycs) cycles-=2; break; case 0xF5: /*CMC*/ - flags^=C_FLAG; + cpu_state.flags ^= C_FLAG; cycles-=2; break; @@ -3084,7 +3094,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 +3111,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 +3155,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 +3199,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 +3232,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 +3251,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 +3270,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 +3287,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 +3314,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 +3336,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); @@ -3491,16 +3501,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(); @@ -3508,13 +3518,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(); @@ -3526,13 +3536,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)); @@ -3540,7 +3550,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/Makefile.am b/src/Makefile.am index f00cd36..7746e30 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,24 +23,26 @@ 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 acc2168.c acc3221.c acer386sx.c ali1429.c amstrad.c cassette.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 i430hx.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 \ +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_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 \ 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 pzx.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 \ vid_ht216.c 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_sigma.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 zenith.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 @@ -70,12 +72,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_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_x86-64.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 +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_imm.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c endif if USE_NETWORKING @@ -114,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/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/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index b49f36f..9c28a55 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -6,25 +6,43 @@ WXVERSION = 31 WXINCLUDE = e:/MinGWget/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 acc2168.o acc3221.o acer386sx.o ali1429.o amstrad.o cassette.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 i430hx.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 pzx.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_ht216.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_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 \ + 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 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 \ 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_sigma.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 zenith.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 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/cassette.c b/src/cassette.c index 84c5625..68f495a 100644 --- a/src/cassette.c +++ b/src/cassette.c @@ -23,6 +23,7 @@ #include #include "ibm.h" #include "cpu.h" +#include "x86.h" #include "device.h" #include "pzx.h" 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.c b/src/codegen.c index 8256ab2..06f6213 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -2,12 +2,63 @@ #include "x86_ops.h" #include "mem.h" #include "codegen.h" +#include "x86.h" + +#include "386_common.h" + +#include "codegen_accumulate.h" +#include "codegen_allocator.h" +#include "codegen_backend.h" +#include "codegen_ir.h" +#include "codegen_ops.h" +#include "codegen_ops_helpers.h" + +#define MAX_INSTRUCTION_COUNT 50 + +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; +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)(); +int (*codegen_timing_jump_cycles)(); void codegen_timing_set(codegen_timing_t *timing) { @@ -16,6 +67,705 @@ 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; + +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; + 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) || (cpu_state.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, codegen_gpf_rout); + + 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) || (cpu_state.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, codegen_gpf_rout); + + 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) +{ + 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) + { + 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 & 7) + { + 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 = &cpu_state.seg_ss; + } + } + + codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-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) + { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (cpu_mod) + { + case 0: + if ((sib & 7) == 5) + { + 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: + 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)++; + extra_bytes = 2; + break; + case 2: + 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*/ + { + 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 = &cpu_state.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) + { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + 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; +} + +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 ((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); + + 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*/ + 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, 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*/ + + 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]; + 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 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 + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; + + codegen_timing_start(); + + while (!over) + { + 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; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.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: +#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; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + over = 1; + pc_off = -1; + test_modrm = 0; + 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; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + + case 0xf0: /*LOCK*/ + 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; + + 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_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); + 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))) + { + /*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) + { + /*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; + } + } + 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]) + { + 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) + uop_MOV_IMM(ir, IREG_pc, new_pc); + + codegen_endpc = (cs + cpu_state.pc) + 8; + + block->ins++; + + if (block->ins >= MAX_INSTRUCTION_COUNT) + CPU_BLOCK_END(); + + return; + } + } + + 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 || + (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || + (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || + (op_table == x86_dynarec_opcodes_3DNOW)) + { + 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, stack_offset); +// 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; + } + +#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 + 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); + 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); + codegen_mark_code_present(block, cs+cpu_state.pc, 8); + + last_op_32 = op_32; + last_op_ea_seg = op_ea_seg; + last_op_ssegs = op_ssegs; + //codegen_block_ins++; + + block->ins++; + + if (block->ins >= MAX_INSTRUCTION_COUNT) + CPU_BLOCK_END(); + + codegen_endpc = (cs + cpu_state.pc) + 8; + +// if (has_ea) +// fatal("Has EA\n"); +} diff --git a/src/codegen.h b/src/codegen.h index c5ad1ed..0f246b3 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 @@ -39,60 +31,88 @@ typedef struct codeblock_t { + uint32_t pc; + uint32_t _cs; + uint32_t phys, phys_2; + uint16_t status; + uint16_t flags; + uint8_t ins; + uint8_t TOP; + + /*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; 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.*/ - 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; - - int pnt; - int ins; - - int was_recompiled; - int TOP; + uint16_t prev, next; + uint16_t prev_2, next_2; - uint32_t pc; - uint32_t _cs; - uint32_t endpc; - uint32_t phys, phys_2; - uint32_t status; - uint32_t flags; - - uint8_t data[2048]; + /*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; +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*/ #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 +/*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 +#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) { - 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) - block = block->left; + if (a < block_cmp) + block = block->left ? &codeblock[block->left] : NULL; else - block = block->right; + block = block->right ? &codeblock[block->right] : NULL; } return block; @@ -100,75 +120,87 @@ 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); - new_block->cmp = a; - - 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 = 0; while (block) { old_block = block; - if (a < old_block->cmp) - block = block->left; + old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32); + + if (a < old_block_cmp) + 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; + if (a < old_block_cmp) + 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; @@ -176,22 +208,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; @@ -199,75 +233,109 @@ 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); } } } -#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 -extern codeblock_t *codeblock; +void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len); -extern codeblock_t **codeblock_hash; +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(); void codegen_reset(); void codegen_block_init(uint32_t phys_addr); 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(); 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, 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); + +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(int required_mem_block); extern int cpu_block_end; extern uint32_t codegen_endpc; @@ -286,23 +354,27 @@ 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)(); +extern int (*codegen_timing_jump_cycles)(); 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)(); + int (*jump_cycles)(); } codegen_timing_t; 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; +extern codegen_timing_t codegen_timing_k6; void codegen_timing_set(codegen_timing_t *timing); @@ -311,45 +383,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; @@ -369,4 +402,13 @@ extern int codegen_reg_loaded[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]; +#endif + #endif 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_allocator.c b/src/codegen_allocator.c new file mode 100644 index 0000000..4b4ffd7 --- /dev/null +++ b/src/codegen_allocator.c @@ -0,0 +1,126 @@ +#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; + uint16_t code_block; +} 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; + mem_blocks[c].code_block = BLOCK_INVALID; + 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, int code_block) +{ + mem_block_t *block; + uint32_t block_nr; + + while (!mem_block_free_list) + { + /*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"); + + /*Remove from free list*/ + block_nr = mem_block_free_list; + block = &mem_blocks[block_nr-1]; + mem_block_free_list = block->next; + + block->code_block = code_block; + 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; + block->code_block = BLOCK_INVALID; + 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..1adb243 --- /dev/null +++ b/src/codegen_allocator.h @@ -0,0 +1,39 @@ +#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 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, 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*/ +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 diff --git a/src/codegen_backend.c b/src/codegen_backend.c new file mode 100644 index 0000000..19e32f6 --- /dev/null +++ b/src/codegen_backend.c @@ -0,0 +1,889 @@ +#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_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; +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; + +#ifdef DEBUG_EXTRA +uint32_t instr_counts[256*256]; +#endif + +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 + 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); +} + +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]; + + if (page->code_present_mask & page->dirty_mask) + { + codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12); + + 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, 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); + } + + 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; +} + +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]); + block_dirty_list_head = block_dirty_list_tail = 0; + dirty_list_size = 0; +#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() +{ + int c; + + for (c = 1; c < BLOCK_SIZE; c++) + { + 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)); + 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() +{ +/* 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) +{ + 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 %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_nr; + } + else + { + block->next = BLOCK_INVALID; + pages[block->phys >> 12].block = block_nr; + } + + if (block->next) + { + 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->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_nr; + } + else + { + block->next_2 = BLOCK_INVALID; + 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) + { + codeblock[block->prev].next = block->next; + if (block->next) + codeblock[block->next].prev = block->prev; + } + else + { + 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->flags & CODEBLOCK_HAS_PAGE2)) + { + if (block->prev_2 || block->next_2) + 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) + { + codeblock[block->prev_2].next_2 = block->next_2; + if (block->next_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->next_2; + if (block->next_2) + codeblock[block->next_2].prev_2 = BLOCK_INVALID; + else + mem_flush_write_page(block->phys_2, 0); + } +} + +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; + + 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); + 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) + delete_block(block); +} + +void codegen_delete_random_block(int required_mem_block) +{ + int block_nr = rand() & BLOCK_MASK; + + while (1) + { + if (block_nr && block_nr != block_current) + { + codeblock_t *block = &codeblock[block_nr]; + + if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block)) + { + delete_block(block); + return; + } + } + block_nr = (block_nr + 1) & BLOCK_MASK; + } +} + +void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + 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 (*block->dirty_mask & block->page_mask) + { +// 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) + fatal("Broken 1\n"); + block_nr = next_block; + } + + block_nr = page->block_2; + + while (block_nr) + { + codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next_2; + + if (*block->dirty_mask2 & block->page_mask2) + { +// 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) + fatal("Broken 2\n"); + block_nr = next_block; + } + + if (page->code_present_mask & page->dirty_mask) + remove_from_evict_list = 1; + page->code_present_mask &= ~page->dirty_mask; + page->dirty_mask = 0; + + 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); +} + +void codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; + + 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"); + block_current = get_block_nr(block); + + block_num = HASH(phys_addr); + codeblock_hash[block_num] = block_current; + + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->phys = phys_addr; + 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 = 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); +} + +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) + mem_flush_write_page(block->phys, cs+cpu_state.pc); + + block_num = HASH(block->phys); + block_current = get_block_nr(block);//block->pnt; + + 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_current); + 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; + +// 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; + + 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->flags |= CODEBLOCK_WAS_RECOMPILED; + + 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(); +} + + +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_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]); + } + } + 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); + 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 & 0xfff) & ~63; + if ((block->pc ^ codegen_endpc) & ~0xfff) + end_pc = 0xfff & ~63; + else + end_pc = (codegen_endpc & 0xfff) & ~63; + if (end_pc < start_pc) + 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->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) & ~0xfff) + { + 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 = (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->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) + 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]); + } + + 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); + recomp_page = -1; +} + +void codegen_block_end() +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask_mark(); + add_to_block_list(block); +} + +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); + 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_recompile(); + add_to_block_list(block); +// pclog("End block %i\n", block_num); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; + + codegen_accumulate_flush(ir_data); + codegen_ir_compile(ir_data, block); +} + +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 = end_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.h b/src/codegen_backend.h new file mode 100644 index 0000000..7a5c5c0 --- /dev/null +++ b/src/codegen_backend.h @@ -0,0 +1,29 @@ +//#ifdef __amd64__ +//#include "codegen_x86-64.h" +#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__ +#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); + +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[]; + +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 new file mode 100644 index 0000000..0c1c2c8 --- /dev/null +++ b/src/codegen_backend_arm.c @@ -0,0 +1,368 @@ +#ifdef __ARM_EABI__ + +#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" +#include "codegen_reg.h" +#include "x86.h" +#include "x87.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +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; + +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_gpf_rout; +void *codegen_exit_rout; + +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_R4, + REG_R5, + REG_R6, + REG_R7, + REG_R8, + REG_R9, + 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, int is_float) +{ + uint32_t *branch_offset; + uint32_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 readmembl + 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); + 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 && !is_float) + host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 2 && !is_float) + host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); + 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) + { + 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); + + *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *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)readmembl); + else if (size == 2) + 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) + 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); +} + +static void build_store_routine(codeblock_t *block, int size, int is_float) +{ + uint32_t *branch_offset; + uint32_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 readmembl + 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); + 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 && !is_float) + host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 2 && !is_float) + host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); + 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) + { + 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); + + *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *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); + 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)writemembl); + 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); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &block_write_data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &block_write_data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &block_write_data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &block_write_data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &block_write_data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &block_write_data[block_pos]; + build_load_routine(block, 8, 1); + + codegen_mem_store_byte = &block_write_data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &block_write_data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &block_write_data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &block_write_data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &block_write_data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &block_write_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; + + 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_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_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_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); + 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_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); + 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_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); +} + +void codegen_backend_init() +{ + codeblock_t *block; + int c; + + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + 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].pc = BLOCK_PC_INVALID; + +// 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_current); + 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 = &block_write_data[block_pos]; + build_fp_round_routine(&codeblock[block_current]); + + 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) + ); + 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*/ +void codegen_backend_prologue(codeblock_t *block) +{ + block_pos = BLOCK_START; + + /*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, 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, 0x40); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); + + codegen_allocator_clean_blocks(block->head_mem_block); +} + +#endif diff --git a/src/codegen_backend_arm.h b/src/codegen_backend_arm.h new file mode 100644 index 0000000..bfd5206 --- /dev/null +++ b/src/codegen_backend_arm.h @@ -0,0 +1,24 @@ +#include "codegen_backend_arm_defs.h" + +#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_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); +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_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 new file mode 100644 index 0000000..eb50aa6 --- /dev/null +++ b/src/codegen_backend_arm64.c @@ -0,0 +1,382 @@ +#ifdef __aarch64__ + +#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" +#include "codegen_reg.h" +#include "x86.h" +#include "x87.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +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; + +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; + +void *codegen_gpf_rout; +void *codegen_exit_rout; + +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_X19, + REG_X20, + REG_X21, + REG_X22, + REG_X23, + REG_X24, + REG_X25, + REG_X26, + REG_X27, + 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, int is_float) +{ + uint32_t *branch_offset; + uint32_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 readmembl + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + codegen_alloc(block, 80); + host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); + 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) + { + 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 && !is_float) + host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 2 && !is_float) + host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); + 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) + 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); + + 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_XSP, -16); + if (size == 1) + host_arm64_call(block, (void *)readmembl); + else if (size == 2) + host_arm64_call(block, (void *)readmemwl); + else if (size == 4) + host_arm64_call(block, (void *)readmemll); + else if (size == 8) + 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); + if (size == 4 && 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_XSP, 16); + host_arm64_RET(block, REG_X30); +} + +static void build_store_routine(codeblock_t *block, int size, int is_float) +{ + uint32_t *branch_offset; + uint32_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 writemembl + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + codegen_alloc(block, 80); + host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); + 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) + { + 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 && !is_float) + host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 2 && !is_float) + host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); + 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) + 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); + + 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_XSP, -16); + if (size == 4 && is_float) + host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); + else if (size == 8) + host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); + if (size == 1) + host_arm64_call(block, (void *)writemembl); + else if (size == 2) + host_arm64_call(block, (void *)writememwl); + else if (size == 4) + host_arm64_call(block, (void *)writememll); + else if (size == 8) + 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); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &block_write_data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &block_write_data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &block_write_data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &block_write_data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &block_write_data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &block_write_data[block_pos]; + build_load_routine(block, 8, 1); + + codegen_mem_store_byte = &block_write_data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &block_write_data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &block_write_data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &block_write_data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &block_write_data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &block_write_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; + + 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 = (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 + 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_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_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_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); +} + +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 *)); + + 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].pc = BLOCK_PC_INVALID; + } + +// 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_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); + + 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); + + 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, (void *)x86gpf); + + codegen_exit_rout = &block_write_data[block_pos]; + 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; + + codegen_allocator_clean_blocks(block->head_mem_block); + + 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; +} + +/*R10 - cpu_state*/ +void codegen_backend_prologue(codeblock_t *block) +{ + block_pos = BLOCK_START; + + /*Entry code*/ + + 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); + + 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_XSP, IREG_TOP_diff_stack_offset); + } +} + +void codegen_backend_epilogue(codeblock_t *block) +{ + 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); +} + +#endif diff --git a/src/codegen_backend_arm64.h b/src/codegen_backend_arm64.h new file mode 100644 index 0000000..3263aa1 --- /dev/null +++ b/src/codegen_backend_arm64.h @@ -0,0 +1,31 @@ +#include "codegen_backend_arm64_defs.h" + +#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_MAX 0x3c0 + + +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); + +uint32_t host_arm64_find_imm(uint32_t data); \ No newline at end of file diff --git a/src/codegen_backend_arm64_defs.h b/src/codegen_backend_arm64_defs.h new file mode 100644 index 0000000..2df1e9f --- /dev/null +++ b/src/codegen_backend_arm64_defs.h @@ -0,0 +1,135 @@ +#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_WZR 31 + +#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_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_XSP 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 + +#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_quad; +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_quad; +extern void *codegen_mem_store_single; +extern void *codegen_mem_store_double; + +extern void *codegen_fp_round; +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_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 new file mode 100644 index 0000000..552665a --- /dev/null +++ b/src/codegen_backend_arm64_ops.c @@ -0,0 +1,1382 @@ +#ifdef __aarch64__ + +#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" + + +#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 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 CSEL_COND(cond) ((cond) << 12) + +#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) +#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_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) +#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) +#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) +#define OPCODE_STR_IMM_F64 (0x3f4 << 22) +#define OPCODE_STRB_IMM (0x0e4 << 22) +#define OPCODE_STRH_IMM (0x1e4 << 22) +#define OPCODE_UBFX (0x14c << 22) + +#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) +#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) +#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) +#define OPCODE_SUBX_LSL (0x658 << 21) + +#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) +#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_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) +#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_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) +#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_MSR_FPCR (0xd51b4400) +#define OPCODE_MUL_V4H (0x0e609c00) +#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) +#define OPCODE_SCVTF_V2S (0x0e21d800) +#define OPCODE_SQADD_V8B (0x0e200c00) +#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 (0x0f005400) +#define OPCODE_SHL_VQ (0x4f005400) +#define OPCODE_SHRN (0x0f008400) +#define OPCODE_SMULL_V4S_4H (0x0e60c000) +#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) +#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 OPCODE_UQXTN_V8B_8H (0x2e214800) +#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) +#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) +#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 IMM_LOGICAL(imm) ((imm) << 10) + +#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) + +#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) + +#define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) +#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) + +#define DUP_ELEMENT(element) ((element) << 19) + +/*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; +} + +/*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; +} + +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; +} + +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, 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]; + + 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) + 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_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)); +} +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_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)); +} +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)); +} +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)); +} + +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)); +} + +void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + 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) | IMM_LOGICAL(imm_encoding)); + } + 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_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) +{ + 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) | IMM_LOGICAL(imm_encoding)); + } + 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_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_B(codeblock_t *block, void *dest) +{ + 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); + 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)); +} + +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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 |= OFFSET26(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); + 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; + + 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); + 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) +{ + 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)) + { + 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_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_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_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) +{ + 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) | IMM_LOGICAL(imm_encoding)); + } + 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_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_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)); +} +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) +{ + 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)); +} +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_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) +{ + codegen_addlong(block, OPCODE_FMOV_D_D | Rd(dst_reg) | Rn(src_reg)); +} +void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg) +{ + 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_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) +{ + 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_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) +{ + 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_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_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_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) +{ + 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)); +} + +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_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)); +} + +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_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 || shift) + 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_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) +{ + 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) + 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; + + 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_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); +} + +void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +{ + 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) | IMM_LOGICAL(imm_encoding)); + } + 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_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) +{ + 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)); +} + +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_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)); +} + +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) + 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) +{ + 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)); +} +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)); +} +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)); +} +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)); +} + +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_V4H_4S(codeblock_t *block, int dst_reg, int 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) +{ + 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, 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, 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, int 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) +{ + 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) +{ + 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) +{ + 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_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)); +} + +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_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)); +} + +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_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)); +} +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)); +} +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)); +} + +uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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_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, int 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, int 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, int 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) +{ + 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) +{ + 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) +{ + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); + 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)) + 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 diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h new file mode 100644 index 0000000..2a514ed --- /dev/null +++ b/src/codegen_backend_arm64_ops.h @@ -0,0 +1,264 @@ +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); +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); + +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_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); + +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); + +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_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_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); + +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_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_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); + +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); +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); + +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_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_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); +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); + +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_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); +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); +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); + +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); +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); + +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_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); +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); + +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); + +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); +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_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 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); + +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); +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); +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); +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); + +#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_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); +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); + + +#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)) + + +void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); + +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 new file mode 100644 index 0000000..0cad9bb --- /dev/null +++ b/src/codegen_backend_arm64_uops.c @@ -0,0 +1,3367 @@ +#ifdef __aarch64__ + +#include "ibm.h" +#include "x86.h" +#include "x87.h" +#include "386_common.h" +#include "codegen.h" +#include "codegen_backend.h" +#include "codegen_backend_arm64_defs.h" +#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) +#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) +#define REG_IS_Q(size) (size == IREG_SIZE_Q) + +static int codegen_ADD(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)) + { + 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) +{ + 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)) + { + 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)) + { + 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)) + { + 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; +} + +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(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_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); + } + 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 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); + + return 0; +} +static int codegen_AND_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_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_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); + } + else + fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + 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); + + 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); + host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); + + 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_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_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); + 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_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); + 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_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); + 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, codegen_exit_rout); + + host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); + + 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, codegen_exit_rout); + + 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) +{ + host_arm64_jump(block, (uintptr_t)uop->p); + + 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); + + 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_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_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)codegen_exit_rout); + + 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)codegen_exit_rout); + 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 (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); + } + 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 if (REG_IS_Q(dest_size)) + { + host_arm64_call(block, codegen_mem_load_quad); + } + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + 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); + } + 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); + } + else if (REG_IS_Q(dest_size)) + { + host_arm64_FMOV_D_D(block, dest_reg, REG_V_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_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)codegen_exit_rout); + 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)codegen_exit_rout); + 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) +{ + 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)codegen_exit_rout); + + 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 (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); + 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 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->src_reg_c_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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); + 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 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); + + return 0; +} +static int codegen_MOV_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_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 & 0xffff); + } + else if (REG_IS_B(dest_size)) + { + 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 & 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + else + fatal("MOV_IMM %x\n", uop->dest_reg_a_real); + + return 0; +} +static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_arm64_MOVX_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_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); + 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_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); + } + 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 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); + + 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 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); + + 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)) + { + 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); + 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_write_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_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_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); + 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_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); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + 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) + { + 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) +{ + 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; +} + +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_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + 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); + + 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_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); + + 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, REG_V_TEMP, src_reg_b); + 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); + + 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_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); + + 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_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_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); + + 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_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); + + 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_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); + + 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_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); + + 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_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); + + 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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); + + 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_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); + + 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_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); + + 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); + 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_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); + + 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_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_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_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_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); + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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); + 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_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_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_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); + + 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_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); + + 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_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); + + 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_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); + + 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_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); + + 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_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); + + 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); + 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); + + 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; +} + +static int codegen_SUB(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)) + { + 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) +{ + 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_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); + 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_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); + } + 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) +{ + 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; +} + +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, + + [UOP_JMP & UOP_MASK] = codegen_JMP, + + [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, + [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_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_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, + [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, + [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_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, + + [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, + [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, + + [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, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [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, + + [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_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_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, + + [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, + [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_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, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP +}; + +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_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)) + 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_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_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)) + 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_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +{ + 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); + 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_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); + 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_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); + 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) +{ + 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_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)) + 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_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_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); + host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); +} +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_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); + 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) +{ + 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); + 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) +{ + 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"); +} + +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_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_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_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_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_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_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_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_XSP, stack_offset); +} + +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + host_arm64_branch_set_offset(p, &block_write_data[block_pos]); +} +#endif diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h new file mode 100644 index 0000000..2f50129 --- /dev/null +++ b/src/codegen_backend_arm_defs.h @@ -0,0 +1,89 @@ +#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_HOST_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_TEMP REG_R3 +#define REG_TEMP2 REG_R2 + +#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_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) +#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_HOST_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) + +#define CODEGEN_HOST_REGS 7 +#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_quad; +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_quad; +extern void *codegen_mem_store_single; +extern void *codegen_mem_store_double; + +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 new file mode 100644 index 0000000..9be45f2 --- /dev/null +++ b/src/codegen_backend_arm_ops.c @@ -0,0 +1,1272 @@ +#ifdef __ARM_EABI__ + +#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" + +#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) + +#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_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) +#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_BX 0xe12fff10 +#define OPCODE_LDRH_IMM 0xe1d000b0 +#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 +#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 +#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 +#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 0xf3bb0600 +#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 +#define OPCODE_VMOV_S_32 0xee000a10 +#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 +#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 +#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 +#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_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 +#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 + +#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_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) + +#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)) + +#define LDRH_IMM(imm) (((imm) & 0xf) | (((imm) & 0xf0) << 4)) +#define STRH_IMM(imm) LDRH_IMM(imm) + +#define VSHIFT_IMM(shift) ((shift) << 16) + +#define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) + +#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, 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; + + /*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); +} + +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) + 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 + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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_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) +{ + 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 + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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_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_B(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_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)); +} + +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)); +} +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; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_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_BL_r1(codeblock_t *block, uintptr_t dest_addr) +{ + uint32_t offset; + + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t)&block_write_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)); +} + +uint32_t *host_arm_BCC_(codeblock_t *block) +{ + codegen_addlong(block, COND_CC | OPCODE_B); + + 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_write_data[block_pos - 4]; +} +uint32_t *host_arm_BEQ_(codeblock_t *block) +{ + codegen_addlong(block, COND_EQ | OPCODE_B); + + 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_write_data[block_pos - 4]; +} +uint32_t *host_arm_BGT_(codeblock_t *block) +{ + codegen_addlong(block, COND_GT | OPCODE_B); + + 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_write_data[block_pos - 4]; +} +uint32_t *host_arm_BLE_(codeblock_t *block) +{ + codegen_addlong(block, COND_LE | OPCODE_B); + + 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_write_data[block_pos - 4]; +} +uint32_t *host_arm_BLT_(codeblock_t *block) +{ + codegen_addlong(block, COND_LT | OPCODE_B); + + 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_write_data[block_pos - 4]; +} +uint32_t *host_arm_BNE_(codeblock_t *block) +{ + codegen_addlong(block, COND_NE | OPCODE_B); + + 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_write_data[block_pos - 4]; +} +uint32_t *host_arm_BVC_(codeblock_t *block) +{ + codegen_addlong(block, COND_VC | OPCODE_B); + + 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_write_data[block_pos - 4]; +} + +void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) +{ + 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); + + codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset)); +} +void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) +{ + 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); + + 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; + + 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 + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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 + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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 + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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_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)); +} + +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_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_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) +{ + 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_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 | 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_cond(block, cond, dst_reg, src_reg, REG_TEMP, 0); + } +} + +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 | 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)); +} + +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_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)); +} + +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 + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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_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; + + if (get_arm_imm(imm, &arm_imm)) + { + codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm); + } + else + { + host_arm_MOV_IMM(block, REG_TEMP, imm); + 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)); +} + +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)); +} +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)); +} +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)); +} +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)); +} + +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)); +} +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_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)); +} +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)); +} +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)); +} +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)); +} +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)); +} +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)); +} +void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) +{ + if ((offset > 1020) || (offset & 3)) + 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_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_VMOV_F32_ONE(codeblock_t *block, int dst_reg) +{ + codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(dst_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_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)); +} +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_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)); +} + +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) +{ + 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_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 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 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 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_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_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-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_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-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_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-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_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-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_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-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_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_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) +{ + if ((offset > 1020) || (offset & 3)) + 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) +{ + 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)); +} +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)); +} + +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)); +} +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 new file mode 100644 index 0000000..7627f51 --- /dev/null +++ b/src/codegen_backend_arm_ops.h @@ -0,0 +1,252 @@ +#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); +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); +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); +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_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); +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); +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_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); +#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_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); + +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); + +#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_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); + +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_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); +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); + +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); + +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); +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); + +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); + +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); + +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); + +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); +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); +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_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); +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_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_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); +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 new file mode 100644 index 0000000..12c2eb9 --- /dev/null +++ b/src/codegen_backend_arm_uops.c @@ -0,0 +1,3499 @@ +#ifdef __ARM_EABI__ + +#include +#include "ibm.h" +#include "x86.h" +#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" +#include "codegen_ir_defs.h" + +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; +} + +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); + host_arm_BLX(block, REG_R3); +} + +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) +#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) +{ + 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)) + { + 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)) + { + 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) + { + 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); + 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); +// 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)) + { + 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)) + { + 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) + { + 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) +{ + 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) +{ + 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_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); + } + 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 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); + + return 0; +} +static int codegen_AND_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_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 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); + + 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) +{ + 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); + 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); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + + 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, (uintptr_t)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_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_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); + 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_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); + 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_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); + 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)codegen_exit_rout); + + *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; + + 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)codegen_exit_rout); + + *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); + 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) +{ + host_arm_B(block, (uintptr_t)uop->p); + + 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); + return 0; +} +static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ + 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) +{ + 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) +{ + host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); + 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)codegen_exit_rout); + + 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, (uintptr_t)codegen_mem_load_byte); + } + else if (REG_IS_W(dest_size)) + { + host_arm_BL(block, (uintptr_t)codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + 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, (uintptr_t)codegen_exit_rout); + 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 (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); + } + else if (REG_IS_W(dest_size)) + { + host_arm_BL(block, (uintptr_t)codegen_mem_load_word); + } + else if (REG_IS_L(dest_size)) + { + 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); + 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); + } + 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); + } + else if (REG_IS_Q(dest_size)) + { + host_arm_VMOV_D_D(block, dest_reg, REG_D_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_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)codegen_exit_rout); + 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)codegen_exit_rout); + 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) +{ + 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, (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, (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, (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, (uintptr_t)codegen_exit_rout); + + 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 (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); + 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, (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, (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, (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); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + + 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, (uintptr_t)codegen_mem_store_byte); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + + 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, (uintptr_t)codegen_mem_store_word); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + + 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, (uintptr_t)codegen_mem_store_long); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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)codegen_exit_rout); + + 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); + 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 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); + + return 0; +} + +static int codegen_MOV_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_L(dest_size)) + { + host_arm_MOV_IMM(block, dest_reg, uop->imm_data); + } + 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; +} +static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, uop->dest_reg_a_real, (uintptr_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_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); + 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_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); + } + else 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 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); + + 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); + 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 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); + + 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_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); + + 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_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); + 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_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); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) + { + 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) + { + 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) +{ + 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; +} + +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_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 + 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_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_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 + 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_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_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 + 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); + 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_F32_S32(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); + 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_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); + + 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_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_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); + + 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_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_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); + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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 == 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); + } + 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); + 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_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_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_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); + 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); + + 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; +} + +static int codegen_SUB(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)) + { + 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_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 + 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) +{ + 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_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); + 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_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); + } + 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) +{ + 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; +} + +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, + + [UOP_JMP & UOP_MASK] = codegen_JMP, + + [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, + [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_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_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, + [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, + [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_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, + + [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, + [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, + + [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, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [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, + + [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_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_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, + + [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, + [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_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, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP +}; + +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)) + 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)) + 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_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); +} +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); + 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) +{ + 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_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)) + 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_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); + 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_st_64(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_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) +{ + 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"); +} + +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) + host_arm_LDR_IMM(block, host_reg, REG_HOST_SP, stack_offset); + 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); +} +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) +{ + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_STR_IMM(block, host_reg, REG_HOST_SP, stack_offset); + 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); +} + +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + *(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 new file mode 100644 index 0000000..f1dcd86 --- /dev/null +++ b/src/codegen_backend_x86-64.c @@ -0,0 +1,376 @@ +#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.h" +#include "codegen_backend_x86-64_ops_sse.h" +#include "codegen_reg.h" +#include "x86.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +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; + +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_gpf_rout; +void *codegen_exit_rout; + +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_EAX, + REG_EBX, + 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 build_load_routine(codeblock_t *block, int size, int is_float) +{ + 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 readmembl + 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 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 2 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); + 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) + 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); + host_x86_RET(block); + + *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_write_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 && !is_float) + { + host_x86_CALL(block, (void *)readmembl); + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + } + 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 && !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) + { + 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 + 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); +} + +static void build_store_routine(codeblock_t *block, int size, int is_float) +{ + 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 writemembl + 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 && !is_float) + host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + 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) + 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); + host_x86_RET(block); + + *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_write_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, 0x28); + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data + 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 + 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 + 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 *)writemembl); + else if (size == 2) + 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, 0x28); +#else + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8); +#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); +} + +static void build_loadstore_routines(codeblock_t *block) +{ + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + 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]; + build_load_routine(block, 8, 1); + + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + 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); +} + +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 *)); + + 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].pc = BLOCK_PC_INVALID; + +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); + + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + 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]); + + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; +#if WIN64 + 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); + 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_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); + 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( + "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) +{ + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); +} + +void codegen_backend_prologue(codeblock_t *block) +{ + 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_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, 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_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); + 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 new file mode 100644 index 0000000..150c8c8 --- /dev/null +++ b/src/codegen_backend_x86-64.h @@ -0,0 +1,12 @@ +#include "codegen_backend_x86-64_defs.h" + +#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_MAX 0x3c0 diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h new file mode 100644 index 0000000..95a5294 --- /dev/null +++ b/src/codegen_backend_x86-64_defs.h @@ -0,0 +1,65 @@ +#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 +#define REG_EBX 3 +#define REG_ESP 4 +#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 + +#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_load_quad; +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_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_ops.c b/src/codegen_backend_x86-64_ops.c new file mode 100644 index 0000000..48acb73 --- /dev/null +++ b/src/codegen_backend_x86-64_ops.c @@ -0,0 +1,1729 @@ +#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.h" +#include "codegen_backend_x86-64_ops_helpers.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_ROL 0x00 +#define RM_OP_ROR 0x08 +#define RM_OP_SHL 0x20 +#define RM_OP_SHR 0x28 +#define RM_OP_SAR 0x38 + +static inline void call(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff; + + codegen_alloc_bytes(block, 5); + diff = func - (uintptr_t)&block_write_data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + codegen_addbyte(block, 0xE8); /*CALL*/ + codegen_addlong(block, (uint32_t)diff); + } + 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*/ + } +} + +static inline void jmp(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff; + + codegen_alloc_bytes(block, 5); + diff = func - (uintptr_t)&block_write_data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uint32_t)diff); + } + 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*/ + } +} + +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\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, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\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); + } +} +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_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); +} +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*ADD dst_reg, src_reg*/ +} +void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*ADD dst_reg, src_reg*/ +} +void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*ADD dst_reg, src_reg*/ +} + +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_AND8_REG_IMM - dst_reg & 8\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, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_AND16_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_AND32_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*AND dst_reg, src_reg*/ +} +void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*AND dst_reg, src_reg*/ +} +void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*AND dst_reg, src_reg*/ +} + +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_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); + } +} +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); + } +} +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_JMP(codeblock_t *block, void *p) +{ + jmp(block, (uintptr_t)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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_write_data[block_pos-4]; +} + +void host_x86_LAHF(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + +void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + 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)); +} +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_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_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_alloc_bytes(block, 4); + 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_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); + } +} +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_alloc_bytes(block, 7); + 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_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); + } +} + +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_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); + } +} +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_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); + } + 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); + + if (src_reg & 8) + fatal("host_x86_MOV32_ABS_REG - bad reg\n"); + + 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); + } + else + { + 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); + } +} +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_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); + } +} + +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_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); + } +} + +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_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*/ +} + +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_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); + } + 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); + + if (dst_reg & 8) + fatal("host_x86_MOV16_REG_ABS reg & 8\n"); + + 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); + } + 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); + + if (dst_reg & 8) + fatal("host_x86_MOV32_REG_ABS reg & 8\n"); + + 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); + } +} +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_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); + } + 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) +{ + 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_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); + } +} + +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_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]*/ +} + +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"); + 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 + 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_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); +} +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_MOV32_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + 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); +} +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_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); +} + +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_MOV32_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) + { + 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); +} +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_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); +} + +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); +} +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); +} + +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); + } +} + +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) +{ + 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) +{ + 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)); +} + +void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + 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); + } +} + +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*/ +} + +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_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); +} + +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*/ +} + +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); + +// 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_alloc_bytes(block, 5); + codegen_addbyte(block, 0x44); + 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 + { + 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) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x90); /*NOP*/ +} + +void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\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, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*OR dst_reg, src_reg*/ +} +void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*OR dst_reg, src_reg*/ +} +void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*OR dst_reg, src_reg*/ +} + +void host_x86_POP(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + { + 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) + { + 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*/ +} + +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) + 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*/ +} + +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*/ +} + +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*/ +} + +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*/ +} + +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*/ +} + +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_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\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, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\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); + } +} +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_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); +} +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*SUB dst_reg, src_reg*/ +} +void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*SUB dst_reg, src_reg*/ +} +void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*SUB dst_reg, src_reg*/ +} + +#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_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) +{ + if (dst_reg & 8) + 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); + } +} + +void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\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, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\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); + } +} +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*XOR dst_reg, src_reg*/ +} +void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 7) << 3)); /*XOR dst_reg, src_reg*/ +} +void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + 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 & 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 new file mode 100644 index 0000000..3cd86fb --- /dev/null +++ b/src/codegen_backend_x86-64_ops.h @@ -0,0 +1,193 @@ +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); +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_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); +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); + +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_JS_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_LAHF(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_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); + +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); +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); + +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_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); +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_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); + +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); + +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); +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_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_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); + +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, 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); +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_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_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); +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_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 new file mode 100644 index 0000000..729e4fd --- /dev/null +++ b/src/codegen_backend_x86-64_uops.c @@ -0,0 +1,3144 @@ +#ifdef __amd64__ + +#include "ibm.h" +#include "x86.h" +#include "x87.h" +#include "386_common.h" +#include "codegen.h" +#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) +#define STACK_ARG1 (4) +#define STACK_ARG2 (8) +#define STACK_ARG3 (12) + +#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) +#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) +{ + 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_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + else + 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, 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, 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; +} + +static int codegen_ADD_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 (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, 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, 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, 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; +} + +static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + if (!uop->imm_data) + { + 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 + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); +#endif + return 0; +} + +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_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); + 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, 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, 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; +} + +static int codegen_AND_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 (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + 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, 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, 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; +} + +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); + } +#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; +} + +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); + 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); + + return 0; +} + +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, codegen_exit_rout); + + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +#endif + 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); + } +#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; +} +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); + } +#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; +} + +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); + 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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + 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); + 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; +} + +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_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) +{ + 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); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + 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); + 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) +{ + 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_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_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); + } +#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) +{ + 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_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) +{ + 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_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_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); + } +#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; +} + +static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + 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_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); +#else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +#endif + host_x86_CALL(block, x86_int); + 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; +} +static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + 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_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); +#else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +#endif + host_x86_CALL(block, x86_int); + 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); + 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); + + 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_MOVZX_REG_32_16(block, REG_ECX, src_reg); +#else + 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; +} + +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) +{ +#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; +} + +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); +#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, codegen_exit_rout); + + 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); + } +#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)) + { + 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 (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); + } + 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 if (REG_IS_Q(dest_size)) + { + 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)) + { + 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); + } + else if (REG_IS_Q(dest_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_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); + +#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, 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); + 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); + +#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, 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); + 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) +{ + 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); + } +#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); + + 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, codegen_exit_rout); + + 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, codegen_exit_rout); + + 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, codegen_exit_rout); + + 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 (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); + 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 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); + } +#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); + + 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); + +#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, 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, codegen_exit_rout); + + 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); + +#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, 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, codegen_exit_rout); + + 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); + 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 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + 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); + } +#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) +{ + 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_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); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + 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 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); + } +#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) +{ + 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); + } +#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) +{ + 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_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + 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 = (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; +} + +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); + 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_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); + 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, 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_OR8_REG_REG(block, dest_reg, 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) +{ + 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, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + 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, 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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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_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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); +#endif + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +static int codegen_SUB(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 (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + 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, 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, 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) +{ + 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, 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, 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, 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; +} + +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); + } +#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; +} +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); + } +#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; +} + +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_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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + 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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + 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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_XOR8_REG_REG(block, dest_reg, 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) +{ + 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, uop->imm_data); + } + else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) + { + 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, 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; +} + +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, + + [UOP_JMP & UOP_MASK] = codegen_JMP, + + [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, + [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_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_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, + [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, + [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_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_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, + + [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, + [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, + + [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, + [UOP_FDIV & UOP_MASK] = codegen_FDIV, + [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, + + [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_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_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, + + [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, + [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_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, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP +}; + +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); +} +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_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); +} +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_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) +{ + 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_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) +{ + 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_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_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); +} +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); +} +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_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) +{ + 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_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) +{ + 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_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_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); +} +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_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); +} + +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_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_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); +} + +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + *(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 new file mode 100644 index 0000000..1700eb0 --- /dev/null +++ b/src/codegen_backend_x86.c @@ -0,0 +1,366 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#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" +#include "codegen_backend_x86_ops_sse.h" +#include "codegen_reg.h" +#include "x86.h" + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#include +#endif + +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; + +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_gpf_rout; +void *codegen_exit_rout; + +int codegen_host_reg_list[CODEGEN_HOST_REGS] = +{ + REG_EAX, + REG_EBX, + REG_EDX +}; + +int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = +{ + REG_XMM0, + REG_XMM1, + REG_XMM2, + REG_XMM3, + REG_XMM4, + REG_XMM5 +}; + +static void build_load_routine(codeblock_t *block, int size, int is_float) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset = NULL; + + /*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 readmembl + 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 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); + 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) + 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); + host_x86_RET(block); + + *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_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); + if (size == 1) + host_x86_CALL(block, (void *)readmembl); + else if (size == 2) + 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 && !is_float) + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + else if (size == 2 && !is_float) + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + 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) + { + 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); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; +} + +static void build_store_routine(codeblock_t *block, int size, int is_float) +{ + uint8_t *branch_offset; + uint8_t *misaligned_offset = NULL; + + /*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 writemembl + 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 && !is_float) + host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + 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) + 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); + host_x86_RET(block); + + *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_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); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + if (size == 8) + { + host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); + host_x86_SUB32_REG_IMM(block, REG_ESP, 8); + } + host_x86_PUSH(block, REG_EDI); + if (size == 1) + host_x86_CALL(block, (void *)writemembl); + else if (size == 2) + 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) + 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); + 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, 0); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + 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]; + build_load_routine(block, 8, 1); + + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + 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); +} + +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 +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, 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)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + 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].pc = BLOCK_PC_INVALID; + +// 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_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + 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, 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_write_data = NULL; + + cpu_state.old_fp_control = 0; + asm( + "fstcw %0\n" + "stmxcsr %1\n" + : "=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) +{ + /*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 = 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, 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, 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, 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 new file mode 100644 index 0000000..db521a7 --- /dev/null +++ b/src/codegen_backend_x86.h @@ -0,0 +1,12 @@ +#include "codegen_backend_x86_defs.h" + +#define BLOCK_SIZE 0x10000 +#define BLOCK_MASK 0xffff +#define BLOCK_START 0 + +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff + +#define HASH(l) ((l) & 0x1ffff) + +#define BLOCK_MAX 0x3c0 diff --git a/src/codegen_backend_x86_defs.h b/src/codegen_backend_x86_defs.h new file mode 100644 index 0000000..8999ca3 --- /dev/null +++ b/src/codegen_backend_x86_defs.h @@ -0,0 +1,50 @@ +#ifndef _CODEGEN_BACKEND_X86_DEFS_H_ +#define _CODEGEN_BACKEND_X86_DEFS_H_ + +#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 + +#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 REG_XMM_TEMP2 REG_XMM6 + +#define CODEGEN_HOST_REGS 3 +#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_quad; +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_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) +#define STACK_ARG3 (12) + +#endif diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c new file mode 100644 index 0000000..41ab522 --- /dev/null +++ b/src/codegen_backend_x86_ops.c @@ -0,0 +1,1291 @@ +#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.h" +#include "codegen_backend_x86_ops_helpers.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_ROL 0x00 +#define RM_OP_ROR 0x08 +#define RM_OP_SHL 0x20 +#define RM_OP_SHR 0x28 +#define RM_OP_SAR 0x38 + +void host_x86_ADD32_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_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); + } +} + +void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + 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, uint16_t imm_data) +{ + 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); + } +} +void host_x86_ADD32_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_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); + } +} + +void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + 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) +{ + codegen_alloc_bytes(block, 3); + 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) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ +} + +void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + 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, uint16_t imm_data) +{ + 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); + } +} +void host_x86_AND32_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_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); + } +} + +void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + 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) +{ + codegen_alloc_bytes(block, 3); + 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) +{ + codegen_alloc_bytes(block, 2); + 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) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe8); /*CALL*/ + 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); + } +} +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); + } +} + +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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_write_data[block_pos-4]; +} + +void host_x86_LAHF(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + +void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + 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_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_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); + } +} +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_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); + } +} + +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_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); + } +} +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_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); + } +} +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_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); + } +} + +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_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); + } +} + +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*/ +} + +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_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); + } +} +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_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); + } +} +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_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); + } +} + +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); +} + +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_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); + } +} + +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]*/ +} + +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_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); +} +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_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); +} + +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_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); +} +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_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); +} + +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); + } +} +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); + } +} + +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)); +} + +void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + 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); + } +} + +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*/ +} + +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); + + 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); + } +} +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_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); + } +} + +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_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + 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) +{ + codegen_alloc_bytes(block, 3); + 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) +{ + codegen_alloc_bytes(block, 2); + 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, uint8_t imm_data) +{ + 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, uint16_t imm_data) +{ + 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); + } +} +void host_x86_OR32_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_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); + } +} + +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*/ +} + +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) +{ + 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_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + 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, uint16_t imm_data) +{ + 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); + } +} +void host_x86_SUB32_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_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); + } +} + +void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + 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) +{ + codegen_alloc_bytes(block, 3); + 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) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, 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_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); + } +} + +void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + 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) +{ + codegen_alloc_bytes(block, 3); + 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) +{ + codegen_alloc_bytes(block, 2); + 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, uint8_t imm_data) +{ + 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, uint16_t imm_data) +{ + 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); + } +} +void host_x86_XOR32_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_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); + } +} + +#endif diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h new file mode 100644 index 0000000..94f526c --- /dev/null +++ b/src/codegen_backend_x86_ops.h @@ -0,0 +1,192 @@ +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, 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); +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_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); +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); + +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_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); + +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); +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_LAHF(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_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); + +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); +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); + +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_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); + +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); + +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, 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_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_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); + +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, 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); +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_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); +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, 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_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 new file mode 100644 index 0000000..c09512e --- /dev/null +++ b/src/codegen_backend_x86_uops.c @@ -0,0 +1,3139 @@ +#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 + +#include "ibm.h" +#include "x86.h" +#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_backend_x86_ops_fpu.h" +#include "codegen_backend_x86_ops_sse.h" +#include "codegen_ir_defs.h" + +/*void codegen_debug() +{ + 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) +#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) +{ + 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_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); + else + 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, 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, 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; +} + +static int codegen_ADD_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_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); + else + 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, 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, 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; +} + +static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + if (!uop->imm_data) + { + 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 + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); +#endif + return 0; +} + +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_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); + 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, 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, 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; +} + +static int codegen_AND_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_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, 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, 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; +} + +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); + } +#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; +} + +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); +#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); + + return 0; +} + +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, codegen_exit_rout); +// host_x86_CALL(block, codegen_debug); + + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +#endif + 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); + } +#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; +} +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); + } +#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; +} + +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); + 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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} +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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + 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); + 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; +} + +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_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) +{ + 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); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + 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); + 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) +{ + 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_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_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); + } +#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) +{ + 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_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) +{ + 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_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_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); + } +#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; +} + +static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + 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_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, codegen_exit_rout); + *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) +{ + 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_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, 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); + 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); + + 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) +{ + 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); + } +#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; +} + +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_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); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); + + 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); + } +#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)) + { + 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 (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); + } + 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 if (REG_IS_Q(dest_size)) + { + 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)) + { + 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); + } + else if (REG_IS_Q(dest_size)) + { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_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); +#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, 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); + 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); +#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, 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); + 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) +{ + 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); + } +#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); + + 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 (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); + 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 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); + } +#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); + + 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, codegen_exit_rout); + + 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, codegen_exit_rout); + + 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, codegen_exit_rout); + + 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); +#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, 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, codegen_exit_rout); + + 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); +#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, 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, codegen_exit_rout); + + 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); + 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 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + 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); + } +#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) +{ + 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_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); + } + else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) + { + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + 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 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); + } +#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) +{ + 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); + } +#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) +{ + 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_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + 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.*/ + 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 = (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; +} + +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); + 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_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); + 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, 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_OR8_REG_REG(block, dest_reg, 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) +{ + 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); + + if (REG_IS_L(dest_size) && dest_reg == src_reg) + { + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_W(dest_size) && dest_reg == src_reg) + { + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); + } + else if (REG_IS_B(dest_size) && dest_reg == src_reg) + { + host_x86_OR8_REG_IMM(block, dest_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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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_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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); +#endif + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#ifdef RECOMPILER_DEBUG + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +#endif + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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; +} + +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); + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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); + } +#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) +{ + 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; +} + +static int codegen_SUB(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 (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, 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, 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, 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) +{ + 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, 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, 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, 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; +} + +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); + } +#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; +} +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); + } +#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; +} + +static int codegen_XOR(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_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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + 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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + 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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_XOR8_REG_REG(block, dest_reg, 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) +{ + 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) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); + } + 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, uop->imm_data); + } + 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, 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; +} + +#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, + [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_JMP_DEST & UOP_MASK] = codegen_JMP_DEST, + + [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, + [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_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_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, + [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, + [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_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, + + [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, + [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, + + [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, + [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, + [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + + [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_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_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, + + [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, + [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_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, + + [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP, + +#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) +{ + 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); +} +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); +} +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_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) +{ + 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_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) +{ + 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_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_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); +} +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); + + 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_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) +{ + 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_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) +{ + 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_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_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); +} +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); +} +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_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); +} + +void codegen_set_jump_dest(codeblock_t *block, void *p) +{ + *(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 new file mode 100644 index 0000000..d7e6157 --- /dev/null +++ b/src/codegen_ir.c @@ -0,0 +1,190 @@ +#include "ibm.h" +#include "codegen.h" +#include "codegen_allocator.h" +#include "codegen_backend.h" +#include "codegen_ir.h" +#include "codegen_reg.h" + +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() +{ + 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, 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) +{ + 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; + + 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++) + { + 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); + block_pos = 0; + 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); + + if (uop->type & UOP_TYPE_BARRIER) + codegen_reg_flush_invalidate(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_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); + if (uop->src_reg_a.reg != IREG_INVALID) + { + 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, 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->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); + } + } + + if (!uop_handlers[uop->type & UOP_MASK]) + 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) + { + 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); + block_write_data = NULL; +// if (has_ea) +// fatal("IR compilation complete\n"); +} diff --git a/src/codegen_ir.h b/src/codegen_ir.h new file mode 100644 index 0000000..6274816 --- /dev/null +++ b/src/codegen_ir.h @@ -0,0 +1,6 @@ +#include "codegen_ir_defs.h" + +ir_data_t *codegen_ir_init(); + +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_ir_defs.h b/src/codegen_ir_defs.h new file mode 100644 index 0000000..76f4979 --- /dev/null +++ b/src/codegen_ir_defs.h @@ -0,0 +1,810 @@ +#ifndef _CODEGEN_IR_DEFS_ +#define _CODEGEN_IR_DEFS_ + +#include "codegen_reg.h" + +#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. + 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*/ +#define UOP_TYPE_PARAMS_POINTER (1 << 29) +/*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) +#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 | 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) +#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_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_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*/ +#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*/ +#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_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_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_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*/ +#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) +/*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]*/ +#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_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_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) +/*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) +/*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) +/*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) + +/*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) +/*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) +/*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) +/*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) +/*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) +/*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) +/*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) +/*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) + +/*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_INVALID 0xff + +#define UOP_MASK 0xffff + +typedef struct uop_t +{ + uint32_t type; + 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, src_reg_c_real; + int jump_dest_uop; + int jump_list_next; + void *jump_dest; + uint32_t pc; +} uop_t; + +#define UOP_NR_MAX 4096 + +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) +{ + 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 = 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->pc = cpu_state.oldpc; + + uop->jump_dest_uop = -1; + uop->jump_list_next = -1; + + if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) + codegen_reg_mark_as_required(); + + return uop; +} + +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(uint32_t uop_type, ir_data_t *ir) +{ + uop_t *uop = uop_alloc(ir, uop_type); + + 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, uop_type); + + 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_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_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) +{ + uop_t *uop = uop_alloc(ir, uop_type); + + uop->type = uop_type; + 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_type); + + uop->type = uop_type; + 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_type); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_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_type); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + 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_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, 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_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, 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_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, 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_type); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_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_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); + + 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, 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->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_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_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_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, uop_type); + + 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_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_type; + uop->p = 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_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, uop_type); + + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; + 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_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) + +#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_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) +#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_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) +#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_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) +#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_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) + +#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) + +#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) + +#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_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) +#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) + +#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_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_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) + +#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) +#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_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) + +#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); +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); +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_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); +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_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); + +#endif diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 68da1ed..5c63795 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -1,129 +1,150 @@ #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_ir.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_3dnow.h" #include "codegen_ops_arith.h" -#include "codegen_ops_fpu.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" #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" -#include "codegen_ops_mmx.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_pack.h" +#include "codegen_ops_mmx_shift.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 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, -/*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, +/*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*/ 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_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, +/*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, 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, -/*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, +/*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, 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*/ +/* 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, -/*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, +/*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*/ 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_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, +/*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, 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, -/*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 +/*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, ropCMC, ropF6, ropF7_32, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, 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 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_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, +/*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, 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, 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*/ +/*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_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, +/*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, 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, 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_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, ropEMMS, 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*/ 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, +/*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, - - /*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 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, @@ -145,7 +166,7 @@ RecompOpFn recomp_opcodes_d8[512] = /*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 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, @@ -170,93 +191,93 @@ RecompOpFn recomp_opcodes_d8[512] = 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 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, +/*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, 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, +/*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, 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, +/*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, 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, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, +/*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*/ +/* 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, +/*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, 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, +/*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, 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, +/*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, 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, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, +/*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] = { /*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, +/* 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*/ 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*/ 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, +/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*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*/ 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, +/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*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*/ 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, +/* 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*/ 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*/ 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, +/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*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*/ 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, +/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, +/*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, }; @@ -264,7 +285,7 @@ RecompOpFn recomp_opcodes_da[512] = 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 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, @@ -286,8 +307,8 @@ RecompOpFn recomp_opcodes_db[512] = /*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, +/* 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, @@ -311,7 +332,7 @@ RecompOpFn recomp_opcodes_db[512] = 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 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, @@ -333,7 +354,7 @@ RecompOpFn recomp_opcodes_dc[512] = /*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 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, @@ -358,68 +379,68 @@ RecompOpFn recomp_opcodes_dc[512] = 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 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, +/*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*/ 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, +/*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*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/* 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, +/*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*/ 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, +/*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, }; 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, +/* 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*/ 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*/ 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, +/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, +/*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*/ 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, +/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, +/*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, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, @@ -427,21 +448,21 @@ RecompOpFn recomp_opcodes_de[512] = /*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, +/* 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*/ 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*/ 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, +/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, +/*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*/ 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, +/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, +/*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, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, @@ -452,7 +473,7 @@ RecompOpFn recomp_opcodes_de[512] = 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 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, @@ -474,7 +495,7 @@ RecompOpFn recomp_opcodes_df[512] = /*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 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, @@ -495,97 +516,3 @@ RecompOpFn recomp_opcodes_df[512] = /*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.h b/src/codegen_ops.h index 7060238..64f3547 100644 --- a/src/codegen_ops.h +++ b/src/codegen_ops.h @@ -3,10 +3,13 @@ #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_3DNOW[256]; extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; extern RecompOpFn recomp_opcodes_da[512]; @@ -15,8 +18,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_3dnow.c b/src/codegen_ops_3dnow.c new file mode 100644 index 0000000..7a2af83 --- /dev/null +++ b/src/codegen_ops_3dnow.c @@ -0,0 +1,208 @@ +#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); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ + 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); \ + } \ + \ + codegen_mark_code_present(block, cs+op_pc+1, 1); \ + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + } + + codegen_mark_code_present(block, cs+op_pc+1, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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)); + } + + codegen_mark_code_present(block, cs+op_pc+1, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + } + + codegen_mark_code_present(block, cs+op_pc+1, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + } + + 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) +{ + 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; + 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); + } + + 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) +{ + 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; + 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); + } + + codegen_mark_code_present(block, cs+op_pc+1, 1); + 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); + + codegen_mark_code_present(block, cs+op_pc, 2); + 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); diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c new file mode 100644 index 0000000..08bb5f1 --- /dev/null +++ b/src/codegen_ops_arith.c @@ -0,0 +1,2517 @@ +#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" +#include "codegen_ops_helpers.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; + 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) +{ + 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; + 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) +{ + 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; + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + 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; + 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) +{ + 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; + 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) +{ + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + + 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; +} +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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_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_IMM(ir, IREG_flags_op, FLAGS_ADD32); + + codegen_flags_changed = 1; + 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; + 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) +{ + 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; + 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) +{ + 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; + 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; + + 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, 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_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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + 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_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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + 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_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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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)); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + 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; + 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) +{ + 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; + 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) +{ + 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; + 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) + { + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + 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; + 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) +{ + 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; + 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) +{ + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + + 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); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_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_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + 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 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)); + 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*/ + 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; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + 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)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + 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*/ + 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)); + 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*/ + 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)); + 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_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, 0); + 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); + + 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*/ + 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; + + 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); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + 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; + + 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 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; + + default: + return 0; + } + } + + 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)); + 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*/ + 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; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + 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)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + 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*/ + 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)); + 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*/ + 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)); + 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_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, 0); + 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); + 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*/ + 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); + 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*/ + 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_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); + 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_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); + 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*/ + 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*/ + 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); + 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*/ + 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); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + 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; + + default: + return 0; + } + } + + 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)); + 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*/ + 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; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + 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)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + 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*/ + 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)); + 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*/ + 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)); + 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; + + 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, 0); + 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); + + 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*/ + 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); + 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*/ + 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); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + 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); + 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); + 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); + 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*/ + 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*/ + 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); + 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*/ + 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); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + 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; + + default: + return 0; + } + } + + 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; + 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 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); + 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, 0); + 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); + + 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*/ + 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); + 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); + 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); + 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; + + 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 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; + + default: + return 0; + } + } + + 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; + 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 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); + 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, 0); + 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); + + 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*/ + 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 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); + 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; + codegen_mark_code_present(block, cs+op_pc+1, 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) +{ + codegen_mark_code_present(block, cs+op_pc, 1); + rebuild_c(ir); + + 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 57c5e8e..1338102 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -1,1028 +1,64 @@ -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; +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); - 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; +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); - 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); +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); - codegen_flags_changed = 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); +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); - 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); +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); - 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; -} +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); -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); +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); - 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); +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); - 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; -} +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_branch.c b/src/codegen_ops_branch.c new file mode 100644 index 0000000..ea9b986 --- /dev/null +++ b/src/codegen_ops_branch.c @@ -0,0 +1,1011 @@ +#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 int ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + 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 0; + + 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, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} +static int ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + 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, dest_addr); + uop_JMP(ir, codegen_exit_rout); + return 0; + + 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, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} + +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 0; + + case FLAGS_SUB8: + 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: + 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: + 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); + 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, 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 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) + { + case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: + /*Carry is always zero*/ + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + return 0; + + case FLAGS_SUB8: + 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: + 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: + 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); + 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, 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 int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) + { + 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); + } + 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 + { + 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); + } + 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); + } + return 0; +} +int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) + { + 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); + } + 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 + { + 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); + } + 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); + } + return 0; +} + +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*/ + 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: + 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: + 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: + 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: + 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 (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 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*/ + 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: + 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: + 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: + 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: + 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; + } + 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 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) + { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + 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: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + 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: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + 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); + 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, 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 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) + { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + 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: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + 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: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + 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); + 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, 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 int ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + 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, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} +static int ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + 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, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} + +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*/ + 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: + 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: + 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: + 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: + 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: + 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); + 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; + } + 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 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*/ + 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: + 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: + 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: + 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: + 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: + 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); + 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; + } + 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 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: + 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: + 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: + 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: + 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 (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 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: + 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: + 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: + 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: + 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; + } + 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) \ +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); \ + uint32_t dest_addr = op_pc + 1 + offset; \ + int ret; \ + \ + if (!(op_32 & 0x100)) \ + dest_addr &= 0xffff; \ + ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+1); \ + \ + codegen_mark_code_present(block, cs+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; \ + \ + ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+2); \ + \ + codegen_mark_code_present(block, cs+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; \ + \ + ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+4); \ + \ + codegen_mark_code_present(block, cs+op_pc, 4); \ + return ret ? dest_addr : (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); + 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, 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; +} + +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; + uint32_t ret_addr; + int jump_uop; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (((op_32 & 0x200) ? ECX : CX) != 1 && codegen_can_unroll(block, ir, op_pc+1, dest_addr)) + { + 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 + { + 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_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + + codegen_mark_code_present(block, cs+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) +{ + 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); + 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 || !flags_res_valid()) + { + 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, 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); + + 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) +{ + 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); + 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 || !flags_res_valid()) + { + 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, 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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_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_fpu_arith.c b/src/codegen_ops_fpu_arith.c new file mode 100644 index 0000000..3f05802 --- /dev/null +++ b/src/codegen_ops_fpu_arith.c @@ -0,0 +1,570 @@ +#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 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 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(block, ir); + + 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(block, 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_POP2(block, 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; + + 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 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; + + 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 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 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(block, 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(block, 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) +{ + 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 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(block, 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) +{ + 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 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; + + 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 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; +} +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(block, 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(block, ir); + + 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(block, 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_POP2(block, 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) \ +{ \ + 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 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(block, 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; \ + \ + 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 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(block, 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; \ + \ + 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) + + +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 new file mode 100644 index 0000000..60ae273 --- /dev/null +++ b/src/codegen_ops_fpu_arith.h @@ -0,0 +1,63 @@ +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); +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 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); +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 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); +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); + +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); diff --git a/src/codegen_ops_fpu_constant.c b/src/codegen_ops_fpu_constant.c new file mode 100644 index 0000000..aa264ce --- /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(block, 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(block, 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); diff --git a/src/codegen_ops_fpu_loadstore.c b/src/codegen_ops_fpu_loadstore.c new file mode 100644 index 0000000..e61e5cb --- /dev/null +++ b/src/codegen_ops_fpu_loadstore.c @@ -0,0 +1,231 @@ +#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(block, 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(block, 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(block, 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); + 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; +} +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); + 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); + + 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(block, 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(block, ir); + + 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_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(block, ir); + + 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(block, 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(block, 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_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(block, 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..b206f96 --- /dev/null +++ b/src/codegen_ops_fpu_loadstore.h @@ -0,0 +1,17 @@ +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); +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_ops_fpu_misc.c b/src/codegen_ops_fpu_misc.c new file mode 100644 index 0000000..2848ba9 --- /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_ST_i64(-1), IREG_ST_i64(src_reg)); + uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); + fpu_PUSH(block, 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_ST_i64(dest_reg), IREG_ST_i64(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_ST_i64(dest_reg), IREG_ST_i64(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + fpu_POP(block, 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+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) +{ + 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+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) +{ + 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_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_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_ST_i64(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_ops_helpers.c b/src/codegen_ops_helpers.c new file mode 100644 index 0000000..903a0e5 --- /dev/null +++ b/src/codegen_ops_helpers.c @@ -0,0 +1,65 @@ +#include "ibm.h" +#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" + +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); +} + +#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; + int first_instruction; + + /*Check that dest instruction was actually compiled into block*/ + start = codegen_get_instruction_uop(block, dest_addr, &first_instruction); + + /*Couldn't find any uOPs corresponding to the destination instruction*/ + if (start == -1) + { + /*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; + } + else + start = ir->wr_pos; + } + + 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, first_instruction); + + return 1; +} diff --git a/src/codegen_ops_helpers.h b/src/codegen_ops_helpers.h new file mode 100644 index 0000000..ae3e5ed --- /dev/null +++ b/src/codegen_ops_helpers.h @@ -0,0 +1,126 @@ +#include "386_common.h" +#include "codegen_backend.h" + +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 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) +{ + 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); +} + +static inline void fpu_POP(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_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); +} +static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir) +{ + 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); +} + +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); +} + +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)); +} + +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 new file mode 100644 index 0000000..5e4cda4 --- /dev/null +++ b/src/codegen_ops_jump.c @@ -0,0 +1,289 @@ +#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); + uint32_t dest_addr = op_pc+1+offset; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (offset < 0) + codegen_can_unroll(block, ir, op_pc+1, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 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) +{ + uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); + uint32_t dest_addr = op_pc+2+offset; + + dest_addr &= 0xffff; + + if (offset < 0) + codegen_can_unroll(block, ir, op_pc+1, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 2); + 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; + + if (offset < 0) + codegen_can_unroll(block, ir, op_pc+1, dest_addr); + codegen_mark_code_present(block, cs+op_pc, 4); + 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) +{ + 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); + + 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) +{ + 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); + + codegen_mark_code_present(block, cs+op_pc, 6); + 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; + + 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); + 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) +{ + 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); + + codegen_mark_code_present(block, cs+op_pc, 4); + 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); + + 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) +{ + 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); + + codegen_mark_code_present(block, cs+op_pc, 2); + 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) && !(cpu_state.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) && !(cpu_state.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) && !(cpu_state.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); + + 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) +{ + uint16_t offset; + + if ((msw&1) && !(cpu_state.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); + + codegen_mark_code_present(block, cs+op_pc, 2); + return -1; +} diff --git a/src/codegen_ops_jump.h b/src/codegen_ops_jump.h index d2271cf..db4c95c 100644 --- a/src/codegen_ops_jump.h +++ b/src/codegen_ops_jump.h @@ -1,270 +1,21 @@ -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; +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); - if (offset & 0x80) - offset |= 0xffffff00; +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); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+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 ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); -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; +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); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff); - - 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); +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); -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); +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); - 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) +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_logic.c b/src/codegen_ops_logic.c new file mode 100644 index 0000000..015031f --- /dev/null +++ b/src/codegen_ops_logic.c @@ -0,0 +1,804 @@ +#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_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) +{ + 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; + 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) +{ + 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; + 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) +{ + 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_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_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; + + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 0); + 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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + 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; + 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) +{ + 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; + 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) +{ + 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_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; + + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 0); + 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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + 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; + 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) +{ + 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; + 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) +{ + 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_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; + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + 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; + 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) +{ + 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; + 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) +{ + 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_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; + + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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_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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + 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 dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 0); + 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_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + return op_pc + 1; +} diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h index ca57fca..d86fbb4 100644 --- a/src/codegen_ops_logic.h +++ b/src/codegen_ops_logic.h @@ -1,564 +1,36 @@ -#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; \ - } +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); -ROP_LOGIC(AND, AND, 1) -ROP_LOGIC(OR, OR, 1) -ROP_LOGIC(XOR, XOR, 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); +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); -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; +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); - 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; -} +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_misc.c b/src/codegen_ops_misc.c new file mode 100644 index 0000000..13e0e64 --- /dev/null +++ b/src/codegen_ops_misc.c @@ -0,0 +1,611 @@ +#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_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_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); + + 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_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); + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + codegen_mark_code_present(block, cs+op_pc+1, 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + codegen_mark_code_present(block, cs+op_pc+1, 2); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + codegen_mark_code_present(block, cs+op_pc+1, 4); + 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; +} + +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) != 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) + return 0; + src_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)) /*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); + 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 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) + 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 op_pc+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) +{ + x86seg *target_seg = NULL; + int src_reg, sp_reg; + + 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) + return 0; + src_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)) /*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); + 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 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); + 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 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; +} + +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; +} + +#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; \ + \ + 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); \ + 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; \ + \ + 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); \ + 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) + +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 9eb9567..8f2fd76 100644 --- a/src/codegen_ops_misc.h +++ b/src/codegen_ops_misc.h @@ -1,269 +1,37 @@ -static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - return op_pc; -} +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); -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; -} +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); -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; -} +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); -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; +uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); - if ((fetchdat & 0x30) != 0x00) - return 0; +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); - 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); +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); - 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; - } +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); - 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; +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); - 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; -} +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_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_mmx_arith.c b/src/codegen_ops_mmx_arith.c new file mode 100644 index 0000000..1629fe6 --- /dev/null +++ b/src/codegen_ops_mmx_arith.c @@ -0,0 +1,57 @@ +#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); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ + 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) + +ropParith(PMADDWD) +ropParith(PMULHW) +ropParith(PMULLW) diff --git a/src/codegen_ops_mmx_arith.h b/src/codegen_ops_mmx_arith.h new file mode 100644 index 0000000..5f67f0a --- /dev/null +++ b/src/codegen_ops_mmx_arith.h @@ -0,0 +1,19 @@ +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); + +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); diff --git a/src/codegen_ops_mmx_cmp.c b/src/codegen_ops_mmx_cmp.c new file mode 100644 index 0000000..b7fe44d --- /dev/null +++ b/src/codegen_ops_mmx_cmp.c @@ -0,0 +1,44 @@ +#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); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ + 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); diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c new file mode 100644 index 0000000..ac591e8 --- /dev/null +++ b/src/codegen_ops_mmx_loadstore.c @@ -0,0 +1,110 @@ +#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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + 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); + } + + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + 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)); + } + + 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_ops_mmx_logic.c b/src/codegen_ops_mmx_logic.c new file mode 100644 index 0000000..744f22b --- /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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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); diff --git a/src/codegen_ops_mmx_pack.c b/src/codegen_ops_mmx_pack.c new file mode 100644 index 0000000..e625217 --- /dev/null +++ b/src/codegen_ops_mmx_pack.c @@ -0,0 +1,47 @@ +#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); \ + codegen_mark_code_present(block, cs+op_pc, 1); \ + 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); diff --git a/src/codegen_ops_mmx_shift.c b/src/codegen_ops_mmx_shift.c new file mode 100644 index 0000000..3086f4d --- /dev/null +++ b/src/codegen_ops_mmx_shift.c @@ -0,0 +1,93 @@ +#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); + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + } + + 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) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + 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*/ + 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; + + } + + 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) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + 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*/ + 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; + + } + + codegen_mark_code_present(block, cs+op_pc+1, 1); + 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); diff --git a/src/codegen_ops_mov.c b/src/codegen_ops_mov.c new file mode 100644 index 0000000..26cd4e5 --- /dev/null +++ b/src/codegen_ops_mov.c @@ -0,0 +1,772 @@ +#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 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); + + 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) +{ + uint16_t imm = fastreadw(cs + op_pc); + + 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) +{ + 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; +} + + + +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 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; + uop_MOV(ir, 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_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)); + } + + 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 src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOV(ir, 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_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)); + } + + 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 src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + uop_MOV(ir, 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_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)); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, 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_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, 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_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int src_reg = fetchdat & 7; + uop_MOV(ir, 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_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); + + 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) +{ + 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); + + 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 = 0; + + if (op_32 & 0x200) + { + 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); + 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); +} + +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); + + 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) +{ + 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); + + 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) +{ + 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); + + codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + 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) +{ + x86seg *target_seg; + uint16_t imm; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + 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) +{ + x86seg *target_seg; + uint32_t imm; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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, 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); + } + + codegen_mark_code_present(block, cs+op_pc+1, 4); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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; +} + +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 61fcd0f..03a9cb8 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -1,656 +1,43 @@ -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); +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); - 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); +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); - STORE_IMM_REG_L(opcode & 7, fetchdat); - - return op_pc + 4; -} +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); -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); +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); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 0); +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); - 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); +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); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 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); +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); - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - 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); +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); -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); +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); - 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) +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_shift.c b/src/codegen_ops_shift.c new file mode 100644 index 0000000..0d19f40 --- /dev/null +++ b/src/codegen_ops_shift.c @@ -0,0 +1,1135 @@ +#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_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) +{ + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + 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); + 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 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); + 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 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); + 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 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); + 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 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); + 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 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); + 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; +} + +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 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); + 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 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); + 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) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if ((fetchdat & 0x30) == 0x10) /*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); + 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; + 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; +} +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 & 0x30) == 0x10) /*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); + 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; + 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; +} +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; + + if ((fetchdat & 0x30) == 0x10) /*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); + 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); + } + 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); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp2, 0); + + 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 + { + 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; +} + +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 & 0x30) == 0x10) /*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); + 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 & 0x30) == 0x10) /*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); + 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 & 0x30) == 0x10) /*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); + 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 & 0x30) == 0x10) /*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, codegen_exit_rout); + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + 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); + 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 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); + 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 & 0x30) == 0x10) /*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, codegen_exit_rout); + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + 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); + 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 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); + 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 & 0x30) == 0x10) /*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, codegen_exit_rout); + + codegen_mark_code_present(block, cs+op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + { + int dest_reg = fetchdat & 7; + + 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); + 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 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); + 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; + + 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; + + 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; + + 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; + + 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; + + 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; + + 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; + + 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; + + 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 index 75d024f..f109b0d 100644 --- a/src/codegen_ops_shift.h +++ b/src/codegen_ops_shift.h @@ -1,125 +1,16 @@ -#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); \ - } +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); -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; +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); - if ((fetchdat & 0x38) < 0x20) - return 0; +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); - 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; -} +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_ops_stack.c b/src/codegen_ops_stack.c new file mode 100644 index 0000000..c3c8a46 --- /dev/null +++ b/src/codegen_ops_stack.c @@ -0,0 +1,409 @@ +#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_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 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); + + 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) +{ + 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); + + codegen_mark_code_present(block, cs+op_pc, 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); + + 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) +{ + 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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); + + codegen_mark_code_present(block, cs+op_pc, 1); + 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) + +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; +} + + +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; +} + +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 3ea27d3..6b9ac57 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -1,269 +1,49 @@ -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; +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); - 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; +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); - 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); +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); - 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); +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); -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; +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); - 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; +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); - 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; -} +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); -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; +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); - if (imm & 0x80) - imm |= 0xff00; +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); - 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; +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); - if (imm & 0x80) - imm |= 0xffffff00; +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); - 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) +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_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_reg.c b/src/codegen_reg.c new file mode 100644 index 0000000..eb07cfb --- /dev/null +++ b/src/codegen_reg.c @@ -0,0 +1,770 @@ +#include "ibm.h" +#include "codegen.h" +#include "codegen_backend.h" +#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]; +reg_version_t reg_version[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_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 +{ + REG_BYTE, + REG_WORD, + REG_DWORD, + REG_QWORD, + REG_POINTER, + REG_DOUBLE, + REG_FPU_ST_BYTE, + REG_FPU_ST_DOUBLE, + REG_FPU_ST_QWORD +}; + +enum +{ + REG_INTEGER, + 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, 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, 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, REG_PERMANENT}, + [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT}, + + [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, 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, REG_PERMANENT}, + + [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, 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, 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, REG_PERMANENT}, + + [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, 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, 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, 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, REG_PERMANENT}, + [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT}, + + [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.*/ + [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, REG_VOLATILE}, + [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; + 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; + + 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; + reg_version[c][0].refcount = 0; + } + for (c = 0; c < CODEGEN_HOST_REGS; c++) + { + 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; + } + + reg_dead_list = 0; + max_version_refcount = 0; +} + +static inline int ir_get_refcount(ir_reg_t ir_reg) +{ + 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) +{ + 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, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + 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, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p); + 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_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"); + 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_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 + 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 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; + +//pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version); +} + +static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate) +{ + int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); + void *p = ireg_data[ir_reg].p; + + if (!reg_version[ir_reg][reg_set->regs[c].version].refcount && + ireg_data[ir_reg].is_volatile) + return; + + 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, 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, 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, reg_set->reg_list[c]); + else + 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"); + if ((uintptr_t)p < 256) + fatal("codegen_reg_writeback - REG_POINTER %p\n", p); + 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 (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 + codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]); + break; + + default: + fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); + } + + if (invalidate) + reg_set->regs[c] = invalid_ir_reg; + 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->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; + } + } +} + +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 dest_reference = 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, + src_reg_b.reg, src_reg_b.version);*/ + + if (!ir_reg_is_invalid(dest_reg_a)) + { + 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) && 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++; + } + 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) +{ + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int c; + + /*Search for required register*/ + for (c = 0; c < reg_set->nr_regs; c++) + { + 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_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"); + } + + if (c == reg_set->nr_regs) + { + /*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)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c])) + break; + } + if (c == reg_set->nr_regs) + { + /*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); +// 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; + } +// else +// pclog(" already loaded %i\n", c); + + 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], reg_set->regs[c].reg,reg_set->regs[c].version, c); + 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 (!reg_is_native_size(ir_reg)) + { + /*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; + 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) + 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); + + 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 reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg); + } + + /*Search for previous version in host register*/ + for (c = 0; c < reg_set->nr_regs; c++) + { + 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_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; + } + } + } + + if (c == reg_set->nr_regs) + { + /*Search for unused registers*/ + for (c = 0; c < reg_set->nr_regs; c++) + { + if (ir_reg_is_invalid(reg_set->regs[c])) + break; + } + + if (c == reg_set->nr_regs) + { + /*No unused registers. Search for an 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_write_reg - out of registers\n"); + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, 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 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; + + reg_set = &host_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); + } + } + + 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; + + reg_set = &host_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, 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]) && reg_set->dirty[c]) + { + codegen_reg_writeback(reg_set, block, c, 1); + } + reg_set->regs[c] = invalid_ir_reg; + 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 new file mode 100644 index 0000000..bd790a9 --- /dev/null +++ b/src/codegen_reg.h @@ -0,0 +1,399 @@ +#ifndef _CODEGEN_REG_H_ +#define _CODEGEN_REG_H_ + +#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) + +#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) +#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) +#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) + +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_ssegsx = 17, + + IREG_rm_mod_reg = 18, + + 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, + + 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 = 33, + IREG_temp1 = 34, + IREG_temp2 = 35, + IREG_temp3 = 36, + + IREG_FPU_TOP = 37, + + IREG_temp0d = 38, + IREG_temp1d = 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 + 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_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_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_flagsx = 74, + IREG_eflagsx = 75, + + 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, + + 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_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, + 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, + + 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, + 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, + + 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, + + IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, + + 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)) +#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_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) + +#define IREG_MM(reg) ((reg) + IREG_MM0) + +#define IREG_TOP_diff_stack_offset 32 + +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; +} + +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]; + +/*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 +{ + uint16_t reg; + uint16_t version; +} ir_reg_t; + +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) +{ + 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)]; + 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 (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; +} + +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 = 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(); + 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; + version->parent_uop = uop_nr; +// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK); + 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(); +/*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, 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); + +void codegen_reg_mark_as_required(); +void codegen_reg_process_dead_list(struct ir_data_t *ir); +#endif diff --git a/src/codegen_timing_486.c b/src/codegen_timing_486.c index 4e05e24..6f9e3af 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; @@ -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 9559e03..cc1e119 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; @@ -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_common.c b/src/codegen_timing_common.c index b56335a..c29f24f 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, @@ -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, @@ -658,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 ac7bd2a..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) @@ -82,6 +85,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..5d5aa8e --- /dev/null +++ b/src/codegen_timing_k6.c @@ -0,0 +1,2365 @@ +/*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, &vector_cmpxchg_op, + &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 prefixes; + +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; +} + +/*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 + 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]; + } + + /*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) + { + 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; + prefixes = 0; +} + +void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) +{ + if (prefix != 0x0f) + decode_timestamp++; + + last_prefix = prefix; + prefixes++; +} + +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; + } + } + + 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); +} + +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() +{ + 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_jump_cycles +}; diff --git a/src/codegen_timing_pentium.c b/src/codegen_timing_pentium.c index 4194e3a..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; @@ -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; @@ -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; @@ -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 bdf499e..c23b30b 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; @@ -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 new file mode 100644 index 0000000..c85a0e9 --- /dev/null +++ b/src/codegen_timing_winchip2.c @@ -0,0 +1,759 @@ +/*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 op_pc) +{ + 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; + } +} + +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_jump_cycles +}; 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/cpu.c b/src/cpu.c index c5958c5..42cbee1 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; @@ -34,6 +36,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 +58,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,17 +72,18 @@ 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; 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_use_dynarec; int cpu_cyrix_alignment; @@ -90,6 +95,8 @@ int cpu_waitstates; int cpu_cache_int_enabled, cpu_cache_ext_enabled; int is386; +int is486; +int CPUID; uint64_t tsc = 0; @@ -113,364 +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 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}, - {"", -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} -}; - void cpu_set_edx() { EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; @@ -500,11 +149,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; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; has_vlb = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type <= CPU_Cx5x86); @@ -548,8 +192,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) { @@ -802,8 +448,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: @@ -949,10 +594,8 @@ void cpu_set() 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 << 19) | (1 << 21); - cpu_hasMMX = cpu_hasMSR = 1; - cpu_hasCR4 = 1; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4; + msr.fcr = (1 << 8) | (1 << 16); cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; /*unknown*/ timing_int_rm = 26; @@ -978,6 +621,44 @@ 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_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_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_winchip2); + 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*/ @@ -1009,12 +690,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; @@ -1050,12 +727,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; @@ -1091,11 +764,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; @@ -1131,11 +801,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; @@ -1152,11 +819,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; @@ -1205,16 +869,90 @@ 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; 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_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_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; + codegen_timing_set(&codegen_timing_k6); + 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_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_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; + codegen_timing_set(&codegen_timing_k6); + break; + default: fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); } @@ -1308,7 +1046,7 @@ void cpu_CPUID() else { EBX = 0x746e6543; /*CentaurHauls*/ - ECX = 0x736c7561; + ECX = 0x736c7561; EDX = 0x48727561; } } @@ -1317,14 +1055,74 @@ void cpu_CPUID() EAX = 0x540; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_hasCX8) - EDX |= CPUID_CMPXCHG8B; + if (cpu_has_feature(CPU_FEATURE_CX8)) + 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_has_feature(CPU_FEATURE_CX8)) + 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_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + if (cpu_has_feature(CPU_FEATURE_3DNOW)) + 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) @@ -1439,6 +1237,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; } } @@ -1447,6 +1459,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) { @@ -1499,6 +1512,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; } } @@ -1507,6 +1534,7 @@ void cpu_WRMSR() switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type) { case CPU_WINCHIP: + case CPU_WINCHIP2: switch (ECX) { case 0x02: @@ -1523,11 +1551,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_features |= CPU_FEATURE_3DNOW; + else + cpu_features &= ~CPU_FEATURE_3DNOW; if (EAX & (1 << 29)) CPUID = 0; else @@ -1562,6 +1597,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 ef21835..2e8cc4f 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -28,12 +28,18 @@ 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 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 @@ -84,10 +90,13 @@ 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[]; extern CPU cpus_6x86[]; +extern CPU cpus_K6_S7[]; +extern CPU cpus_K6_SS7[]; extern CPU cpus_pcjr[]; extern CPU cpus_europc[]; @@ -105,12 +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; +#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 inline int cpu_has_feature(int feature) +{ + return cpu_features & feature; +} #define CR4_TSD (1 << 2) #define CR4_DE (1 << 3) @@ -133,6 +149,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(); @@ -140,7 +158,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/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} +}; + 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..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 { @@ -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 25ab9f0..ca3a4fc 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -9,8 +9,7 @@ #include "io.h" #include "pic.h" #include "timer.h" - -extern int motoron; +#include "x86.h" static int fdc_reset_stat = 0; /*FDC*/ @@ -39,7 +38,7 @@ typedef struct FDC int pcjr, ps1; - int watchdog_timer; + pc_timer_t watchdog_timer; int watchdog_count; int data_ready; @@ -65,12 +64,13 @@ typedef struct FDC uint8_t fifobuf[16]; int int_pending; + + pc_timer_t timer; } FDC; static FDC fdc; void fdc_callback(); -int timetolive; //#define SECTORS 9 int lastbyte=0; uint8_t disc_3f7; @@ -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); } @@ -322,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; @@ -332,25 +333,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 +356,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 +377,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 +460,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 +468,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 +539,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 +548,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, 256 * TIMER_USEC); // fdc.drive = fdc.params[0] & 3; disc_drivesel = fdc.drive & 1; fdc_reset_stat = 0; @@ -587,7 +571,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 +581,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 +596,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 +617,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 +641,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); @@ -689,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) { @@ -771,9 +762,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 +794,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 +858,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 +970,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 +991,6 @@ void fdc_callback() paramstogo = 2; discint = 0; - disctime = 0; return; case 0x0d: /*Format track*/ @@ -1015,26 +999,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 +1048,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 +1064,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 +1071,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 +1085,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 +1093,6 @@ void fdc_callback() fdc.res[10] = 0; paramstogo=1; discint=0; - disctime = 0; return; case 0x94: /*Lock*/ fdc.lock = 1; @@ -1129,7 +1100,6 @@ void fdc_callback() fdc.res[10] = 0x10; paramstogo=1; discint=0; - disctime = 0; return; case 0x18: /*NSC*/ @@ -1137,7 +1107,6 @@ void fdc_callback() fdc.res[10] = 0x73; paramstogo=1; discint=0; - disctime = 0; return; case 0xfc: /*Invalid*/ @@ -1149,7 +1118,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 +1128,7 @@ void fdc_callback() void fdc_overrun() { disc_sector_stop(); - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1234,13 +1202,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 +1225,7 @@ void fdc_notfound() void fdc_datacrcerror() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1274,7 +1242,7 @@ void fdc_datacrcerror() void fdc_headercrcerror() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1291,7 +1259,7 @@ void fdc_headercrcerror() void fdc_writeprotect() { - disctime = 0; + timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; @@ -1380,7 +1348,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 +1372,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/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/gameport.c b/src/gameport.c index 5d16123..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" @@ -69,7 +70,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 +87,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 +102,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 +120,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 +138,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 +159,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..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 { @@ -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/headland.c b/src/headland.c index 8af4a5d..0208c5d 100644 --- a/src/headland.c +++ b/src/headland.c @@ -177,9 +177,7 @@ void headland_write(uint16_t addr, uint8_t val, void *priv) //pclog("Headland write %02X %02X at %04X:%04X\n",headland_index,val,CS,cpu_state.oldpc); 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); @@ -532,7 +530,5 @@ void headland_init() mem_mapping_disable(&headland_ems_mapping[i]); } - for(i=4;i<10;i++) isram[i] = 0; - headland_memmap_state_update(); } 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/i430hx.c b/src/i430hx.c index fce9a01..d7133f5 100644 --- a/src/i430hx.c +++ b/src/i430hx.c @@ -64,7 +64,7 @@ void i430hx_write(int func, int addr, uint8_t val, void *priv) if ((card_i430hx[0x59] ^ val) & 0xf0) { i430hx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); +// shadowbios = (val & 0x10); } pclog("i430hx_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 ed3aac2..950122f 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -2,6 +2,8 @@ #include #include +#include "timer.h" + #ifdef ABS #undef ABS #endif @@ -30,27 +32,14 @@ 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 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); -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); +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); @@ -69,221 +58,14 @@ 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; /*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]; -} 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]; - - uint16_t old_npxc, new_npxc; -} cpu_state; - -#define cycles cpu_state._cycles - -extern uint32_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 0xffff - -/*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 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) - -uint16_t flags,eflags; -uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; - -extern int ins,output; -extern int cycdiff; - -x86seg gdt,ldt,idt,tr; -x86seg _cs,_ds,_es,_ss,_fs,_gs; -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 _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 CPL ((_cs.access>>5)&3) - -void 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 - -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 ((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 uint8_t opcode; -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 @@ -295,7 +77,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]; @@ -377,7 +159,6 @@ PIC pic,pic2; extern int pic_intpending; -int disctime; char discfns[2][256]; int driveempty[2]; @@ -469,7 +250,8 @@ enum ROM_ZD_SUPERS, /* [8088] Zenith Data Systems SupersPort */ ROM_PB410A, ROM_PPC512, - + ROM_FIC_VA503P, + ROM_MAX }; @@ -537,10 +319,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..4e8d5ef 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 @@ -94,11 +94,12 @@ 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; -int idecallback[2] = {0, 0}; +pc_timer_t ide_timer[2]; int cur_ide[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; @@ -268,7 +269,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 +324,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 +426,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 +457,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 +488,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 +521,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 +531,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 +543,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 +559,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 +568,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 +576,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 +595,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 +603,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 +767,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); } @@ -848,6 +819,7 @@ void callbackide(int ide_board) { ide->cylinder=0xEB14; atapi->stop(); + atapi_reset(&ide->atapi); } if (ide->type == IDE_NONE) { @@ -858,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) { @@ -935,8 +908,8 @@ 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*/ + 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 { /*DMA successful*/ @@ -948,7 +921,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 { @@ -1013,8 +986,8 @@ 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*/ + 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 { /*DMA successful*/ @@ -1027,7 +1000,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 +1174,11 @@ abort_cmd: void ide_callback_pri() { - idecallback[0] = 0; callbackide(0); } void ide_callback_sec() { - idecallback[1] = 0; callbackide(1); } @@ -1292,8 +1263,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; } @@ -1302,11 +1273,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 cb497ea..0c2ce0b 100644 --- a/src/ide.h +++ b/src/ide.h @@ -2,6 +2,7 @@ #define __IDE__ #include "device.h" +#include "timer.h" struct IDE; @@ -15,18 +16,19 @@ 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" 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..0324e9c 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; } @@ -258,23 +258,23 @@ 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; - 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; @@ -430,21 +430,21 @@ 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; - 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,37 +529,47 @@ 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; 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)) { - 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; 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)) { - 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; } } + +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/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/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 6799aea..6519897 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -34,6 +34,8 @@ struct uint8_t pa; uint8_t pb; + + pc_timer_t send_delay_timer; } keyboard_pcjr; static uint8_t key_queue[16]; @@ -41,8 +43,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) { @@ -129,7 +130,6 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv) keyboard_pcjr.pb = val; timer_process(); - timer_update_outstanding(); cassette_set_motor((val & 8) ? 0 : 1); @@ -214,5 +214,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 86b3a8f..0dce487 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -37,6 +37,8 @@ struct int tandy; int pb2_turbo; + + pc_timer_t send_delay_timer; } keyboard_xt; static uint8_t key_queue[16]; @@ -44,7 +46,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) @@ -125,8 +127,7 @@ void keyboard_xt_write(uint16_t port, uint8_t val, void *priv) ppi.pb = val; timer_process(); - timer_update_outstanding(); - + if (romset == ROM_IBMPC) cassette_set_motor((val & 8) ? 0 : 1); else if (keyboard_xt.pb2_turbo) @@ -241,7 +242,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() @@ -253,5 +254,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/mcr.c b/src/mcr.c index 83d7530..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; @@ -10,7 +11,6 @@ void resetmcr() { mcrlock=0; mcrfirst=1; - shadowbios=0; } void writemcr(uint16_t addr, uint8_t val) @@ -29,7 +29,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 eabbcaa..dd3186d 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; @@ -44,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; @@ -58,7 +46,13 @@ int cachesize=256; uint8_t *ram, *rom = NULL; uint8_t romext[32768]; -//int abrt=0; +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; + +uint32_t mem_logical_addr; + +int mmuflush=0; +int mmu_perm=4; void resetreadlookup() { @@ -76,9 +70,6 @@ void resetreadlookup() } -int mmuflush=0; -int mmu_perm=4; - void flushmmucache() { int c; @@ -210,15 +201,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]; @@ -295,7 +280,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; @@ -420,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)]; @@ -432,16 +416,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; } @@ -449,7 +430,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; @@ -460,11 +441,11 @@ 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; + mem_logical_addr = addr; if (cr0 >> 31) { @@ -473,13 +454,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]) @@ -494,456 +479,380 @@ 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); } -uint8_t readmemb386l(uint32_t seg, uint32_t addr) +uint16_t readmemwl(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; -/* 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; - } + mem_mapping_t *map; - addr &= rammask; + mem_logical_addr = addr; - 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 seg, uint32_t addr, uint8_t val) -{ - if (seg==-1) + if (addr & 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; - 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 seg, uint32_t addr) -{ - uint32_t addr2 = mem_logical_addr = seg + addr; - - if (seg==-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); + 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_b[addr2 >> 14]) + map = read_mapping[addr >> 14]; + if (map) { - 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); + if (map->read_w) + return map->read_w(addr, map->p); + + if (map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); } -// pclog("Bad readmemwl %08X\n", addr2); + +// 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_mapping_t *map; - if (seg==-1) - { - x86gpf("NULL segment", 0); - printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr); - return; - } + mem_logical_addr = addr; - if (addr2 & 1) + if (addr & 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 (is386) - { - writememb386l(seg,addr,val); - writememb386l(seg,addr+1,val>>8); - } - else - { - writemembl(seg+addr,val); - writemembl(seg+addr+1,val>>8); + if (mmutranslate_write(addr) == 0xffffffff) return; + if (mmutranslate_write(addr+1) == 0xffffffff) return; } + 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]) + map = write_mapping[addr >> 14]; + if (map) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 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[addr2 >> 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]); - 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_mapping_t *map; - 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; - } + mem_logical_addr = addr; - if (addr2 & 3) + if (addr & 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]); + map = read_mapping[addr >> 14]; + if (map) + { + if (map->read_l) + return map->read_l(addr, map->p); - 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_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 (map->read_w) + return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); -// pclog("Bad readmemll %08X\n", addr2); + 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; } -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_mapping_t *map; - if (seg==-1) + mem_logical_addr = addr; + + 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]) + map = write_mapping[addr >> 14]; + if (map) { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 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); + } } - if (_mem_write_w[addr2 >> 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]); - return; - } - if (_mem_write_b[addr2 >> 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]); - 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_mapping_t *map; - 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; - } + mem_logical_addr = addr; - 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); + 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(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_mapping_t *map; - 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) + mem_logical_addr = addr; + + 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]) + map = write_mapping[addr >> 14]; + if (map) { - _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]); - 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); + } } - if (_mem_write_w[addr2 >> 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]); - return; - } - if (_mem_write_b[addr2 >> 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]); - 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) { + 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); @@ -952,10 +861,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); @@ -982,14 +893,59 @@ 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 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 |= 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) @@ -997,11 +953,38 @@ 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 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\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 |= 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); + } } } void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) @@ -1009,11 +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 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\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 |= 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); + } + } } } @@ -1124,8 +1127,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]; + +//pclog("mem_invalidate: %08x\n", start_addr); + 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); + } } } @@ -1174,17 +1184,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*/ @@ -1203,24 +1205,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; } } } @@ -1365,80 +1359,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; - } - - 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(_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; @@ -1480,7 +1400,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; @@ -1488,6 +1417,13 @@ void mem_resize() 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)); @@ -1497,22 +1433,15 @@ 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; - } - - 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; + 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(_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(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)); memset(&base_mapping, 0, sizeof(base_mapping)); @@ -1557,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] = 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 = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; } } diff --git a/src/mem.h b/src/mem.h index 2aabde9..429973a 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; @@ -35,7 +37,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, @@ -111,6 +112,14 @@ 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 { void (*write_b)(uint32_t addr, uint8_t val, struct page_t *p); @@ -119,18 +128,31 @@ typedef struct page_t uint8_t *mem; - struct codeblock_t *block[4], *block_2[4]; + uint16_t block, block_2; /*Head of codeblock tree associated with this page*/ - struct codeblock_t *head; + 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; 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) @@ -146,17 +168,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 (phys_addr != 0xffffffff) + addreadlookup(addr, phys_addr); + + return phys_addr; } void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr); @@ -180,7 +219,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(); @@ -194,5 +233,5 @@ void mmu_invalidate(uint32_t addr); int loadbios(); -extern unsigned char isram[0x10000]; +extern int purgeable_page_count; #endif diff --git a/src/mem_bios.c b/src/mem_bios.c index 0f04f5f..b12887a 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -986,6 +986,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/mfm_at.c b/src/mfm_at.c index 1084229..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 { @@ -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..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 { @@ -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/model.c b/src/model.c index 75c17fa..d370533 100644 --- a/src/model.c +++ b/src/model.c @@ -38,6 +38,7 @@ #include "lpt.h" #include "mem.h" #include "mouse_ps2.h" +#include "mvp3.h" #include "neat.h" #include "nmi.h" #include "nvr.h" @@ -59,12 +60,15 @@ #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" #include "vid_pcjr.h" #include "vid_tandy.h" #include "vid_t1000.h" +#include "vt82c586b.h" +#include "w83877tf.h" #include "wd76c10.h" #include "xi8088.h" #include "zenith.h" @@ -116,6 +120,7 @@ void at_pb570_init(); void compaq_pip_init(); void xt_xi8088_init(); void xt_zenith_init(); +void at_mvp3_init(); int model; int AMSTRAD, AT, PCI, TANDY; @@ -208,6 +213,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}, {"[Socket 7] Epox P55-VA", ROM_P55VA, "p55va", { {"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_p55va_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} }; @@ -752,11 +759,24 @@ void at_p55t2p4_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(); + device_add(&sst_39sf010_device); +} + 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/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/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/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 a09cb4d..4fe085a 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; @@ -19,9 +20,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 +64,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 +74,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 +99,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 +131,6 @@ void nvr_update_end(void *p) } // pclog("RTC onesec\n"); - - nvr_update_end_count = 0; } void nvr_onesec(void *p) @@ -144,11 +143,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 +173,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 { @@ -323,7 +322,8 @@ void loadnvr() case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","rb"); break; case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "rb"); break; case ROM_PB410A: f = nvrfopen("pb410a.nvr", "rb"); nvrmask = 127; break; - + case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break; + default: return; } if (!f) @@ -348,7 +348,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() { @@ -421,7 +421,8 @@ void savenvr() case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","wb"); break; case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "wb"); break; case ROM_PB410A: f = nvrfopen("pb410a.nvr", "wb"); break; - + case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break; + default: return; } fwrite(nvrram,128,1,f); @@ -431,8 +432,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/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 341f771..9deea6d 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; @@ -81,7 +80,6 @@ void fullspeed(); int framecount,fps; -int output; int atfullspeed; void saveconfig(char *fn); @@ -106,7 +104,7 @@ void pclog(const char *format, ...) vsprintf(buf, format, ap); va_end(ap); fputs(buf,pclogf); - //fflush(pclogf); + fflush(pclogf); #endif } @@ -360,8 +358,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 +384,6 @@ void resetpc() // cpuspeed2=(AT)?2:1; // atfullspeed=0; ///* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed(); - shadowbios=0; } void resetpc_cad() @@ -410,7 +406,7 @@ void resetpchard() sound_reset(); io_init(); cpu_set(); - mem_resize(); + mem_alloc(); fdc_init(); disc_reset(); disc_load(0, discfns[0]); @@ -449,7 +445,6 @@ void resetpchard() // atfullspeed = 0; // setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed); - shadowbios = 0; ali1429_reset(); keyboard_at_reset(); @@ -565,8 +560,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; @@ -576,8 +569,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; @@ -624,6 +615,7 @@ void speedchanged() void closepc() { + codegen_close(); atapi->exit(); // ioctl_close(); dumppic(); @@ -916,7 +908,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/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/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/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/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 eb1a953..ca41c39 100644 --- a/src/scat.c +++ b/src/scat.c @@ -1417,8 +1417,6 @@ void scat_init() mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); } - for(i=4;i<10;i++) isram[i] = 0; - for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++) { mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); 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_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..48dbdb6 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); @@ -423,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); @@ -697,7 +702,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 +766,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 +867,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 +880,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 +972,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 +985,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 +1373,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; } } @@ -1553,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 f314ebf..914f984 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) @@ -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; @@ -818,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 91956e2..51dacb2 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; @@ -220,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; @@ -689,7 +695,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 +756,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 +825,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 +893,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; @@ -1197,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, 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/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/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..b56b510 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(); @@ -1223,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) 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..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*/ @@ -106,54 +107,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 +153,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..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 @@ -118,7 +119,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 +400,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 +415,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 +436,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 +455,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 +463,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 +471,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 +487,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 +507,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 +563,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 +741,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/sst39sf010.c b/src/sst39sf010.c new file mode 100644 index 0000000..8acb664 --- /dev/null +++ b/src/sst39sf010.c @@ -0,0 +1,225 @@ +#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]; + uint8_t data[0x20000]; +} 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); + memset(sst->data, 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); + memset(&sst->data[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->data[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); + } + memcpy(sst->data, rom, 0x20000); + + 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(sst->data, 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; 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/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(); } } 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; diff --git a/src/vid_cga.c b/src/vid_cga.c index fe7f903..7a21b2f 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; @@ -329,7 +331,7 @@ void cga_poll(void *p) } else { - cga->vidtime += cga->dispontime; + timer_advance_u64(&cga->timer, cga->dispontime); cga->linepos = 0; if (cga->vsynctime) { @@ -450,6 +452,7 @@ void cga_poll(void *p) void cga_init(cga_t *cga) { + timer_add(&cga->timer, cga_poll, cga, 1); cga->composite = 0; } @@ -468,7 +471,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_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; } 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 735d6ad..f06345b 100644 --- a/src/vid_genius.c +++ b/src/vid_genius.c @@ -97,8 +97,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; @@ -245,8 +245,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; } @@ -461,7 +461,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; @@ -525,7 +525,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) @@ -560,7 +560,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 3265bb4..31ba65a 100644 --- a/src/vid_mda.c +++ b/src/vid_mda.c @@ -73,8 +73,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) @@ -89,7 +89,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; @@ -143,7 +143,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) @@ -246,7 +246,6 @@ void *mda_standalone_init() mda_init(mda); mda->vram = malloc(0x1000); - timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda); 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); @@ -280,6 +279,8 @@ void mda_init(mda_t *mda) mdacols[0x08][0][1] = mdacols[0x08][1][1] = cgapal[0]; mdacols[0x80][0][1] = mdacols[0x80][1][1] = cgapal[0]; mdacols[0x88][0][1] = mdacols[0x88][1][1] = cgapal[0]; + + timer_add(&mda->timer, mda_poll, mda, 1); } void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) diff --git a/src/vid_mda.h b/src/vid_mda.h index e61b15e..7a5a2f7 100644 --- a/src/vid_mda.h +++ b/src/vid_mda.h @@ -8,9 +8,9 @@ typedef struct mda_t uint8_t ctrl, stat; - int dispontime, dispofftime; - int vidtime; - + uint64_t dispontime, dispofftime; + pc_timer_t timer; + int firstline, lastline; int linepos, displine; 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 f643692..2b8a229 100644 --- a/src/vid_pc1512.c +++ b/src/vid_pc1512.c @@ -36,7 +36,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; @@ -154,8 +155,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) @@ -172,7 +173,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; @@ -338,7 +339,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) @@ -463,7 +464,7 @@ static void *pc1512_init() pc1512->fontbase = (device_get_config_int("codepage") & 3) * 256; display_type = device_get_config_int("display_type"); - 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); cgapal_rebuild(display_type, 0); 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 737e943..e430232 100644 --- a/src/vid_pc200.c +++ b/src/vid_pc200.c @@ -35,7 +35,7 @@ typedef struct pc200_t cga_t cga; mda_t mda; - int vidtime; + pc_timer_t timer; uint8_t emulation; /* Which display are we emulating? */ uint8_t dipswitches; /* DIP switches 1-3 */ @@ -54,23 +54,6 @@ static uint8_t crtcmask[32] = 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static void setvidtime(pc200_t *pc200) -{ - switch (pc200->emulation) - { - case PC200_CGA: - case PC200_TV: - case PC200_LCDC: - pc200->vidtime = pc200->cga.vidtime; - break; - - case PC200_MDA: - case PC200_LCDM: - pc200->vidtime = pc200->mda.vidtime; - break; - } -} - /* LCD colour mappings * * 0 => solid green @@ -193,7 +176,6 @@ void pc200_out(uint16_t addr, uint8_t val, void *p) { fullchange = changeframecount; mda_recalctimings(mda); - setvidtime(pc200); } } return; @@ -204,7 +186,6 @@ void pc200_out(uint16_t addr, uint8_t val, void *p) if ((mda->ctrl ^ old) & 3) { mda_recalctimings(mda); - setvidtime(pc200); } pc200->crtc_index &= 0x1F; pc200->crtc_index |= 0x80; @@ -243,7 +224,6 @@ void pc200_out(uint16_t addr, uint8_t val, void *p) { fullchange = changeframecount; cga_recalctimings(cga); - setvidtime(pc200); } } return; @@ -254,7 +234,6 @@ void pc200_out(uint16_t addr, uint8_t val, void *p) if ((cga->cgamode ^ old) & 3) { cga_recalctimings(cga); - setvidtime(pc200); } pc200->crtc_index &= 0x1F; pc200->crtc_index |= 0x80; @@ -280,6 +259,9 @@ void pc200_out(uint16_t addr, uint8_t val, void *p) nmi = 1; return; } + timer_disable(&pc200->cga.timer); + timer_disable(&pc200->mda.timer); + timer_disable(&pc200->timer); pc200->operation_ctrl = val; /* Bits 0 and 1 control emulation and output mode */ if (val & 1) /* Monitor */ @@ -296,6 +278,13 @@ void pc200_out(uint16_t addr, uint8_t val, void *p) } PC200LOG(("Video emulation set to %d\n", pc200->emulation)); + if (pc200->emulation == PC200_CGA || pc200->emulation == PC200_TV) + timer_advance_u64(&pc200->cga.timer, 1); + else if (pc200->emulation == PC200_MDA) + timer_advance_u64(&pc200->mda.timer, 1); + else + timer_advance_u64(&pc200->timer, 1); + /* Bit 2 disables the IDA. We don't support dynamic enabling * and disabling of the IDA (instead, PCEM disconnects the * IDA from the bus altogether) so don't implement this */ @@ -450,7 +439,7 @@ void lcdm_poll(pc200_t *pc200) int blink; if (!mda->linepos) { - pc200->vidtime += mda->dispofftime; + timer_advance_u64(&pc200->timer, mda->dispofftime); mda->stat |= 1; mda->linepos = 1; oldsc = mda->sc; @@ -487,7 +476,7 @@ void lcdm_poll(pc200_t *pc200) } else { - pc200->vidtime += mda->dispontime; + timer_advance_u64(&pc200->timer, mda->dispontime); if (mda->dispon) mda->stat&=~1; mda->linepos=0; if (mda->vsynctime) @@ -598,7 +587,7 @@ void lcdc_poll(pc200_t *pc200) if (!cga->linepos) { - pc200->vidtime += cga->dispofftime; + timer_advance_u64(&pc200->timer, cga->dispofftime); cga->cgastat |= 1; cga->linepos = 1; oldsc = cga->sc; @@ -670,7 +659,7 @@ void lcdc_poll(pc200_t *pc200) } else { - pc200->vidtime += cga->dispontime; + timer_advance_u64(&pc200->timer, cga->dispontime); cga->linepos = 0; if (cga->vsynctime) { @@ -796,18 +785,18 @@ void pc200_poll(void *p) switch (pc200->emulation) { - case PC200_CGA: - case PC200_TV: - pc200->cga.vidtime = pc200->vidtime; - cga_poll(&pc200->cga); - pc200->vidtime = pc200->cga.vidtime; - return; +// case PC200_CGA: +// case PC200_TV: +// pc200->cga.vidtime = pc200->vidtime; +// cga_poll(&pc200->cga); +// pc200->vidtime = pc200->cga.vidtime; +// return; - case PC200_MDA: - pc200->mda.vidtime = pc200->vidtime; - mda_poll(&pc200->mda); - pc200->vidtime = pc200->mda.vidtime; - return; +// case PC200_MDA: +// pc200->mda.vidtime = pc200->vidtime; +// mda_poll(&pc200->mda); +// pc200->vidtime = pc200->mda.vidtime; +// return; case PC200_LCDM: lcdm_poll(pc200); @@ -870,8 +859,9 @@ void *pc200_init() mda_setcol(0xC0, 0, 1, 0); pc200->cga.fontbase = (device_get_config_int("codepage") & 3) * 256; - - timer_add(pc200_poll, &pc200->vidtime, TIMER_ALWAYS_ENABLED, pc200); + +// pclog("pc200=%p pc200->timer=%p pc200->cga=%p pc200->mda=%p pc200->mda->timer=%p\n", pc200, &pc200->timer, &pc200->cga, &pc200->mda, &pc200->mda->timer); + timer_add(&pc200->timer, pc200_poll, pc200, 1); mem_mapping_add(&pc200->mda_mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, 0, &pc200->mda); mem_mapping_add(&pc200->cga_mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &pc200->cga); io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200); @@ -882,6 +872,16 @@ void *pc200_init() cgapal_rebuild(display_type, contrast); set_lcd_cols(0); + timer_disable(&pc200->cga.timer); + timer_disable(&pc200->mda.timer); + timer_disable(&pc200->timer); + if (pc200->emulation == PC200_CGA || pc200->emulation == PC200_TV) + timer_enable(&pc200->cga.timer); + else if (pc200->emulation == PC200_MDA) + timer_enable(&pc200->mda.timer); + else + timer_enable(&pc200->timer); + return pc200; } @@ -899,8 +899,6 @@ void pc200_speed_changed(void *p) cga_recalctimings(&pc200->cga); mda_recalctimings(&pc200->mda); - - setvidtime(pc200); } device_config_t pc200_config[] = 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_s3_virge.c b/src/vid_s3_virge.c index d0ffe56..60afc23 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; } } diff --git a/src/vid_sigma.c b/src/vid_sigma.c index e44a5f1..99235c2 100644 --- a/src/vid_sigma.c +++ b/src/vid_sigma.c @@ -138,9 +138,9 @@ typedef struct sigma_t uint16_t ma, maback; int oddeven; - int dispontime, dispofftime; - int vidtime; - + uint64_t dispontime, dispofftime; + pc_timer_t timer; + int firstline, lastline; int drawcursor; @@ -398,8 +398,8 @@ void sigma_recalctimings(sigma_t *sigma) _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); - sigma->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - sigma->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); + sigma->dispontime = (uint64_t)_dispontime; + sigma->dispofftime = (uint64_t)_dispofftime; } @@ -645,7 +645,7 @@ void sigma_poll(void *p) if (!sigma->linepos) { - sigma->vidtime += sigma->dispofftime; + timer_advance_u64(&sigma->timer, sigma->dispofftime); sigma->sigmastat |= STATUS_RETR_H; sigma->linepos = 1; oldsc = sigma->sc; @@ -727,7 +727,7 @@ void sigma_poll(void *p) } else { - sigma->vidtime += sigma->dispontime; + timer_advance_u64(&sigma->timer, sigma->dispontime); sigma->linepos = 0; if (sigma->vsynctime) { @@ -871,8 +871,8 @@ void *sigma_init() sigma->vram = malloc(0x8000 * 4); - timer_add(sigma_poll, &sigma->vidtime, TIMER_ALWAYS_ENABLED, sigma); - mem_mapping_add(&sigma->mapping, 0xb8000, 0x08000, + timer_add(&sigma->timer, sigma_poll, sigma, 1); + mem_mapping_add(&sigma->mapping, 0xb8000, 0x08000, sigma_read, NULL, NULL, sigma_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, sigma); diff --git a/src/vid_svga.c b/src/vid_svga.c index b98d0fe..538b131 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -435,8 +435,12 @@ 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; + 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]); @@ -480,7 +484,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; @@ -542,7 +546,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) @@ -733,8 +737,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; @@ -752,7 +756,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 852010f..08f5111 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..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; @@ -214,7 +223,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 +257,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; @@ -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; @@ -386,7 +388,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 @@ -2659,7 +2661,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 || @@ -3703,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*/ @@ -3716,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; @@ -3735,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; @@ -3764,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; @@ -3802,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; @@ -3871,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); @@ -5860,15 +5869,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 +5888,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 +6131,22 @@ 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; + { + 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: @@ -6208,7 +6222,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 +7454,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 +7624,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 +7641,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 a34c49d..1d80bf5 100644 --- a/src/vid_wy700.c +++ b/src/vid_wy700.c @@ -189,8 +189,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; @@ -489,8 +489,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; } @@ -758,7 +758,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; @@ -819,7 +819,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) @@ -867,7 +867,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) */ diff --git a/src/vt82c586b.c b/src/vt82c586b.c new file mode 100644 index 0000000..2540d5c --- /dev/null +++ b/src/vt82c586b.c @@ -0,0 +1,421 @@ +#include + +#include "ibm.h" +#include "ide.h" +#include "ide_sff8038i.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; + + 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) + { + 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 < 4) || (addr == 5) || (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 & 0x85; + 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; + } + + 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 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*/ + if ((addr < 4) || (addr == 5) || (addr == 6) + || (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 4: + vt82c586b.usb_regs[4] = val & 0x97; + usb_update_io_mapping(); + break; + case 7: + vt82c586b.usb_regs[7] = val & 0x7f; + break; + + 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) +{ + /*Read-only addresses*/ + if ((addr < 0xd) || (addr >= 0xe && addr < 0x40) + || (addr == 0x43) + || (addr == 0x48) + || (addr >= 0x4a && addr < 0x50) + || (addr >= 0x54)) + return; + + 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; + } +} + +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); + + sff_bus_master_init(vt82c586b.busmaster); + + ide_pri_disable(); + ide_sec_disable(); +} 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(); diff --git a/src/wx-config.c b/src/wx-config.c index 13f22cb..4b8d40e 100644 --- a/src/wx-config.c +++ b/src/wx-config.c @@ -557,7 +557,7 @@ int config_dlgsave(void* hdlg) if (has_been_inited) { - mem_resize(); + mem_alloc(); loadbios(); resetpchard(); } 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); 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 ); 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" diff --git a/src/x86.h b/src/x86.h index 1c15e1f..a9365c0 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,23 +1,226 @@ -uint16_t oldcs; -extern uint32_t rmdat32; -int oldcpl; +#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; -int tempc; -int output; -int firstrepcycle; +extern int trap; -uint32_t easeg,ealimit,ealimitw; +extern uint32_t use32; +extern int stack32; -int skipnextprint; -int inhlt; +extern uint8_t znptable8[256]; +extern uint16_t *mod1add[2][8]; +extern uint32_t *mod1seg[8]; -uint8_t opcode; -int noint; +extern int cgate16, cgate32; +extern int cpl_override; -uint16_t lastcs,lastpc; -int timetolive,keyboardtimer; +extern int x86_was_reset; + +extern int insc; +extern int fpucount; +extern float mips,flops; #define setznp168 setznp16 @@ -30,12 +233,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; \ @@ -43,34 +240,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 ((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 { @@ -87,22 +262,17 @@ extern uint32_t abrt_error; void x86_doabrt(int x86_abrt); -extern uint8_t opcode2; +extern int codegen_flat_ds; +extern int codegen_flat_ss; -extern uint16_t rds; -extern uint32_t rmdat32; - -extern int inscounts[256]; +extern uint32_t pccache; +extern uint8_t *pccache2; 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(); @@ -112,5 +282,19 @@ 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); +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); +void pmodeiret(int is32); + +void x86_int(int num); +void x86_int_sw(int num); +int x86_int_sw_rm(int num); + +int divl(uint32_t val); +int idivl(int32_t val); + +#endif diff --git a/src/x86_flags.h b/src/x86_flags.h index 3fa9cc5..49170f3 100644 --- a/src/x86_flags.h +++ b/src/x86_flags.h @@ -1,3 +1,5 @@ +extern int tempc; + enum { FLAGS_UNKNOWN, @@ -26,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, @@ -33,6 +43,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,10 +81,22 @@ 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_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: - return flags & Z_FLAG; + return cpu_state.flags & Z_FLAG; } return 0; } @@ -83,6 +113,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 +125,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,10 +137,18 @@ 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_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: - return flags & N_FLAG; + return cpu_state.flags & N_FLAG; } return 0; } @@ -139,10 +181,22 @@ 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_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: - return flags & P_FLAG; + return cpu_state.flags & P_FLAG; } return 0; } @@ -159,22 +213,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); @@ -192,9 +252,23 @@ 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 flags & V_FLAG; + return cpu_state.flags & V_FLAG; } return 0; } @@ -225,6 +299,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,9 +316,21 @@ 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_ROL8: + case FLAGS_ROL16: + case FLAGS_ROL32: + case FLAGS_ROR8: + case FLAGS_ROR16: + case FLAGS_ROR32: case FLAGS_UNKNOWN: - return flags & A_FLAG; + return cpu_state.flags & A_FLAG; } return 0; } @@ -244,23 +340,39 @@ 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); + 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; + 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: @@ -278,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: @@ -286,7 +410,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 +433,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,12 +448,21 @@ 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; } } +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; @@ -352,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; @@ -447,67 +584,47 @@ 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; - 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_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; - 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_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; - 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_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; - 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; -} - -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; - 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_op1 = a; + cpu_state.flags_op2 = b; + cpu_state.flags_res = a - (b + tempc); + cpu_state.flags_op = FLAGS_SBC32; } +extern void cpu_386_flags_extract(); +extern void cpu_386_flags_rebuild(); 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..9f852d5 --- /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_32(fetchdat); + ILLEGAL_ON(cpu_mod == 3); + + CLOCK_CYCLES(1); + return 0; +} + +static int opFEMMS(uint32_t fetchdat) +{ + ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX)); + 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); +} 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..06a33e2 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) @@ -134,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; } @@ -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) @@ -165,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; } @@ -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_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 272d22b..7261fef 100644 --- a/src/x86_ops_bit.h +++ b/src/x86_ops_bit.h @@ -3,11 +3,12 @@ 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(); - 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); @@ -18,11 +19,12 @@ 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(); - 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); @@ -33,11 +35,12 @@ 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(); - 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); @@ -48,11 +51,12 @@ 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(); - 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); @@ -66,14 +70,16 @@ 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; \ 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); \ @@ -85,14 +91,16 @@ 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; \ 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); \ @@ -104,14 +112,16 @@ 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; \ 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); \ @@ -123,14 +133,16 @@ 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; \ 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); \ @@ -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); @@ -155,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; @@ -177,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; @@ -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); @@ -197,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; @@ -219,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; @@ -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); @@ -240,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; @@ -262,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; @@ -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); @@ -282,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; @@ -304,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 0c1ee04..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) { @@ -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..8b6087d 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); \ @@ -17,24 +16,23 @@ 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) \ 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); \ @@ -46,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; } \ } @@ -104,6 +102,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 +111,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 +120,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 +132,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 +143,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,16 +154,20 @@ static int opFF_w_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - oxpc = cpu_state.pc; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + 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(); 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 +193,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 +202,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 +211,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 +223,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 +234,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,16 +245,20 @@ static int opFF_w_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - oxpc = cpu_state.pc; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + 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(); 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 +285,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 +294,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 +303,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 +315,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 +326,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,16 +337,20 @@ static int opFF_l_a16(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - oxpc = cpu_state.pc; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + 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(); 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 +376,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 +385,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 +394,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 +406,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 +417,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,16 +428,20 @@ static int opFF_l_a32(uint32_t fetchdat) PREFETCH_FLUSH(); break; case 0x28: /*JMP far*/ - oxpc = cpu_state.pc; + if (cpu_mod != 3) + SEG_CHECK_READ(cpu_state.ea_seg); + 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(); 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_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_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_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_jump.h b/src/x86_ops_jump.h index 292102a..94cad2d 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,8 @@ static int opLOOPNE_w(uint32_t fetchdat) if (CX && !ZF_SET()) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -110,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; @@ -126,6 +133,8 @@ static int opLOOPE_w(uint32_t fetchdat) if (CX && ZF_SET()) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -141,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; @@ -157,6 +168,8 @@ static int opLOOP_w(uint32_t fetchdat) if (CX) { cpu_state.pc += offset; + if (!(cpu_state.op32 & 0x100)) + cpu_state.pc &= 0xffff; CPU_BLOCK_END(); PREFETCH_FLUSH(); return 1; @@ -172,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; @@ -186,6 +201,8 @@ static int opJCXZ(uint32_t fetchdat) if (!CX) { 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); @@ -202,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); @@ -217,6 +236,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 +248,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); @@ -248,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(); @@ -260,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(); @@ -274,6 +296,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); diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index 43c0d97..aa81a2c 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); @@ -81,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; @@ -90,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; @@ -105,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 @@ -128,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 @@ -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); @@ -181,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; @@ -190,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; @@ -205,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 @@ -228,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 @@ -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); @@ -286,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; @@ -296,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; @@ -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); @@ -380,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; @@ -390,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; @@ -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); @@ -474,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; @@ -484,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; @@ -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); @@ -544,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; @@ -554,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; @@ -584,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--; @@ -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; @@ -700,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); @@ -743,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); @@ -761,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; @@ -817,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; @@ -827,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; @@ -848,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); @@ -875,14 +917,15 @@ 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(); + oldcpl = CPL; CLOCK_CYCLES(350); return 0; @@ -903,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); @@ -916,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 4397a39..95ed658 100644 --- a/src/x86_ops_mmx.h +++ b/src/x86_ops_mmx.h @@ -11,12 +11,13 @@ } \ else \ { \ + SEG_CHECK_READ(cpu_state.ea_seg); \ src.q = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; \ CLOCK_CYCLES(2); \ } #define MMX_ENTER() \ - if (!cpu_hasMMX) \ + if (!cpu_has_feature(CPU_FEATURE_MMX)) \ { \ cpu_state.pc = cpu_state.oldpc; \ x86illegal(); \ @@ -31,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_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_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; 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_ctrl.h b/src/x86_ops_mov_ctrl.h index 7b21bf7..962d1b2 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); @@ -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; @@ -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); @@ -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; @@ -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); @@ -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; @@ -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); @@ -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; @@ -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_mov_seg.h b/src/x86_ops_mov_seg.h index 5153bb1..54a30cb 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,34 +145,35 @@ 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) { 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; } @@ -177,34 +186,35 @@ 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) { 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; } @@ -220,9 +230,10 @@ 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; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -235,9 +246,10 @@ 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; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -251,9 +263,10 @@ 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; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -267,9 +280,10 @@ 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; + loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -283,9 +297,10 @@ 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; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -298,9 +313,10 @@ 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; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].w = addr; CLOCK_CYCLES(7); @@ -314,9 +330,10 @@ 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; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -330,9 +347,10 @@ 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; + loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; cpu_state.regs[cpu_reg].l = addr; CLOCK_CYCLES(7); @@ -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; \ @@ -407,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_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_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(); diff --git a/src/x86_ops_mul.h b/src/x86_ops_mul.h index 9a316b9..5971140 100644 --- a/src/x86_ops_mul.h +++ b/src/x86_ops_mul.h @@ -4,14 +4,16 @@ 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; 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); @@ -24,14 +26,16 @@ 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; 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); @@ -45,14 +49,16 @@ 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; 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); @@ -65,14 +71,16 @@ 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; 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); @@ -86,15 +94,17 @@ 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; 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); @@ -107,15 +117,17 @@ 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; 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); @@ -129,14 +141,17 @@ 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; 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); @@ -149,14 +164,17 @@ 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; 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); @@ -171,12 +189,15 @@ 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; 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); @@ -187,12 +208,15 @@ 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; 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); @@ -204,12 +228,15 @@ 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; 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); @@ -220,12 +247,15 @@ 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; 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 288d1bb..5301ef3 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; @@ -12,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); @@ -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(); @@ -35,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); @@ -53,11 +57,13 @@ 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; \ \ 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) \ { \ @@ -65,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; \ @@ -77,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; \ @@ -103,10 +109,12 @@ 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(); \ - 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) \ @@ -125,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) \ { \ @@ -163,22 +171,28 @@ 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); 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); 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); @@ -199,12 +213,14 @@ 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); 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,9 +244,11 @@ 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; + cpu_state.flags &= ~Z_FLAG; if (!(sel & 0xfffc)) return 0; /*Null selector*/ cpl_override = 1; valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); @@ -243,14 +261,16 @@ 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; 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; + 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 +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; @@ -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) @@ -318,12 +342,14 @@ 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); 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; @@ -335,12 +361,14 @@ 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); 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); @@ -360,12 +390,14 @@ 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); 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) @@ -385,12 +417,13 @@ 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); 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_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 66587ef..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) \ { \ @@ -9,12 +7,13 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) { \ uint8_t temp; \ \ - check_io_perm(DX); \ + 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; \ \ - 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; \ @@ -36,13 +35,14 @@ static int opREP_INSW_ ## size(uint32_t fetchdat) { \ uint16_t temp; \ \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ check_io_perm(DX); \ check_io_perm(DX+1); \ 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; \ @@ -64,6 +64,7 @@ static int opREP_INSL_ ## size(uint32_t fetchdat) { \ uint32_t temp; \ \ + SEG_CHECK_WRITE(&cpu_state.seg_es); \ check_io_perm(DX); \ check_io_perm(DX+1); \ check_io_perm(DX+2); \ @@ -71,8 +72,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; \ @@ -93,11 +94,13 @@ 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--; \ - else SRC_REG++; \ + if (cpu_state.flags & D_FLAG) SRC_REG--; \ + else SRC_REG++; \ CNT_REG--; \ cycles -= 14; \ reads++; writes++; total_cycles += 14; \ @@ -117,12 +120,14 @@ 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); \ - 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; \ @@ -142,14 +147,16 @@ 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); \ 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; \ @@ -170,16 +177,21 @@ 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(&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; \ \ - 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++; \ @@ -203,16 +215,21 @@ 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(&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; \ \ - 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++; \ @@ -236,16 +253,21 @@ 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(&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; \ \ - 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++; \ @@ -271,12 +293,14 @@ 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(&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++; \ + if (cpu_state.flags & D_FLAG) DEST_REG--; \ + else DEST_REG++; \ CNT_REG--; \ cycles -= is486 ? 4 : 5; \ writes++; total_cycles += is486 ? 4 : 5; \ @@ -299,12 +323,14 @@ 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(&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; \ + 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; \ @@ -327,12 +353,14 @@ 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(&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; \ + 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; \ @@ -356,11 +384,13 @@ 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; \ - 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; \ @@ -383,11 +413,13 @@ 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; \ - 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; \ @@ -410,11 +442,13 @@ 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; \ - 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; \ @@ -441,11 +475,14 @@ 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(&cpu_state.seg_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++; } \ + 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; \ @@ -468,11 +505,14 @@ 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(&cpu_state.seg_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; } \ + 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; \ @@ -495,11 +535,14 @@ 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(&cpu_state.seg_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; } \ + 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; \ @@ -523,13 +566,15 @@ 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(&cpu_state.seg_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ 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; \ @@ -554,13 +599,15 @@ 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(&cpu_state.seg_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ 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; \ @@ -585,13 +632,15 @@ 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(&cpu_state.seg_es); \ while ((CNT_REG > 0) && (FV == tempz)) \ { \ 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..70ac327 100644 --- a/src/x86_ops_ret.h +++ b/src/x86_ops_ret.h @@ -1,10 +1,9 @@ #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; \ } \ - oxpc = cpu_state.pc; \ if (stack32) \ { \ cpu_state.pc = readmemw(ss, ESP); \ @@ -21,12 +20,11 @@ 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; \ } \ - oxpc = cpu_state.pc; \ if (stack32) \ { \ cpu_state.pc = readmeml(ss, ESP); \ @@ -94,7 +92,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; @@ -108,19 +106,18 @@ static int opIRET_286(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; if (stack32) { 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 +136,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 +148,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; @@ -184,19 +181,18 @@ static int opIRET(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; if (stack32) { 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 +212,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; @@ -230,21 +226,20 @@ static int opIRETD(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; if (stack32) { 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_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..0d6d193 100644 --- a/src/x86_ops_shift.h +++ b/src/x86_ops_shift.h @@ -6,36 +6,21 @@ 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; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \ + temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \ + seteab(temp); if (cpu_state.abrt) return 1; \ + 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*/ \ - while (c > 0) \ - { \ - temp2 = temp & 1; \ - temp >>= 1; \ - if (temp2) temp |= 0x80; \ - 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; \ + temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \ + 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; \ 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 +30,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 +47,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; \ @@ -98,36 +83,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; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 15)) 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; \ + 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, c*/ \ - while (c > 0) \ - { \ - temp2 = temp & 1; \ - temp >>= 1; \ - if (temp2) temp |= 0x8000; \ - 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; \ - 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; \ + 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; \ 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 +107,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 +124,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; \ @@ -190,33 +160,18 @@ 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; \ - flags &= ~(C_FLAG | V_FLAG); \ - if (temp2) flags |= C_FLAG; \ - if ((flags & C_FLAG) ^ (temp >> 31)) 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; \ + 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, c*/ \ - while (c > 0) \ - { \ - temp2 = temp & 1; \ - temp >>= 1; \ - if (temp2) temp |= 0x80000000; \ - 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; \ - 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; \ + 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; \ case 0x10: /*RCL l, c*/ \ temp2 = CF_SET(); \ @@ -229,14 +184,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 +201,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; \ @@ -281,6 +236,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 +251,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 +266,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 +281,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 +296,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 +311,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 +327,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 +340,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 +353,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 +366,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 +379,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 +392,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 +406,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 +420,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 +434,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 +448,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 +462,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 +476,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); @@ -505,7 +496,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() \ @@ -517,7 +508,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; \ } @@ -531,7 +522,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() \ @@ -543,7 +534,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) \ @@ -552,6 +543,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 +557,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 +571,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 +585,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..b7e827b 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) { @@ -462,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) @@ -473,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; @@ -493,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 b08460b..433d683 100644 --- a/src/x86_ops_string.h +++ b/src/x86_ops_string.h @@ -1,19 +1,27 @@ 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(&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; } 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(&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; @@ -21,20 +29,28 @@ 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(&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; } 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(&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; @@ -42,20 +58,28 @@ 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(&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; } 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(&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; @@ -64,22 +88,30 @@ 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(&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); - 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; } 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(&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); - 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; @@ -87,22 +119,30 @@ 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(&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); - 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; } 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(&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); - 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; @@ -110,22 +150,30 @@ 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(&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); - 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; } 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(&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); - 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; @@ -133,18 +181,20 @@ static int opCMPSL_a32(uint32_t fetchdat) 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; } 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; @@ -152,18 +202,20 @@ static int opSTOSB_a32(uint32_t fetchdat) 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; } 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; @@ -171,18 +223,20 @@ static int opSTOSW_a32(uint32_t fetchdat) 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; } 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; @@ -191,20 +245,26 @@ 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++; + if (cpu_state.flags & D_FLAG) SI--; + else SI++; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); return 0; } 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++; + if (cpu_state.flags & D_FLAG) ESI--; + else ESI++; CLOCK_CYCLES(5); PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); return 0; @@ -212,20 +272,26 @@ 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; + 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; } 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; + 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; @@ -233,20 +299,26 @@ 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; + 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; } 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; + 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; @@ -255,20 +327,26 @@ 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(&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; } 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(&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; @@ -276,20 +354,26 @@ 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(&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; } 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(&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; @@ -297,20 +381,26 @@ 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(&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; } 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(&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; @@ -319,11 +409,13 @@ static int opSCASL_a32(uint32_t fetchdat) static int opINSB_a16(uint32_t fetchdat) { uint8_t temp; + + SEG_CHECK_WRITE(&cpu_state.seg_es); 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; @@ -331,11 +423,13 @@ static int opINSB_a16(uint32_t fetchdat) static int opINSB_a32(uint32_t fetchdat) { uint8_t temp; + + SEG_CHECK_WRITE(&cpu_state.seg_es); 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; @@ -344,12 +438,14 @@ static int opINSB_a32(uint32_t fetchdat) static int opINSW_a16(uint32_t fetchdat) { uint16_t temp; + + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); 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; @@ -357,12 +453,14 @@ static int opINSW_a16(uint32_t fetchdat) static int opINSW_a32(uint32_t fetchdat) { uint16_t temp; + + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); 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; @@ -371,14 +469,16 @@ static int opINSW_a32(uint32_t fetchdat) static int opINSL_a16(uint32_t fetchdat) { uint32_t temp; + + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); 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; @@ -386,14 +486,16 @@ static int opINSL_a16(uint32_t fetchdat) static int opINSL_a32(uint32_t fetchdat) { uint32_t temp; + + SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); 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; @@ -401,10 +503,13 @@ 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++; + 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); @@ -412,10 +517,13 @@ 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++; + 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); @@ -424,11 +532,14 @@ 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; - 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); @@ -436,11 +547,14 @@ 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; - 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); @@ -449,13 +563,16 @@ 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); 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); @@ -463,13 +580,16 @@ 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); 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/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/x86seg.c b/src/x86seg.c index 9840c0b..21a3778 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,15 +58,13 @@ void x86abort(const char *format, ...) exit(-1); } -uint8_t opcode2; - static void seg_reset(x86seg *s) { s->access = (0 << 5) | 2; 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,20 +80,19 @@ 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) { // 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) @@ -115,22 +110,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; - oxpc=cpu_state.pc; + cpu_state.flags &= ~I_FLAG; + cpu_state.flags &= ~T_FLAG; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); return; @@ -164,8 +158,6 @@ void x86_doabrt(int x86_abrt) SP-=4; } } -// ingpf = 0; -// abrt = gpf = 1; } void x86gpf(char *s, uint16_t error) { @@ -238,14 +230,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; @@ -309,22 +301,22 @@ 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; int dpl; - if (msw&1 && !(eflags&VM_FLAG)) + if (msw&1 && !(cpu_state.eflags&VM_FLAG)) { // intcount++; if (!(seg&~3)) { - if (s==&_ss) + if (s==&cpu_state.seg_ss) { pclog("SS selector = NULL!\n"); x86ss(NULL,0); - return; + return 1; // dumpregs(); // exit(-1); } @@ -332,10 +324,10 @@ 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; + return 0; } // if (s==&_ss) pclog("Load SS %04X\n",seg); // pclog("Protected mode seg load!\n"); @@ -344,12 +336,12 @@ void 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); x86gpf(NULL,seg&~3); - return; + return 1; } addr+=ldt.base; } @@ -361,7 +353,7 @@ void loadseg(uint16_t seg, x86seg *s) // dumpregs(); // exit(-1); x86gpf(NULL,seg&~3); - return; + return 1; } addr+=gdt.base; } @@ -369,22 +361,22 @@ 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==&_ss) + if (s==&cpu_state.seg_ss) { if (!(seg&~3)) { 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,18 +386,18 @@ 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]); } - 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); @@ -420,7 +412,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 +420,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); @@ -453,9 +445,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,29 +455,31 @@ 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; else cpu_cur_status |= CPU_STATUS_NOTFLATSS; } + + return cpu_state.abrt; } #define DPL ((segdat[2]>>13)&3) @@ -497,7 +491,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(); @@ -547,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) @@ -568,9 +562,10 @@ 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(); + oldcpl = CPL; #ifdef CS_ACCESSED cpl_override = 1; @@ -590,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; } @@ -601,25 +596,26 @@ 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 (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; } } -void loadcsjmp(uint16_t seg, uint32_t oxpc) +void loadcsjmp(uint16_t seg, uint32_t old_pc) { uint16_t segdat[4]; uint32_t addr; 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)) { @@ -693,8 +689,9 @@ 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(); + oldcpl = CPL; /* if (segdat[3]&0x40) { use32=0x300; @@ -725,7 +722,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))) { @@ -797,8 +793,9 @@ 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(); + oldcpl = CPL; set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -821,11 +818,11 @@ 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); - flags &= ~NT_FLAG; + cpu_state.flags &= ~NT_FLAG; cpl_override=0; // case 0xB00: /*386 Busy task gate*/ // if (optype==JMP) pclog("Task switch!\n"); @@ -833,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(); @@ -846,14 +843,15 @@ 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 (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; } } @@ -926,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; @@ -939,7 +937,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); @@ -1028,8 +1026,9 @@ 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(); + oldcpl = CPL; /* if (segdat[3]&0x40) { use32=0x300; @@ -1205,7 +1204,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,8 +1215,9 @@ 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(); + oldcpl = CPL; set_use32(segdat[3]&0x40); cpu_state.pc=newpc; @@ -1258,8 +1258,6 @@ void loadcscall(uint16_t seg) } } // x86abort("Call gate with count %i\n",count); -// PUSHL(oldcs); -// PUSHL(oldpc); if (cpu_state.abrt) return; } else { @@ -1296,8 +1294,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; @@ -1309,19 +1305,10 @@ 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(&_cs, segdat); + 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; @@ -1343,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; @@ -1363,14 +1350,15 @@ 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 (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; } } @@ -1381,7 +1369,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(); @@ -1495,9 +1483,10 @@ 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(); + oldcpl = CPL; set_use32(segdat[3] & 0x40); // pclog("CPL=RPL return to %04X:%08X\n",CS,pc); @@ -1630,7 +1619,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,27 +1636,23 @@ 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(); + oldcpl = CPL; 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("CPL=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); PUSHL(DS); PUSHL(ES); if (cpu_state.abrt) return; - loadseg(0,&_ds); - loadseg(0,&_es); - loadseg(0,&_fs); - loadseg(0,&_gs); + loadseg(0,&cpu_state.seg_ds); + loadseg(0,&cpu_state.seg_es); + loadseg(0,&cpu_state.seg_fs); + loadseg(0,&cpu_state.seg_gs); } 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); @@ -1919,7 +1904,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); @@ -1927,7 +1912,7 @@ void pmodeint(int num, int soft) // if (output) pclog("16Stack %04X:%08X\n",SS,ESP); } cpl_override=0; - _cs.access=0; + cpu_state.seg_cs.access=0; cycles -= timing_int_pm_outer - timing_int_pm; // pclog("Non-confirming int gate, CS = %04X\n"); break; @@ -1945,7 +1930,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); @@ -1962,7 +1947,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); @@ -1975,11 +1960,12 @@ void pmodeint(int num, int soft) x86gpf(NULL,seg&~3); return; } - do_seg_load(&_cs, segdat2); + do_seg_load(&cpu_state.seg_cs, segdat2); CS = (seg & ~3) | new_cpl; - _cs.access = (_cs.access & ~(3 << 5)) | (new_cpl << 5); + 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); @@ -1991,14 +1977,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; @@ -2063,7 +2049,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) @@ -2072,7 +2058,6 @@ void pmodeiret(int is32) x86gpf(NULL,0); return; } - oxpc=cpu_state.pc; if (is32) { newpc=POPL(); @@ -2086,12 +2071,12 @@ 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; + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempflags & 0xCFD5) | 2; cycles -= timing_iret_rm; return; } @@ -2100,7 +2085,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); @@ -2130,7 +2115,6 @@ void pmodeiret(int is32) cpl_override=0; return; } - oxpc=cpu_state.pc; flagmask=0xFFFF; if (CPL) flagmask&=~0x3000; if (IOPL>16; + cpu_state.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(); + oldcpl = CPL; 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; - 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; @@ -2292,9 +2277,10 @@ 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(); + oldcpl = CPL; set_use32(segdat[3]&0x40); #ifdef CS_ACCESSED @@ -2392,7 +2378,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,20 +2394,21 @@ 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(); + oldcpl = CPL; 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; - 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"); } @@ -2475,13 +2462,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); @@ -2554,8 +2541,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); @@ -2572,7 +2559,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); @@ -2643,8 +2630,9 @@ 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(); + oldcpl = CPL; set_use32(segdat2[3] & 0x40); cpu_cur_status &= ~CPU_STATUS_V86; } @@ -2659,15 +2647,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); } @@ -2693,12 +2681,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); @@ -2758,7 +2747,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); @@ -2842,8 +2831,9 @@ 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(); + oldcpl = CPL; set_use32(0); EAX=new_eax | 0xFFFF0000; @@ -2856,15 +2846,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); diff --git a/src/x87.c b/src/x87.c index 25ce726..44f22e0 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() @@ -56,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.h b/src/x87.h index 790b6eb..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; @@ -10,7 +15,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 +24,14 @@ 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) + +#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.h b/src/x87_ops.h index dc15866..1208854 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -7,26 +7,21 @@ 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 \ { \ 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; \ @@ -38,9 +33,9 @@ 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.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0; + cpu_state.TOP--; + cpu_state.ST[cpu_state.TOP&7] = i; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; } static inline void x87_push_u64(uint64_t i) @@ -53,16 +48,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.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0; + 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]; - cpu_state.tag[cpu_state.TOP&7] = 3; - cpu_state.TOP=(cpu_state.TOP+1)&7; + double t = cpu_state.ST[cpu_state.TOP&7]; + cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; + cpu_state.TOP++; return t; } @@ -186,13 +181,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 6723bd1..f52abe8 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -4,13 +4,14 @@ 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]); \ 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&7] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -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,9 +45,10 @@ 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; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -53,9 +57,10 @@ 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; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -64,9 +69,10 @@ 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; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(11); \ return 0; \ } \ @@ -75,9 +81,10 @@ 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; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -86,9 +93,10 @@ 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; \ + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ CLOCK_CYCLES(8); \ return 0; \ } @@ -113,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&7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -123,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; } @@ -133,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; @@ -198,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; } @@ -210,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; @@ -224,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&7] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -234,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; } @@ -244,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; @@ -256,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&7] = TAG_VALID; CLOCK_CYCLES(73); return 0; } @@ -266,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; } @@ -276,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; @@ -288,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&7] = TAG_VALID; CLOCK_CYCLES(16); return 0; } @@ -298,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; } @@ -308,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; @@ -320,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&7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -330,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; } @@ -340,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; @@ -352,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&7] = TAG_VALID; CLOCK_CYCLES(8); return 0; } @@ -362,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; } @@ -372,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; @@ -407,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; } @@ -419,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; diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h index 09bbf82..96c18e6 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,12 +90,13 @@ 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)); x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] |= 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; @@ -99,12 +106,13 @@ 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)); x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] |= 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; @@ -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,9 +178,10 @@ 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; + 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; @@ -183,9 +194,10 @@ 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; + 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; @@ -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..f22d618 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -32,12 +32,13 @@ 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 = 0x0303030303030303ll; + *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; cpu_state.ismmx = 0; CLOCK_CYCLES(17); + CPU_BLOCK_END(); return 0; } @@ -47,7 +48,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; } @@ -86,7 +87,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 +96,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; @@ -127,6 +128,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 +136,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; } @@ -142,7 +145,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)) { @@ -274,9 +277,9 @@ 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 = 0x0303030303030303ll; + *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; cpu_state.ismmx = 0; @@ -287,6 +290,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 +298,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,8 +307,9 @@ 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)); + seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -311,8 +317,9 @@ 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)); + seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -329,8 +336,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; } @@ -346,11 +353,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); @@ -363,7 +370,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&7] = TAG_VALID; CLOCK_CYCLES(6); return 0; } @@ -374,7 +381,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&7] = TAG_VALID; CLOCK_CYCLES(3); return 0; } @@ -397,7 +404,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; @@ -471,7 +478,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; } @@ -482,7 +489,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&7] = TAG_VALID; CLOCK_CYCLES(200); return 0; } @@ -493,7 +500,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; @@ -505,7 +512,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; @@ -517,7 +524,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&7] = TAG_VALID; x87_push(1.0); cpu_state.npxs &= ~C2; CLOCK_CYCLES(235); @@ -530,7 +537,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; @@ -541,7 +548,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; } @@ -551,7 +558,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; } @@ -564,7 +571,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&7] = TAG_VALID; if (fplog) pclog("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; @@ -581,7 +588,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&7] = TAG_VALID; if (fplog) pclog("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; @@ -597,7 +604,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&7] = TAG_VALID; CLOCK_CYCLES(83); return 0; } @@ -610,7 +617,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&7] = TAG_VALID; x87_push(cos(td)); cpu_state.npxs &= ~C2; CLOCK_CYCLES(330); @@ -623,7 +630,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&7] = TAG_VALID; if (fplog) pclog("%g\n", ST(0)); CLOCK_CYCLES(21); return 0; @@ -637,7 +644,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&7] = TAG_VALID; CLOCK_CYCLES(30); return 0; } @@ -648,7 +655,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&7] = TAG_VALID; cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -660,7 +667,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&7] = TAG_VALID; cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -676,7 +683,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; @@ -684,7 +691,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; @@ -698,6 +705,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 +713,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,11 +723,12 @@ 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; 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; } @@ -727,11 +737,12 @@ 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; 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; } @@ -784,6 +795,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 +803,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 +812,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 +822,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); @@ -822,8 +837,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); \