First stage of dynamic recompiler rewrite.
Basic IR generation calls C implementation of all instructions. Backend generation implemented for x86, x86-64, ARM and ARM64.
This commit is contained in:
parent
e6dce0920b
commit
03fe25d818
46 changed files with 4134 additions and 17767 deletions
24
Makefile.in
24
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@
|
# @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
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
|
@ -133,7 +133,7 @@ am__recursive_targets = \
|
||||||
$(RECURSIVE_CLEAN_TARGETS) \
|
$(RECURSIVE_CLEAN_TARGETS) \
|
||||||
$(am__extra_recursive_targets)
|
$(am__extra_recursive_targets)
|
||||||
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
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)
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
# Read a list of newline-separated strings from the standard input,
|
# Read a list of newline-separated strings from the standard input,
|
||||||
# and print each of them once, without duplicates. Input order is
|
# and print each of them once, without duplicates. Input order is
|
||||||
|
|
@ -308,7 +308,6 @@ pdfdir = @pdfdir@
|
||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
|
@ -342,8 +341,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
echo ' $(SHELL) ./config.status'; \
|
echo ' $(SHELL) ./config.status'; \
|
||||||
$(SHELL) ./config.status;; \
|
$(SHELL) ./config.status;; \
|
||||||
*) \
|
*) \
|
||||||
echo ' 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__depfiles_maybe);; \
|
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
|
||||||
esac;
|
esac;
|
||||||
|
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
$(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 TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
-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)
|
$(am__remove_distdir)
|
||||||
test -d "$(distdir)" || mkdir "$(distdir)"
|
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
|
@ -526,7 +528,7 @@ distdir: $(DISTFILES)
|
||||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||||
|| chmod -R a+r "$(distdir)"
|
|| chmod -R a+r "$(distdir)"
|
||||||
dist-gzip: 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)
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
dist-bzip2: distdir
|
dist-bzip2: distdir
|
||||||
|
|
@ -552,7 +554,7 @@ dist-shar: distdir
|
||||||
@echo WARNING: "Support for shar distribution archives is" \
|
@echo WARNING: "Support for shar distribution archives is" \
|
||||||
"deprecated." >&2
|
"deprecated." >&2
|
||||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&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)
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
dist-zip: distdir
|
dist-zip: distdir
|
||||||
|
|
@ -570,7 +572,7 @@ dist dist-all:
|
||||||
distcheck: dist
|
distcheck: dist
|
||||||
case '$(DIST_ARCHIVES)' in \
|
case '$(DIST_ARCHIVES)' in \
|
||||||
*.tar.gz*) \
|
*.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*) \
|
*.tar.bz2*) \
|
||||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||||
*.tar.lz*) \
|
*.tar.lz*) \
|
||||||
|
|
@ -580,7 +582,7 @@ distcheck: dist
|
||||||
*.tar.Z*) \
|
*.tar.Z*) \
|
||||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||||
*.shar.gz*) \
|
*.shar.gz*) \
|
||||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
|
||||||
*.zip*) \
|
*.zip*) \
|
||||||
unzip $(distdir).zip ;;\
|
unzip $(distdir).zip ;;\
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
380
configure
vendored
380
configure
vendored
|
|
@ -590,6 +590,8 @@ LTLIBOBJS
|
||||||
LIBOBJS
|
LIBOBJS
|
||||||
OS_MACOSX_FALSE
|
OS_MACOSX_FALSE
|
||||||
OS_MACOSX_TRUE
|
OS_MACOSX_TRUE
|
||||||
|
OS_OTHER_FALSE
|
||||||
|
OS_OTHER_TRUE
|
||||||
OS_WINDOWS_FALSE
|
OS_WINDOWS_FALSE
|
||||||
OS_WINDOWS_TRUE
|
OS_WINDOWS_TRUE
|
||||||
OS_LINUX_FALSE
|
OS_LINUX_FALSE
|
||||||
|
|
@ -622,6 +624,10 @@ USE_NETWORKING_FALSE
|
||||||
USE_NETWORKING_TRUE
|
USE_NETWORKING_TRUE
|
||||||
USE_WX_FALSE
|
USE_WX_FALSE
|
||||||
USE_WX_TRUE
|
USE_WX_TRUE
|
||||||
|
CPU_ARM64_FALSE
|
||||||
|
CPU_ARM64_TRUE
|
||||||
|
CPU_ARM_FALSE
|
||||||
|
CPU_ARM_TRUE
|
||||||
CPU_X86_64_FALSE
|
CPU_X86_64_FALSE
|
||||||
CPU_X86_64_TRUE
|
CPU_X86_64_TRUE
|
||||||
CPU_I386_FALSE
|
CPU_I386_FALSE
|
||||||
|
|
@ -641,7 +647,6 @@ am__nodep
|
||||||
AMDEPBACKSLASH
|
AMDEPBACKSLASH
|
||||||
AMDEP_FALSE
|
AMDEP_FALSE
|
||||||
AMDEP_TRUE
|
AMDEP_TRUE
|
||||||
am__quote
|
|
||||||
am__include
|
am__include
|
||||||
DEPDIR
|
DEPDIR
|
||||||
OBJEXT
|
OBJEXT
|
||||||
|
|
@ -705,7 +710,6 @@ infodir
|
||||||
docdir
|
docdir
|
||||||
oldincludedir
|
oldincludedir
|
||||||
includedir
|
includedir
|
||||||
runstatedir
|
|
||||||
localstatedir
|
localstatedir
|
||||||
sharedstatedir
|
sharedstatedir
|
||||||
sysconfdir
|
sysconfdir
|
||||||
|
|
@ -724,7 +728,8 @@ PACKAGE_VERSION
|
||||||
PACKAGE_TARNAME
|
PACKAGE_TARNAME
|
||||||
PACKAGE_NAME
|
PACKAGE_NAME
|
||||||
PATH_SEPARATOR
|
PATH_SEPARATOR
|
||||||
SHELL'
|
SHELL
|
||||||
|
am__quote'
|
||||||
ac_subst_files=''
|
ac_subst_files=''
|
||||||
ac_user_opts='
|
ac_user_opts='
|
||||||
enable_option_checking
|
enable_option_checking
|
||||||
|
|
@ -798,7 +803,6 @@ datadir='${datarootdir}'
|
||||||
sysconfdir='${prefix}/etc'
|
sysconfdir='${prefix}/etc'
|
||||||
sharedstatedir='${prefix}/com'
|
sharedstatedir='${prefix}/com'
|
||||||
localstatedir='${prefix}/var'
|
localstatedir='${prefix}/var'
|
||||||
runstatedir='${localstatedir}/run'
|
|
||||||
includedir='${prefix}/include'
|
includedir='${prefix}/include'
|
||||||
oldincludedir='/usr/include'
|
oldincludedir='/usr/include'
|
||||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||||
|
|
@ -1051,15 +1055,6 @@ do
|
||||||
| -silent | --silent | --silen | --sile | --sil)
|
| -silent | --silent | --silen | --sile | --sil)
|
||||||
silent=yes ;;
|
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)
|
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||||
ac_prev=sbindir ;;
|
ac_prev=sbindir ;;
|
||||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||||
|
|
@ -1197,7 +1192,7 @@ fi
|
||||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||||
libdir localedir mandir runstatedir
|
libdir localedir mandir
|
||||||
do
|
do
|
||||||
eval ac_val=\$$ac_var
|
eval ac_val=\$$ac_var
|
||||||
# Remove trailing slashes.
|
# Remove trailing slashes.
|
||||||
|
|
@ -1350,7 +1345,6 @@ Fine tuning of the installation directories:
|
||||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
|
||||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||||
--includedir=DIR C header files [PREFIX/include]
|
--includedir=DIR C header files [PREFIX/include]
|
||||||
--oldincludedir=DIR C header files for non-gcc [/usr/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),
|
# Find a good install program. We prefer a C program (faster),
|
||||||
# so one script is as good as another. But avoid the broken or
|
# 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
|
# For better backward compatibility. To be removed once Automake 1.9.x
|
||||||
# dies out for good. For more background, see:
|
# dies out for good. For more background, see:
|
||||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||||
mkdir_p='$(MKDIR_P)'
|
mkdir_p='$(MKDIR_P)'
|
||||||
|
|
||||||
# We need awk for the "check" target (and possibly the TAP driver). The
|
# 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.
|
Aborting the configuration process, to ensure you take notice of the issue.
|
||||||
|
|
||||||
You can download and install GNU coreutils to get an 'rm' implementation
|
You can download and install GNU coreutils to get an 'rm' implementation
|
||||||
that behaves properly: <http://www.gnu.org/software/coreutils/>.
|
that behaves properly: <https://www.gnu.org/software/coreutils/>.
|
||||||
|
|
||||||
If you want to complete the configuration process using your problematic
|
If you want to complete the configuration process using your problematic
|
||||||
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
|
'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"
|
ac_config_commands="$ac_config_commands depfiles"
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
|
||||||
am_make=${MAKE-make}
|
$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
|
||||||
cat > confinc << 'END'
|
cat > confinc.mk << 'END'
|
||||||
am__doit:
|
am__doit:
|
||||||
@echo this is the am__doit target
|
@echo this is the am__doit target >confinc.out
|
||||||
.PHONY: am__doit
|
.PHONY: am__doit
|
||||||
END
|
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__include="#"
|
||||||
am__quote=
|
am__quote=
|
||||||
_am_result=none
|
# BSD make does it like this.
|
||||||
# First try GNU make style include.
|
echo '.include "confinc.mk" # ignored' > confmf.BSD
|
||||||
echo "include confinc" > confmf
|
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
|
||||||
# Ignore all kinds of additional output from 'make'.
|
echo 'include confinc.mk # ignored' > confmf.GNU
|
||||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
_am_result=no
|
||||||
*the\ am__doit\ target*)
|
for s in GNU BSD; do
|
||||||
am__include=include
|
{ echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
|
||||||
am__quote=
|
(${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
|
||||||
_am_result=GNU
|
ac_status=$?
|
||||||
;;
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
esac
|
(exit $ac_status); }
|
||||||
# Now try BSD make style include.
|
case $?:`cat confinc.out 2>/dev/null` in #(
|
||||||
if test "$am__include" = "#"; then
|
'0:this is the am__doit target') :
|
||||||
echo '.include "confinc"' > confmf
|
case $s in #(
|
||||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
BSD) :
|
||||||
*the\ am__doit\ target*)
|
am__include='.include' am__quote='"' ;; #(
|
||||||
am__include=.include
|
*) :
|
||||||
am__quote="\""
|
am__include='include' am__quote='' ;;
|
||||||
_am_result=BSD
|
esac ;; #(
|
||||||
|
*) :
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
if test "$am__include" != "#"; then
|
||||||
|
_am_result="yes ($s style)"
|
||||||
|
break
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
|
fi
|
||||||
$as_echo "$_am_result" >&6; }
|
done
|
||||||
rm -f confinc confmf
|
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.
|
# Check whether --enable-dependency-tracking was given.
|
||||||
if test "${enable_dependency_tracking+set}" = set; then :
|
if test "${enable_dependency_tracking+set}" = set; then :
|
||||||
|
|
@ -4220,10 +4214,20 @@ $as_echo "${host_cpu}" >&6; }
|
||||||
x86_64)
|
x86_64)
|
||||||
CPU=x86_64
|
CPU=x86_64
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${host_cpu}" >&5
|
{ $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_echo "${host_cpu}" >&6; }
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
as_fn_error $? "Unsupported CPU." "$LINENO" 5
|
as_fn_error $? "Unsupported CPU. ${host_cpu}" "$LINENO" 5
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
@ -4243,9 +4247,25 @@ else
|
||||||
CPU_X86_64_FALSE=
|
CPU_X86_64_FALSE=
|
||||||
fi
|
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
|
if test "$CPU" = "arm64"; then
|
||||||
$as_echo_n "checking for off64_t... " >&6; }
|
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
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
@ -4265,6 +4285,11 @@ else
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext \
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
conftest$ac_exeext conftest.$ac_ext
|
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 "$as_me:${as_lineno-$LINENO}: result: $has_lfs" >&5
|
||||||
$as_echo "$has_lfs" >&6; }
|
$as_echo "$has_lfs" >&6; }
|
||||||
|
|
||||||
|
|
@ -4464,8 +4489,8 @@ fi
|
||||||
if test "x$sdl_prefix$sdl_exec_prefix" = x ; then
|
if test "x$sdl_prefix$sdl_exec_prefix" = x ; then
|
||||||
|
|
||||||
pkg_failed=no
|
pkg_failed=no
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sdl2 >= $min_sdl_version" >&5
|
||||||
$as_echo_n "checking for SDL... " >&6; }
|
$as_echo_n "checking for sdl2 >= $min_sdl_version... " >&6; }
|
||||||
|
|
||||||
if test -n "$SDL_CFLAGS"; then
|
if test -n "$SDL_CFLAGS"; then
|
||||||
pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
|
pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
|
||||||
|
|
@ -4505,7 +4530,7 @@ fi
|
||||||
|
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
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; }
|
$as_echo "no" >&6; }
|
||||||
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
|
|
@ -4523,7 +4548,7 @@ fi
|
||||||
|
|
||||||
sdl_pc=no
|
sdl_pc=no
|
||||||
elif test $pkg_failed = untried; then
|
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; }
|
$as_echo "no" >&6; }
|
||||||
sdl_pc=no
|
sdl_pc=no
|
||||||
else
|
else
|
||||||
|
|
@ -5213,6 +5238,7 @@ fi
|
||||||
build_macosx="no"
|
build_macosx="no"
|
||||||
build_linux="no"
|
build_linux="no"
|
||||||
build_win="no"
|
build_win="no"
|
||||||
|
build_other="no"
|
||||||
|
|
||||||
case "$host" in
|
case "$host" in
|
||||||
*-*-darwin*)
|
*-*-darwin*)
|
||||||
|
|
@ -5317,7 +5343,7 @@ fi
|
||||||
SET_MAKE='MAKE=mingw32-make'
|
SET_MAKE='MAKE=mingw32-make'
|
||||||
|
|
||||||
;;
|
;;
|
||||||
*)
|
*-*-linux*)
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for glGetError in -lGL" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for glGetError in -lGL" >&5
|
||||||
$as_echo_n "checking for glGetError in -lGL... " >&6; }
|
$as_echo_n "checking for glGetError in -lGL... " >&6; }
|
||||||
if ${ac_cv_lib_GL_glGetError+:} false; then :
|
if ${ac_cv_lib_GL_glGetError+:} false; then :
|
||||||
|
|
@ -5418,6 +5444,107 @@ fi
|
||||||
|
|
||||||
build_linux="yes"
|
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
|
esac
|
||||||
|
|
||||||
LIBS="$LIBS $WX_LIBS $SDL_LIBS"
|
LIBS="$LIBS $WX_LIBS $SDL_LIBS"
|
||||||
|
|
@ -5438,6 +5565,14 @@ else
|
||||||
OS_WINDOWS_FALSE=
|
OS_WINDOWS_FALSE=
|
||||||
fi
|
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
|
if test "$build_macosx" = "yes"; then
|
||||||
OS_MACOSX_TRUE=
|
OS_MACOSX_TRUE=
|
||||||
OS_MACOSX_FALSE='#'
|
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.
|
as_fn_error $? "conditional \"CPU_X86_64\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
fi
|
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
|
if test -z "${USE_WX_TRUE}" && test -z "${USE_WX_FALSE}"; then
|
||||||
as_fn_error $? "conditional \"USE_WX\" was never defined.
|
as_fn_error $? "conditional \"USE_WX\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
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.
|
as_fn_error $? "conditional \"OS_WINDOWS\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
fi
|
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
|
if test -z "${OS_MACOSX_TRUE}" && test -z "${OS_MACOSX_FALSE}"; then
|
||||||
as_fn_error $? "conditional \"OS_MACOSX\" was never defined.
|
as_fn_error $? "conditional \"OS_MACOSX\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
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
|
# INIT-COMMANDS
|
||||||
#
|
#
|
||||||
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
|
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
|
||||||
|
|
||||||
_ACEOF
|
_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
|
# Older Autoconf quotes --file arguments for eval, but not when files
|
||||||
# are listed without --file. Let's play safe and only enable the eval
|
# are listed without --file. Let's play safe and only enable the eval
|
||||||
# if we detect the quoting.
|
# if we detect the quoting.
|
||||||
case $CONFIG_FILES in
|
# TODO: see whether this extra hack can be removed once we start
|
||||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
# requiring Autoconf 2.70 or later.
|
||||||
*) set x $CONFIG_FILES ;;
|
case $CONFIG_FILES in #(
|
||||||
esac
|
*\'*) :
|
||||||
|
eval set x "$CONFIG_FILES" ;; #(
|
||||||
|
*) :
|
||||||
|
set x $CONFIG_FILES ;; #(
|
||||||
|
*) :
|
||||||
|
;;
|
||||||
|
esac
|
||||||
shift
|
shift
|
||||||
for mf
|
# Used to flag and report bootstrapping failures.
|
||||||
|
am_rc=0
|
||||||
|
for am_mf
|
||||||
do
|
do
|
||||||
# Strip MF so we end up with the name of the file.
|
# Strip MF so we end up with the name of the file.
|
||||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
|
||||||
# Check whether this is an Automake generated Makefile or not.
|
# Check whether this is an Automake generated Makefile which includes
|
||||||
# We used to match only the files named 'Makefile.in', but
|
# dependency-tracking related rules and includes.
|
||||||
# some people rename them; so instead we look at the file content.
|
# Grep'ing the whole file directly is not great: AIX grep has a line
|
||||||
# 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
|
|
||||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
# 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
|
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|
||||||
dirpart=`$as_dirname -- "$mf" ||
|
|| continue
|
||||||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
am_dirpart=`$as_dirname -- "$am_mf" ||
|
||||||
X"$mf" : 'X\(//\)[^/]' \| \
|
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||||
X"$mf" : 'X\(//\)$' \| \
|
X"$am_mf" : 'X\(//\)[^/]' \| \
|
||||||
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
|
X"$am_mf" : 'X\(//\)$' \| \
|
||||||
$as_echo X"$mf" |
|
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
|
$as_echo X"$am_mf" |
|
||||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
|
|
@ -6710,53 +6863,48 @@ $as_echo X"$mf" |
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
s/.*/./; q'`
|
s/.*/./; q'`
|
||||||
else
|
am_filepart=`$as_basename -- "$am_mf" ||
|
||||||
continue
|
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
|
||||||
fi
|
X"$am_mf" : 'X\(//\)$' \| \
|
||||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
# from the Makefile without running 'make'.
|
$as_echo X/"$am_mf" |
|
||||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
sed '/^.*\/\([^/][^/]*\)\/*$/{
|
||||||
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\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
/^X\(\/\/\)[^/].*/{
|
/^X\/\(\/\/\)$/{
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
/^X\(\/\/\)$/{
|
/^X\/\(\/\).*/{
|
||||||
s//\1/
|
|
||||||
q
|
|
||||||
}
|
|
||||||
/^X\(\/\).*/{
|
|
||||||
s//\1/
|
s//\1/
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
s/.*/./; q'`
|
s/.*/./; q'`
|
||||||
as_dir=$dirpart/$fdir; as_fn_mkdir_p
|
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
|
||||||
# echo "creating $dirpart/$file"
|
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||||
echo '# dummy' > "$dirpart/$file"
|
| $MAKE -f - am--depfiles" >&5
|
||||||
done
|
(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
|
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
|
||||||
}
|
}
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
|
||||||
14
configure.ac
14
configure.ac
|
|
@ -64,15 +64,25 @@ case "${host_cpu}" in
|
||||||
CPU=x86_64
|
CPU=x86_64
|
||||||
AC_MSG_RESULT(${host_cpu})
|
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
|
esac
|
||||||
|
|
||||||
AM_CONDITIONAL(CPU_I386, test "$CPU" = "i386")
|
AM_CONDITIONAL(CPU_I386, test "$CPU" = "i386")
|
||||||
AM_CONDITIONAL(CPU_X86_64, test "$CPU" = "x86_64")
|
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 <sys/types.h>]],[[off64_t n=0;]])],[has_lfs="yes"],[has_lfs="no"])
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]],[[off64_t n=0;]])],[has_lfs="yes"],[has_lfs="no"])
|
||||||
case "$host" in
|
case "$host" in
|
||||||
*-*-freebsd*) # has off64_t but no fopen64/etc.
|
*-*-freebsd*) # has off64_t but no fopen64/etc.
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "x87.h"
|
#include "x87.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "nmi.h"
|
#include "nmi.h"
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,64 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
|
||||||
eal_r = eal_w = NULL;
|
eal_r = eal_w = NULL;
|
||||||
easeg = cpu_state.ea_seg->base;
|
easeg = cpu_state.ea_seg->base;
|
||||||
ea_rseg = cpu_state.ea_seg->seg;
|
ea_rseg = cpu_state.ea_seg->seg;
|
||||||
|
if (cpu_rm == 4)
|
||||||
|
{
|
||||||
|
uint8_t sib = rmdat >> 8;
|
||||||
|
|
||||||
|
switch (cpu_mod)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
|
||||||
|
cpu_state.pc++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
cpu_state.pc++;
|
||||||
|
cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
|
||||||
|
// cpu_state.pc++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
|
||||||
|
cpu_state.pc += 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*SIB byte present*/
|
||||||
|
if ((sib & 7) == 5 && !cpu_mod)
|
||||||
|
cpu_state.eaaddr = getlong();
|
||||||
|
else if ((sib & 6) == 4 && !cpu_state.ssegs)
|
||||||
|
{
|
||||||
|
easeg = ss;
|
||||||
|
ea_rseg = SS;
|
||||||
|
cpu_state.ea_seg = &_ss;
|
||||||
|
}
|
||||||
|
if (((sib >> 3) & 7) != 4)
|
||||||
|
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
|
||||||
|
if (cpu_mod)
|
||||||
|
{
|
||||||
|
if (cpu_rm == 5 && !cpu_state.ssegs)
|
||||||
|
{
|
||||||
|
easeg = ss;
|
||||||
|
ea_rseg = SS;
|
||||||
|
cpu_state.ea_seg = &_ss;
|
||||||
|
}
|
||||||
|
if (cpu_mod == 1)
|
||||||
|
{
|
||||||
|
cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
|
||||||
|
cpu_state.pc++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpu_state.eaaddr += getlong();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cpu_rm == 5)
|
||||||
|
{
|
||||||
|
cpu_state.eaaddr = getlong();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
|
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
|
||||||
{
|
{
|
||||||
uint32_t addr = easeg + cpu_state.eaaddr;
|
uint32_t addr = easeg + cpu_state.eaaddr;
|
||||||
|
|
@ -38,6 +96,33 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
|
||||||
eal_r = eal_w = NULL;
|
eal_r = eal_w = NULL;
|
||||||
easeg = cpu_state.ea_seg->base;
|
easeg = cpu_state.ea_seg->base;
|
||||||
ea_rseg = cpu_state.ea_seg->seg;
|
ea_rseg = cpu_state.ea_seg->seg;
|
||||||
|
if (!cpu_mod && cpu_rm == 6)
|
||||||
|
{
|
||||||
|
cpu_state.eaaddr = getword();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (cpu_mod)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
cpu_state.eaaddr = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cpu_state.eaaddr = getword();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
|
||||||
|
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
|
||||||
|
{
|
||||||
|
easeg = ss;
|
||||||
|
ea_rseg = SS;
|
||||||
|
cpu_state.ea_seg = &_ss;
|
||||||
|
}
|
||||||
|
cpu_state.eaaddr &= 0xFFFF;
|
||||||
|
}
|
||||||
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
|
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
|
||||||
{
|
{
|
||||||
uint32_t addr = easeg + cpu_state.eaaddr;
|
uint32_t addr = easeg + cpu_state.eaaddr;
|
||||||
|
|
@ -48,8 +133,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat);
|
#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; }
|
||||||
#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
|
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1
|
||||||
|
|
||||||
|
|
||||||
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32)
|
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32)
|
||||||
|
|
@ -57,7 +142,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
|
||||||
#define PREFETCH_FLUSH()
|
#define PREFETCH_FLUSH()
|
||||||
|
|
||||||
#define OP_TABLE(name) dynarec_ops_ ## name
|
#define OP_TABLE(name) dynarec_ops_ ## name
|
||||||
#define CLOCK_CYCLES(c)
|
/*Temporary*/
|
||||||
|
#define CLOCK_CYCLES(c) cycles -= (c)
|
||||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||||
|
|
||||||
#include "386_ops.h"
|
#include "386_ops.h"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ wx-resources.cpp : pc.xrc
|
||||||
|
|
||||||
# PCem
|
# PCem
|
||||||
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \
|
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \
|
||||||
cmd640.c codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
|
cmd640.c codegen.c codegen_backend.c codegen_ir.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
|
||||||
dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
|
dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
|
||||||
hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
|
hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c 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 \
|
joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
|
||||||
|
|
@ -70,12 +70,20 @@ pcem_SOURCES += wx-sdl2-midi.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CPU_I386
|
if CPU_I386
|
||||||
pcem_SOURCES += codegen_x86.c
|
pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_uops.c
|
||||||
pcem_CFLAGS += -msse2
|
pcem_CFLAGS += -msse2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CPU_X86_64
|
if CPU_X86_64
|
||||||
pcem_SOURCES += codegen_x86-64.c
|
pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_uops.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if CPU_ARM
|
||||||
|
pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_uops.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if CPU_ARM64
|
||||||
|
pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_uops.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_NETWORKING
|
if USE_NETWORKING
|
||||||
|
|
|
||||||
1620
src/Makefile.in
1620
src/Makefile.in
File diff suppressed because it is too large
Load diff
|
|
@ -2,6 +2,13 @@
|
||||||
#include "x86_ops.h"
|
#include "x86_ops.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
|
||||||
|
codeblock_t *codeblock;
|
||||||
|
codeblock_t **codeblock_hash;
|
||||||
|
|
||||||
void (*codegen_timing_start)();
|
void (*codegen_timing_start)();
|
||||||
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||||
|
|
@ -19,3 +26,39 @@ void codegen_timing_set(codegen_timing_t *timing)
|
||||||
}
|
}
|
||||||
|
|
||||||
int codegen_in_recompile;
|
int codegen_in_recompile;
|
||||||
|
|
||||||
|
|
||||||
|
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc)
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
ir_data_t *ir = codegen_get_ir_data();
|
||||||
|
uint32_t op_pc = new_pc;
|
||||||
|
OpFn *op_table = x86_dynarec_opcodes;
|
||||||
|
int opcode_shift = 0;
|
||||||
|
int opcode_mask = 0x3ff;
|
||||||
|
uint32_t op_32 = use32;
|
||||||
|
|
||||||
|
|
||||||
|
//pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
|
||||||
|
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||||
|
|
||||||
|
uop_STORE_PTR_IMM(ir, &cpu_state.pc, op_pc);
|
||||||
|
uop_STORE_PTR_IMM(ir, &cpu_state.oldpc, old_pc);
|
||||||
|
uop_STORE_PTR_IMM(ir, &cpu_state.op32, op_32);
|
||||||
|
uop_STORE_PTR_IMM(ir, &cpu_state.ea_seg, (uintptr_t)&_ds);
|
||||||
|
uop_STORE_PTR_IMM_8(ir, &cpu_state.ssegs, 0);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat);
|
||||||
|
uop_CALL_INSTRUCTION_FUNC(ir, op);
|
||||||
|
|
||||||
|
//codegen_block_ins++;
|
||||||
|
|
||||||
|
block->ins++;
|
||||||
|
|
||||||
|
if (block->ins >= 50)
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
|
||||||
|
// addbyte(0xE8); /*CALL*/
|
||||||
|
// addlong(((uint8_t *)codegen_debug - (uint8_t *)(&block->data[block_pos + 4])));
|
||||||
|
|
||||||
|
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,6 @@
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "x86_ops.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) :
|
/*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
|
PCem tracks a 'dirty mask' for each physical page, in which each bit
|
||||||
|
|
@ -37,6 +29,9 @@
|
||||||
same page).
|
same page).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*Hack until better memory management written*/
|
||||||
|
#define BLOCK_DATA_SIZE 0x10000
|
||||||
|
|
||||||
typedef struct codeblock_t
|
typedef struct codeblock_t
|
||||||
{
|
{
|
||||||
uint64_t page_mask, page_mask2;
|
uint64_t page_mask, page_mask2;
|
||||||
|
|
@ -66,7 +61,7 @@ typedef struct codeblock_t
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
uint8_t data[2048];
|
uint8_t data[BLOCK_DATA_SIZE];
|
||||||
} codeblock_t;
|
} codeblock_t;
|
||||||
|
|
||||||
/*Code block uses FPU*/
|
/*Code block uses FPU*/
|
||||||
|
|
@ -311,45 +306,6 @@ extern int block_pos;
|
||||||
|
|
||||||
#define CPU_BLOCK_END() cpu_block_end = 1
|
#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 */
|
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
|
||||||
extern uint32_t recomp_page;
|
extern uint32_t recomp_page;
|
||||||
|
|
||||||
|
|
|
||||||
416
src/codegen_backend.c
Normal file
416
src/codegen_backend.c
Normal file
|
|
@ -0,0 +1,416 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "x86_ops.h"
|
||||||
|
#include "x87.h"
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
#include "386_common.h"
|
||||||
|
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
|
||||||
|
int codegen_flat_ds, codegen_flat_ss;
|
||||||
|
int mmx_ebx_ecx_loaded;
|
||||||
|
int codegen_flags_changed = 0;
|
||||||
|
int codegen_fpu_entered = 0;
|
||||||
|
int codegen_mmx_entered = 0;
|
||||||
|
int codegen_fpu_loaded_iq[8];
|
||||||
|
x86seg *op_ea_seg;
|
||||||
|
int op_ssegs;
|
||||||
|
uint32_t op_old_pc;
|
||||||
|
|
||||||
|
uint32_t recomp_page = -1;
|
||||||
|
|
||||||
|
int block_current = 0;
|
||||||
|
static int block_num;
|
||||||
|
int block_pos;
|
||||||
|
|
||||||
|
int cpu_recomp_flushes, cpu_recomp_flushes_latched;
|
||||||
|
int cpu_recomp_evicted, cpu_recomp_evicted_latched;
|
||||||
|
int cpu_recomp_reuse, cpu_recomp_reuse_latched;
|
||||||
|
int cpu_recomp_removed, cpu_recomp_removed_latched;
|
||||||
|
|
||||||
|
uint32_t codegen_endpc;
|
||||||
|
|
||||||
|
int codegen_block_cycles;
|
||||||
|
static int codegen_block_ins;
|
||||||
|
static int codegen_block_full_ins;
|
||||||
|
|
||||||
|
static uint32_t last_op32;
|
||||||
|
static x86seg *last_ea_seg;
|
||||||
|
static int last_ssegs;
|
||||||
|
|
||||||
|
|
||||||
|
void codegen_init()
|
||||||
|
{
|
||||||
|
codegen_backend_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_reset()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
mem_reset_page_blocks();
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_block()
|
||||||
|
{
|
||||||
|
/* codeblock_t *block = pages[0x119000 >> 12].block;
|
||||||
|
|
||||||
|
pclog("dump_block:\n");
|
||||||
|
while (block)
|
||||||
|
{
|
||||||
|
uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff);
|
||||||
|
uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff);
|
||||||
|
pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next);
|
||||||
|
if (!block->pc)
|
||||||
|
fatal("Dead PC=0\n");
|
||||||
|
|
||||||
|
block = block->next;
|
||||||
|
}
|
||||||
|
pclog("dump_block done\n");*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_to_block_list(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3];
|
||||||
|
|
||||||
|
if (!block->page_mask)
|
||||||
|
fatal("add_to_block_list - mask = 0\n");
|
||||||
|
|
||||||
|
if (block_prev)
|
||||||
|
{
|
||||||
|
block->next = block_prev;
|
||||||
|
block_prev->prev = block;
|
||||||
|
pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block->next = NULL;
|
||||||
|
pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->next)
|
||||||
|
{
|
||||||
|
if (block->next->pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->page_mask2)
|
||||||
|
{
|
||||||
|
block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3];
|
||||||
|
|
||||||
|
if (block_prev)
|
||||||
|
{
|
||||||
|
block->next_2 = block_prev;
|
||||||
|
block_prev->prev_2 = block;
|
||||||
|
pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block->next_2 = NULL;
|
||||||
|
pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_from_block_list(codeblock_t *block, uint32_t pc)
|
||||||
|
{
|
||||||
|
if (!block->page_mask)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (block->prev)
|
||||||
|
{
|
||||||
|
block->prev->next = block->next;
|
||||||
|
if (block->next)
|
||||||
|
block->next->prev = block->prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next;
|
||||||
|
if (block->next)
|
||||||
|
block->next->prev = NULL;
|
||||||
|
else
|
||||||
|
mem_flush_write_page(block->phys, 0);
|
||||||
|
}
|
||||||
|
if (!block->page_mask2)
|
||||||
|
{
|
||||||
|
if (block->prev_2 || block->next_2)
|
||||||
|
fatal("Invalid block_2\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->prev_2)
|
||||||
|
{
|
||||||
|
block->prev_2->next_2 = block->next_2;
|
||||||
|
if (block->next_2)
|
||||||
|
block->next_2->prev_2 = block->prev_2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2);
|
||||||
|
pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2;
|
||||||
|
if (block->next_2)
|
||||||
|
block->next_2->prev_2 = NULL;
|
||||||
|
else
|
||||||
|
mem_flush_write_page(block->phys_2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delete_block(codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t old_pc = block->pc;
|
||||||
|
|
||||||
|
if (block == codeblock_hash[HASH(block->phys)])
|
||||||
|
codeblock_hash[HASH(block->phys)] = NULL;
|
||||||
|
|
||||||
|
if (block->pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("Deleting deleted block\n");
|
||||||
|
block->pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
codeblock_tree_delete(block);
|
||||||
|
remove_from_block_list(block, old_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
|
||||||
|
{
|
||||||
|
struct codeblock_t *block = page->block[(phys_addr >> 10) & 3];
|
||||||
|
|
||||||
|
while (block)
|
||||||
|
{
|
||||||
|
if (mask & block->page_mask)
|
||||||
|
{
|
||||||
|
delete_block(block);
|
||||||
|
cpu_recomp_evicted++;
|
||||||
|
}
|
||||||
|
if (block == block->next)
|
||||||
|
fatal("Broken 1\n");
|
||||||
|
block = block->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = page->block_2[(phys_addr >> 10) & 3];
|
||||||
|
|
||||||
|
while (block)
|
||||||
|
{
|
||||||
|
if (mask & block->page_mask2)
|
||||||
|
{
|
||||||
|
delete_block(block);
|
||||||
|
cpu_recomp_evicted++;
|
||||||
|
}
|
||||||
|
if (block == block->next_2)
|
||||||
|
fatal("Broken 2\n");
|
||||||
|
block = block->next_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_init(uint32_t phys_addr)
|
||||||
|
{
|
||||||
|
codeblock_t *block;
|
||||||
|
page_t *page = &pages[phys_addr >> 12];
|
||||||
|
|
||||||
|
if (!page->block[(phys_addr >> 10) & 3])
|
||||||
|
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
|
||||||
|
|
||||||
|
block_current = (block_current + 1) & BLOCK_MASK;
|
||||||
|
block = &codeblock[block_current];
|
||||||
|
|
||||||
|
// if (block->pc == 0xb00b4ff5)
|
||||||
|
// pclog("Init target block\n");
|
||||||
|
if (block->pc != BLOCK_PC_INVALID)
|
||||||
|
{
|
||||||
|
// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc);
|
||||||
|
delete_block(block);
|
||||||
|
cpu_recomp_reuse++;
|
||||||
|
}
|
||||||
|
block_num = HASH(phys_addr);
|
||||||
|
codeblock_hash[block_num] = &codeblock[block_current];
|
||||||
|
|
||||||
|
block->ins = 0;
|
||||||
|
block->pc = cs + cpu_state.pc;
|
||||||
|
block->_cs = cs;
|
||||||
|
block->pnt = block_current;
|
||||||
|
block->phys = phys_addr;
|
||||||
|
block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK];
|
||||||
|
block->dirty_mask2 = NULL;
|
||||||
|
block->next = block->prev = NULL;
|
||||||
|
block->next_2 = block->prev_2 = NULL;
|
||||||
|
block->page_mask = 0;
|
||||||
|
block->flags = CODEBLOCK_STATIC_TOP;
|
||||||
|
block->status = cpu_cur_status;
|
||||||
|
|
||||||
|
block->was_recompiled = 0;
|
||||||
|
|
||||||
|
recomp_page = block->phys & ~0xfff;
|
||||||
|
|
||||||
|
codeblock_tree_add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ir_data_t *ir_data;
|
||||||
|
|
||||||
|
ir_data_t *codegen_get_ir_data()
|
||||||
|
{
|
||||||
|
return ir_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_start_recompile(codeblock_t *block)
|
||||||
|
{
|
||||||
|
page_t *page = &pages[block->phys >> 12];
|
||||||
|
|
||||||
|
if (!page->block[(block->phys >> 10) & 3])
|
||||||
|
mem_flush_write_page(block->phys, cs+cpu_state.pc);
|
||||||
|
|
||||||
|
block_num = HASH(block->phys);
|
||||||
|
block_current = block->pnt;
|
||||||
|
|
||||||
|
if (block->pc != cs + cpu_state.pc || block->was_recompiled)
|
||||||
|
fatal("Recompile to used block!\n");
|
||||||
|
|
||||||
|
block->status = cpu_cur_status;
|
||||||
|
|
||||||
|
cpu_block_end = 0;
|
||||||
|
|
||||||
|
// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num);
|
||||||
|
|
||||||
|
last_op32 = -1;
|
||||||
|
last_ea_seg = NULL;
|
||||||
|
last_ssegs = -1;
|
||||||
|
|
||||||
|
codegen_block_cycles = 0;
|
||||||
|
codegen_timing_block_start();
|
||||||
|
|
||||||
|
codegen_block_ins = 0;
|
||||||
|
codegen_block_full_ins = 0;
|
||||||
|
|
||||||
|
recomp_page = block->phys & ~0xfff;
|
||||||
|
|
||||||
|
codegen_flags_changed = 0;
|
||||||
|
codegen_fpu_entered = 0;
|
||||||
|
codegen_mmx_entered = 0;
|
||||||
|
|
||||||
|
codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
|
||||||
|
codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
|
||||||
|
|
||||||
|
_ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1;
|
||||||
|
|
||||||
|
block->TOP = cpu_state.TOP;
|
||||||
|
block->was_recompiled = 1;
|
||||||
|
|
||||||
|
codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);
|
||||||
|
codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS);
|
||||||
|
|
||||||
|
ir_data = codegen_ir_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void codegen_block_remove()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
|
||||||
|
delete_block(block);
|
||||||
|
cpu_recomp_removed++;
|
||||||
|
|
||||||
|
recomp_page = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_generate_end_mask()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
uint32_t start_pc;
|
||||||
|
uint32_t end_pc;
|
||||||
|
|
||||||
|
block->endpc = codegen_endpc;
|
||||||
|
|
||||||
|
block->page_mask = 0;
|
||||||
|
start_pc = (block->pc & 0x3ff) & ~15;
|
||||||
|
if ((block->pc ^ block->endpc) & ~0x3ff)
|
||||||
|
end_pc = 0x3ff & ~15;
|
||||||
|
else
|
||||||
|
end_pc = (block->endpc & 0x3ff) & ~15;
|
||||||
|
if (end_pc < start_pc)
|
||||||
|
end_pc = 0x3ff;
|
||||||
|
start_pc >>= PAGE_MASK_SHIFT;
|
||||||
|
end_pc >>= PAGE_MASK_SHIFT;
|
||||||
|
|
||||||
|
// pclog("block_end: %08x %08x\n", start_pc, end_pc);
|
||||||
|
for (; start_pc <= end_pc; start_pc++)
|
||||||
|
{
|
||||||
|
block->page_mask |= ((uint64_t)1 << start_pc);
|
||||||
|
// pclog(" %08x %llx\n", start_pc, block->page_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask;
|
||||||
|
|
||||||
|
block->phys_2 = -1;
|
||||||
|
block->page_mask2 = 0;
|
||||||
|
block->next_2 = block->prev_2 = NULL;
|
||||||
|
if ((block->pc ^ block->endpc) & ~0x3ff)
|
||||||
|
{
|
||||||
|
block->phys_2 = get_phys_noabrt(block->endpc);
|
||||||
|
if (block->phys_2 != -1)
|
||||||
|
{
|
||||||
|
page_t *page_2 = &pages[block->phys_2 >> 12];
|
||||||
|
|
||||||
|
start_pc = 0;
|
||||||
|
end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT;
|
||||||
|
for (; start_pc <= end_pc; start_pc++)
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << start_pc);
|
||||||
|
page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2;
|
||||||
|
|
||||||
|
if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3])
|
||||||
|
mem_flush_write_page(block->phys_2, block->endpc);
|
||||||
|
|
||||||
|
if (!block->page_mask2)
|
||||||
|
fatal("!page_mask2\n");
|
||||||
|
if (block->next_2)
|
||||||
|
{
|
||||||
|
// pclog(" next_2->pc=%08x\n", block->next_2->pc);
|
||||||
|
if (block->next_2->pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)block->next_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask);
|
||||||
|
recomp_page = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_end()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
|
||||||
|
codegen_block_generate_end_mask();
|
||||||
|
add_to_block_list(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_end_recompile(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_timing_block_end();
|
||||||
|
|
||||||
|
remove_from_block_list(block, block->pc);
|
||||||
|
block->next = block->prev = NULL;
|
||||||
|
block->next_2 = block->prev_2 = NULL;
|
||||||
|
codegen_block_generate_end_mask();
|
||||||
|
add_to_block_list(block);
|
||||||
|
// pclog("End block %i\n", block_num);
|
||||||
|
|
||||||
|
if (!(block->flags & CODEBLOCK_HAS_FPU))
|
||||||
|
block->flags &= ~CODEBLOCK_STATIC_TOP;
|
||||||
|
|
||||||
|
codegen_ir_compile(ir_data, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_flush()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
65
src/codegen_backend.h
Normal file
65
src/codegen_backend.h
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
//#ifdef __amd64__
|
||||||
|
//#include "codegen_x86-64.h"
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include "codegen_backend_x86.h"
|
||||||
|
#elif defined __amd64__
|
||||||
|
#include "codegen_backend_x86-64.h"
|
||||||
|
#elif defined __ARM_EABI__
|
||||||
|
#include "codegen_backend_arm.h"
|
||||||
|
#elif defined __aarch64__
|
||||||
|
#include "codegen_backend_arm64.h"
|
||||||
|
#else
|
||||||
|
#error Dynamic recompiler not implemented on your platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void codegen_backend_init();
|
||||||
|
void codegen_backend_prologue(codeblock_t *block);
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block);
|
||||||
|
|
||||||
|
static inline void addbyte(uint8_t val)
|
||||||
|
{
|
||||||
|
codeblock[block_current].data[block_pos++] = val;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void addword(uint16_t val)
|
||||||
|
{
|
||||||
|
*(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val;
|
||||||
|
block_pos += 2;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void addlong(uint32_t val)
|
||||||
|
{
|
||||||
|
*(uint32_t *)&codeblock[block_current].data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void addquad(uint64_t val)
|
||||||
|
{
|
||||||
|
*(uint64_t *)&codeblock[block_current].data[block_pos] = val;
|
||||||
|
block_pos += 8;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ir_data_t;
|
||||||
|
struct uop_t;
|
||||||
|
|
||||||
|
struct ir_data_t *codegen_get_ir_data();
|
||||||
|
|
||||||
|
typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
|
||||||
|
|
||||||
|
extern const uOpFn uop_handlers[];
|
||||||
101
src/codegen_backend_arm.c
Normal file
101
src/codegen_backend_arm.c
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
#ifdef __ARM_EABI__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_arm_defs.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
#endif
|
||||||
|
if (!codeblock)
|
||||||
|
fatal("codeblock failed to alloc - %i\n", (BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
start = (void *)((long)codeblock & pagemask);
|
||||||
|
len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask;
|
||||||
|
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||||
|
{
|
||||||
|
perror("mprotect");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*R11 - literal pool
|
||||||
|
R10 - cpu_state*/
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
codegen_reset_literal_pool(block);
|
||||||
|
|
||||||
|
block_pos = 0;
|
||||||
|
|
||||||
|
block_pos = BLOCK_GPF_OFFSET;
|
||||||
|
host_arm_MOV_IMM(block, REG_R0, 0);
|
||||||
|
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||||
|
host_arm_call(block, x86gpf);
|
||||||
|
while (block_pos != BLOCK_EXIT_OFFSET)
|
||||||
|
host_arm_nop(block);
|
||||||
|
|
||||||
|
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||||
|
host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10);
|
||||||
|
host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||||
|
while (block_pos != BLOCK_START)
|
||||||
|
host_arm_nop(block);
|
||||||
|
|
||||||
|
/*Entry code*/
|
||||||
|
|
||||||
|
host_arm_STMDB_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_LR);
|
||||||
|
host_arm_SUB_IMM(block, REG_SP, REG_SP, 0x10);
|
||||||
|
host_arm_ADD_IMM(block, REG_LITERAL, REG_PC, ARM_LITERAL_POOL_OFFSET);
|
||||||
|
host_arm_SUB_IMM(block, REG_LITERAL, REG_LITERAL, 16 + BLOCK_START);
|
||||||
|
offset = add_literal(block, (uintptr_t)&cpu_state);
|
||||||
|
host_arm_LDR_IMM(block, REG_CPUSTATE, REG_R11, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_arm_ADD_IMM(block, REG_SP, REG_SP, 0x10);
|
||||||
|
host_arm_LDMIA_WB(block, REG_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||||
|
|
||||||
|
if (block_pos > ARM_LITERAL_POOL_OFFSET)
|
||||||
|
fatal("Over limit!\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__clear_cache(&block->data[0], &block->data[block_pos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
33
src/codegen_backend_arm.h
Normal file
33
src/codegen_backend_arm.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#define BLOCK_SIZE 0x1000
|
||||||
|
#define BLOCK_MASK 0x0fff
|
||||||
|
#define BLOCK_START 32
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
/*Hack until better memory management written*/
|
||||||
|
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||||
|
|
||||||
|
#define BLOCK_GPF_OFFSET 0
|
||||||
|
#define BLOCK_EXIT_OFFSET 16
|
||||||
|
|
||||||
|
#define ARM_LITERAL_POOL_OFFSET 0xf000
|
||||||
|
|
||||||
|
/*#define BLOCK_MAX 1720*/
|
||||||
|
#define BLOCK_MAX 65208
|
||||||
|
|
||||||
|
|
||||||
|
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||||
|
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||||
|
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
|
||||||
|
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||||
|
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
|
||||||
|
void host_arm_call(codeblock_t *block, void *dst_addr);
|
||||||
|
void host_arm_nop(codeblock_t *block);
|
||||||
|
|
||||||
|
void codegen_reset_literal_pool(codeblock_t *block);
|
||||||
|
int add_literal(codeblock_t *block, uint32_t data);
|
||||||
115
src/codegen_backend_arm64.c
Normal file
115
src/codegen_backend_arm64.c
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
#ifdef __aarch64__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_arm64_defs.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
#endif
|
||||||
|
if (!codeblock)
|
||||||
|
fatal("codeblock failed to alloc - %i\n", (BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
start = (void *)((long)codeblock & pagemask);
|
||||||
|
len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask;
|
||||||
|
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||||
|
{
|
||||||
|
perror("mprotect");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*R11 - literal pool
|
||||||
|
R10 - cpu_state*/
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
codegen_reset_literal_pool(block);
|
||||||
|
|
||||||
|
block_pos = 0;
|
||||||
|
|
||||||
|
block_pos = BLOCK_GPF_OFFSET;
|
||||||
|
host_arm64_mov_imm(block, REG_ARG0, 0);
|
||||||
|
host_arm64_mov_imm(block, REG_ARG1, 0);
|
||||||
|
host_arm64_call(block, x86gpf);
|
||||||
|
while (block_pos != BLOCK_EXIT_OFFSET)
|
||||||
|
host_arm64_NOP(block);
|
||||||
|
|
||||||
|
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
while (block_pos != BLOCK_START)
|
||||||
|
host_arm64_NOP(block);
|
||||||
|
|
||||||
|
/*Entry code*/
|
||||||
|
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_SP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -16);
|
||||||
|
|
||||||
|
offset = add_literal_q(block, (uintptr_t)&cpu_state);
|
||||||
|
host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_SP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
if (block_pos > ARM_LITERAL_POOL_OFFSET)
|
||||||
|
fatal("Over limit!\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__clear_cache(&block->data[0], &block->data[block_pos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
40
src/codegen_backend_arm64.h
Normal file
40
src/codegen_backend_arm64.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#define BLOCK_SIZE 0x1000
|
||||||
|
#define BLOCK_MASK 0x0fff
|
||||||
|
#define BLOCK_START 64
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
/*Hack until better memory management written*/
|
||||||
|
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||||
|
|
||||||
|
#define BLOCK_GPF_OFFSET 0
|
||||||
|
#define BLOCK_EXIT_OFFSET 32
|
||||||
|
|
||||||
|
#define ARM_LITERAL_POOL_OFFSET 0xf000
|
||||||
|
|
||||||
|
/*#define BLOCK_MAX 1720*/
|
||||||
|
#define BLOCK_MAX 65208
|
||||||
|
|
||||||
|
|
||||||
|
void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
||||||
|
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
|
||||||
|
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||||
|
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
|
||||||
|
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
|
||||||
|
void host_arm64_NOP(codeblock_t *block);
|
||||||
|
void host_arm64_RET(codeblock_t *block, int reg);
|
||||||
|
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||||
|
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_arm64_call(codeblock_t *block, void *dst_addr);
|
||||||
|
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void codegen_reset_literal_pool(codeblock_t *block);
|
||||||
|
int add_literal(codeblock_t *block, uint32_t data);
|
||||||
|
int add_literal_q(codeblock_t *block, uint64_t data);
|
||||||
72
src/codegen_backend_arm64_defs.h
Normal file
72
src/codegen_backend_arm64_defs.h
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
#define REG_W0 0
|
||||||
|
#define REG_W1 1
|
||||||
|
#define REG_W2 2
|
||||||
|
#define REG_W3 3
|
||||||
|
#define REG_W4 4
|
||||||
|
#define REG_W5 5
|
||||||
|
#define REG_W6 6
|
||||||
|
#define REG_W7 7
|
||||||
|
#define REG_W8 8
|
||||||
|
#define REG_W9 9
|
||||||
|
#define REG_W10 10
|
||||||
|
#define REG_W11 11
|
||||||
|
#define REG_W12 12
|
||||||
|
#define REG_W13 13
|
||||||
|
#define REG_W14 14
|
||||||
|
#define REG_W15 15
|
||||||
|
#define REG_W16 16
|
||||||
|
#define REG_W17 17
|
||||||
|
#define REG_W18 18
|
||||||
|
#define REG_W19 19
|
||||||
|
#define REG_W20 20
|
||||||
|
#define REG_W21 21
|
||||||
|
#define REG_W22 22
|
||||||
|
#define REG_W23 23
|
||||||
|
#define REG_W24 24
|
||||||
|
#define REG_W25 25
|
||||||
|
#define REG_W26 26
|
||||||
|
#define REG_W27 27
|
||||||
|
#define REG_W28 28
|
||||||
|
#define REG_W29 29
|
||||||
|
#define REG_W30 30
|
||||||
|
|
||||||
|
#define REG_X0 0
|
||||||
|
#define REG_X1 1
|
||||||
|
#define REG_X2 2
|
||||||
|
#define REG_X3 3
|
||||||
|
#define REG_X4 4
|
||||||
|
#define REG_X5 5
|
||||||
|
#define REG_X6 6
|
||||||
|
#define REG_X7 7
|
||||||
|
#define REG_X8 8
|
||||||
|
#define REG_X9 9
|
||||||
|
#define REG_X10 10
|
||||||
|
#define REG_X11 11
|
||||||
|
#define REG_X12 12
|
||||||
|
#define REG_X13 13
|
||||||
|
#define REG_X14 14
|
||||||
|
#define REG_X15 15
|
||||||
|
#define REG_X16 16
|
||||||
|
#define REG_X17 17
|
||||||
|
#define REG_X18 18
|
||||||
|
#define REG_X19 19
|
||||||
|
#define REG_X20 20
|
||||||
|
#define REG_X21 21
|
||||||
|
#define REG_X22 22
|
||||||
|
#define REG_X23 23
|
||||||
|
#define REG_X24 24
|
||||||
|
#define REG_X25 25
|
||||||
|
#define REG_X26 26
|
||||||
|
#define REG_X27 27
|
||||||
|
#define REG_X28 28
|
||||||
|
#define REG_X29 29
|
||||||
|
#define REG_X30 30
|
||||||
|
|
||||||
|
#define REG_SP 31
|
||||||
|
|
||||||
|
#define REG_ARG0 REG_X0
|
||||||
|
#define REG_ARG1 REG_X1
|
||||||
|
#define REG_ARG2 REG_X2
|
||||||
|
#define REG_ARG3 REG_X3
|
||||||
|
|
||||||
|
#define REG_CPUSTATE REG_X29
|
||||||
300
src/codegen_backend_arm64_uops.c
Normal file
300
src/codegen_backend_arm64_uops.c
Normal file
|
|
@ -0,0 +1,300 @@
|
||||||
|
#ifdef __aarch64__
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_arm64_defs.h"
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
|
||||||
|
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
{
|
||||||
|
*(uint32_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addlong over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Rt(x) (x)
|
||||||
|
#define Rd(x) (x)
|
||||||
|
#define Rn(x) ((x) << 5)
|
||||||
|
#define Rt2(x) ((x) << 10)
|
||||||
|
|
||||||
|
#define DATA_OFFSET_UP (1 << 23)
|
||||||
|
#define DATA_OFFSET_DOWN (0 << 23)
|
||||||
|
|
||||||
|
#define COND_SHIFT 28
|
||||||
|
#define COND_NE (0x1 << COND_SHIFT)
|
||||||
|
#define COND_AL (0xe << COND_SHIFT)
|
||||||
|
|
||||||
|
#define OPCODE_SHIFT 24
|
||||||
|
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
|
||||||
|
|
||||||
|
#define OPCODE_MOVK_W (0x0e5 << 23)
|
||||||
|
#define OPCODE_MOVZ_W (0x0a5 << 23)
|
||||||
|
|
||||||
|
#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22)
|
||||||
|
#define OPCODE_STP_PREIDX_X (0x2a6 << 22)
|
||||||
|
#define OPCODE_STR_IMM_W (0x2e4 << 22)
|
||||||
|
#define OPCODE_STRB_IMM (0x0e4 << 22)
|
||||||
|
|
||||||
|
#define OPCODE_BLR (0xd63f0000)
|
||||||
|
#define OPCODE_NOP (0xd503201f)
|
||||||
|
#define OPCODE_RET (0xd65f0000)
|
||||||
|
|
||||||
|
#define MOV_WIDE_HW(hw) (hw << 21)
|
||||||
|
|
||||||
|
#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15)
|
||||||
|
#define IMM16(imm_data) (imm_data << 5)
|
||||||
|
|
||||||
|
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
||||||
|
|
||||||
|
#define OFFSET12_B(offset) (offset << 10)
|
||||||
|
#define OFFSET12_W(offset) ((offset >> 2) << 10)
|
||||||
|
|
||||||
|
static int literal_offset = 0;
|
||||||
|
void codegen_reset_literal_pool(codeblock_t *block)
|
||||||
|
{
|
||||||
|
literal_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Returns true if offset fits into 19 bits*/
|
||||||
|
static int offset_is_19bit(int offset)
|
||||||
|
{
|
||||||
|
if (offset >= (1 << (18+2)))
|
||||||
|
return 0;
|
||||||
|
if (offset < -(1 << (18+2)))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
|
||||||
|
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
|
||||||
|
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
|
||||||
|
|
||||||
|
int add_literal(codeblock_t *block, uint32_t data)
|
||||||
|
{
|
||||||
|
if (literal_offset >= 4096)
|
||||||
|
fatal("add_literal - literal pool full\n");
|
||||||
|
|
||||||
|
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||||
|
|
||||||
|
literal_offset += 4;
|
||||||
|
|
||||||
|
return literal_offset - 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_literal_q(codeblock_t *block, uint64_t data)
|
||||||
|
{
|
||||||
|
if (literal_offset & 4)
|
||||||
|
literal_offset += 4;
|
||||||
|
|
||||||
|
if (literal_offset >= 4096-4)
|
||||||
|
fatal("add_literal - literal pool full\n");
|
||||||
|
|
||||||
|
*(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||||
|
|
||||||
|
literal_offset += 8;
|
||||||
|
|
||||||
|
return literal_offset - 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int imm_is_imm16(uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void host_arm64_BLR(codeblock_t *block, int addr_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_BLR | Rn(addr_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest)
|
||||||
|
{
|
||||||
|
int offset = dest - (uintptr_t)&block->data[block_pos];
|
||||||
|
if (!offset_is_19bit(offset))
|
||||||
|
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||||
|
codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (!in_range7_x(offset))
|
||||||
|
fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset);
|
||||||
|
codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
|
||||||
|
{
|
||||||
|
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
|
||||||
|
|
||||||
|
if (!offset_is_19bit(offset))
|
||||||
|
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||||
|
|
||||||
|
codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset)
|
||||||
|
{
|
||||||
|
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
|
||||||
|
|
||||||
|
if (!offset_is_19bit(offset))
|
||||||
|
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||||
|
|
||||||
|
codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
int hw;
|
||||||
|
|
||||||
|
if (!imm_is_imm16(imm_data))
|
||||||
|
fatal("MOVZ_IMM - imm not representable %08x\n", imm_data);
|
||||||
|
|
||||||
|
hw = (imm_data & 0xffff0000) ? 1 : 0;
|
||||||
|
if (hw)
|
||||||
|
imm_data >>= 16;
|
||||||
|
|
||||||
|
codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
int hw;
|
||||||
|
|
||||||
|
if (!imm_is_imm16(imm_data))
|
||||||
|
fatal("MOVK_IMM - imm not representable %08x\n", imm_data);
|
||||||
|
|
||||||
|
hw = (imm_data & 0xffff0000) ? 1 : 0;
|
||||||
|
if (hw)
|
||||||
|
imm_data >>= 16;
|
||||||
|
|
||||||
|
codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_NOP(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_NOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_RET(codeblock_t *block, int reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_RET | Rn(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (!in_range7_x(offset))
|
||||||
|
fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset);
|
||||||
|
codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (!in_range12_w(offset))
|
||||||
|
fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset);
|
||||||
|
codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (!in_range12_b(offset))
|
||||||
|
fatal("host_arm64_STRB_IMM out of range12 %i\n", offset);
|
||||||
|
codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void host_arm64_call(codeblock_t *block, void *dst_addr)
|
||||||
|
{
|
||||||
|
int offset = add_literal_q(block, (uintptr_t)dst_addr);
|
||||||
|
host_arm64_LDR_LITERAL_X(block, REG_X16, offset);
|
||||||
|
host_arm64_BLR(block, REG_X16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (imm_is_imm16(imm_data))
|
||||||
|
host_arm64_MOVZ_IMM(block, reg, imm_data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff);
|
||||||
|
host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_call(block, uop->p);
|
||||||
|
host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_mov_imm(block, REG_ARG0, uop->imm_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_mov_imm(block, REG_ARG1, uop->imm_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_mov_imm(block, REG_ARG2, uop->imm_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_mov_imm(block, REG_ARG3, uop->imm_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_mov_imm(block, REG_W16, uop->imm_data);
|
||||||
|
|
||||||
|
if (in_range12_w((uintptr_t)uop->p - (uintptr_t)&cpu_state))
|
||||||
|
host_arm64_STR_IMM_W(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state);
|
||||||
|
else
|
||||||
|
fatal("codegen_STORE_PTR_IMM - not in range\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm64_mov_imm(block, REG_W16, uop->imm_data);
|
||||||
|
|
||||||
|
if (in_range12_b((uintptr_t)uop->p - (uintptr_t)&cpu_state))
|
||||||
|
host_arm64_STRB_IMM(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state);
|
||||||
|
else
|
||||||
|
fatal("codegen_STORE_PTR_IMM - not in range\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uOpFn uop_handlers[UOP_MAX] =
|
||||||
|
{
|
||||||
|
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||||
|
|
||||||
|
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM,
|
||||||
|
|
||||||
|
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||||
|
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
44
src/codegen_backend_arm_defs.h
Normal file
44
src/codegen_backend_arm_defs.h
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#define REG_R0 0
|
||||||
|
#define REG_R1 1
|
||||||
|
#define REG_R2 2
|
||||||
|
#define REG_R3 3
|
||||||
|
#define REG_R4 4
|
||||||
|
#define REG_R5 5
|
||||||
|
#define REG_R6 6
|
||||||
|
#define REG_R7 7
|
||||||
|
#define REG_R8 8
|
||||||
|
#define REG_R9 9
|
||||||
|
#define REG_R10 10
|
||||||
|
#define REG_R11 11
|
||||||
|
#define REG_R12 12
|
||||||
|
#define REG_SP 13
|
||||||
|
#define REG_LR 14
|
||||||
|
#define REG_PC 15
|
||||||
|
|
||||||
|
#define REG_ARG0 REG_R0
|
||||||
|
#define REG_ARG1 REG_R1
|
||||||
|
#define REG_ARG2 REG_R2
|
||||||
|
#define REG_ARG3 REG_R3
|
||||||
|
|
||||||
|
#define REG_CPUSTATE REG_R10
|
||||||
|
#define REG_LITERAL REG_R11
|
||||||
|
|
||||||
|
#define REG_MASK_R0 (1 << REG_R0)
|
||||||
|
#define REG_MASK_R1 (1 << REG_R1)
|
||||||
|
#define REG_MASK_R2 (1 << REG_R2)
|
||||||
|
#define REG_MASK_R3 (1 << REG_R3)
|
||||||
|
#define REG_MASK_R4 (1 << REG_R4)
|
||||||
|
#define REG_MASK_R5 (1 << REG_R5)
|
||||||
|
#define REG_MASK_R6 (1 << REG_R6)
|
||||||
|
#define REG_MASK_R7 (1 << REG_R7)
|
||||||
|
#define REG_MASK_R8 (1 << REG_R8)
|
||||||
|
#define REG_MASK_R9 (1 << REG_R9)
|
||||||
|
#define REG_MASK_R10 (1 << REG_R10)
|
||||||
|
#define REG_MASK_R11 (1 << REG_R11)
|
||||||
|
#define REG_MASK_R12 (1 << REG_R12)
|
||||||
|
#define REG_MASK_SP (1 << REG_SP)
|
||||||
|
#define REG_MASK_LR (1 << REG_LR)
|
||||||
|
#define REG_MASK_PC (1 << REG_PC)
|
||||||
|
|
||||||
|
#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \
|
||||||
|
REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
|
||||||
314
src/codegen_backend_arm_uops.c
Normal file
314
src/codegen_backend_arm_uops.c
Normal file
|
|
@ -0,0 +1,314 @@
|
||||||
|
#ifdef __ARM_EABI__
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_arm_defs.h"
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
|
||||||
|
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
{
|
||||||
|
*(uint32_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addlong over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Rm(x) (x)
|
||||||
|
#define Rd(x) ((x) << 12)
|
||||||
|
#define Rn(x) ((x) << 16)
|
||||||
|
|
||||||
|
#define DATA_OFFSET_UP (1 << 23)
|
||||||
|
#define DATA_OFFSET_DOWN (0 << 23)
|
||||||
|
|
||||||
|
#define COND_SHIFT 28
|
||||||
|
#define COND_NE (0x1 << COND_SHIFT)
|
||||||
|
#define COND_AL (0xe << COND_SHIFT)
|
||||||
|
|
||||||
|
#define OPCODE_SHIFT 20
|
||||||
|
#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_B (0xa0 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT)
|
||||||
|
|
||||||
|
#define OPCODE_BLX 0xe12fff30
|
||||||
|
|
||||||
|
#define B_OFFSET(x) (((x) >> 2) & 0xffffff)
|
||||||
|
|
||||||
|
static int literal_offset = 0;
|
||||||
|
void codegen_reset_literal_pool(codeblock_t *block)
|
||||||
|
{
|
||||||
|
literal_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_literal(codeblock_t *block, uint32_t data)
|
||||||
|
{
|
||||||
|
if (literal_offset >= 4096)
|
||||||
|
fatal("add_literal - literal pool full\n");
|
||||||
|
|
||||||
|
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||||
|
|
||||||
|
literal_offset += 4;
|
||||||
|
|
||||||
|
return literal_offset - 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint32_t arm_data_offset(int offset)
|
||||||
|
{
|
||||||
|
if (offset < -0xffc || offset > 0xffc)
|
||||||
|
fatal("arm_data_offset out of range - %i\n", offset);
|
||||||
|
|
||||||
|
if (offset >= 0)
|
||||||
|
return offset | DATA_OFFSET_UP;
|
||||||
|
return (-offset) | DATA_OFFSET_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm)
|
||||||
|
{
|
||||||
|
int shift = 0;
|
||||||
|
//pclog("get_arm_imm - imm_data=%08x\n", imm_data);
|
||||||
|
if (!(imm_data & 0xffff))
|
||||||
|
{
|
||||||
|
shift += 16;
|
||||||
|
imm_data >>= 16;
|
||||||
|
}
|
||||||
|
if (!(imm_data & 0xff))
|
||||||
|
{
|
||||||
|
shift += 8;
|
||||||
|
imm_data >>= 8;
|
||||||
|
}
|
||||||
|
if (!(imm_data & 0xf))
|
||||||
|
{
|
||||||
|
shift += 4;
|
||||||
|
imm_data >>= 4;
|
||||||
|
}
|
||||||
|
if (!(imm_data & 0x3))
|
||||||
|
{
|
||||||
|
shift += 2;
|
||||||
|
imm_data >>= 2;
|
||||||
|
}
|
||||||
|
if (imm_data > 0xff) /*Note - should handle rotation round the word*/
|
||||||
|
return 0;
|
||||||
|
//pclog(" imm_data=%02x shift=%i\n", imm_data, shift);
|
||||||
|
*arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int in_range(void *addr, void *base)
|
||||||
|
{
|
||||||
|
int diff = (uintptr_t)addr - (uintptr_t)base;
|
||||||
|
|
||||||
|
if (diff < -4095 || diff > 4095)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (!get_arm_imm(imm, &arm_imm))
|
||||||
|
fatal("host_arm_ADD_IMM !check_arm_imm %08x\n", imm);
|
||||||
|
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_BLX(codeblock_t *block, int addr_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_BLX | Rm(addr_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr)
|
||||||
|
{
|
||||||
|
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||||
|
|
||||||
|
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||||
|
fatal("host_arm_BNE - out of range %08x %i\n", offset, offset);
|
||||||
|
|
||||||
|
codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (!get_arm_imm(imm, &arm_imm))
|
||||||
|
fatal("host_arm_MOV_IMM !check_arm_imm %08x\n", imm);
|
||||||
|
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_MOV_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (!get_arm_imm(imm, &arm_imm))
|
||||||
|
fatal("host_arm_SUB_IMM !check_arm_imm %08x\n", imm);
|
||||||
|
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void host_arm_call(codeblock_t *block, void *dst_addr)
|
||||||
|
{
|
||||||
|
int offset = add_literal(block, (uintptr_t)dst_addr);
|
||||||
|
host_arm_LDR_IMM(block, REG_R3, REG_LITERAL, offset);
|
||||||
|
host_arm_BLX(block, REG_R3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_arm_nop(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_arm_MOV_REG(block, REG_R0, REG_R0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm_call(block, uop->p);
|
||||||
|
host_arm_TST_REG(block, REG_R0, REG_R0);
|
||||||
|
host_arm_BNE(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (get_arm_imm(uop->imm_data, &arm_imm))
|
||||||
|
host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int offset = add_literal(block, uop->imm_data);
|
||||||
|
host_arm_LDR_IMM(block, REG_ARG0, REG_LITERAL, offset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (get_arm_imm(uop->imm_data, &arm_imm))
|
||||||
|
host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int offset = add_literal(block, uop->imm_data);
|
||||||
|
host_arm_LDR_IMM(block, REG_ARG1, REG_LITERAL, offset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (get_arm_imm(uop->imm_data, &arm_imm))
|
||||||
|
host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int offset = add_literal(block, uop->imm_data);
|
||||||
|
host_arm_LDR_IMM(block, REG_ARG2, REG_LITERAL, offset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (get_arm_imm(uop->imm_data, &arm_imm))
|
||||||
|
host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int offset = add_literal(block, uop->imm_data);
|
||||||
|
host_arm_LDR_IMM(block, REG_ARG3, REG_LITERAL, offset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
uint32_t arm_imm;
|
||||||
|
|
||||||
|
if (get_arm_imm(uop->imm_data, &arm_imm))
|
||||||
|
host_arm_MOV_IMM(block, REG_R0, uop->imm_data);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int offset = add_literal(block, uop->imm_data);
|
||||||
|
host_arm_LDR_IMM(block, REG_R0, REG_LITERAL, offset);
|
||||||
|
}
|
||||||
|
if (in_range(uop->p, &cpu_state))
|
||||||
|
host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state);
|
||||||
|
else
|
||||||
|
fatal("codegen_STORE_PTR_IMM - not in range\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_arm_MOV_IMM(block, REG_R0, uop->imm_data);
|
||||||
|
if (in_range(uop->p, &cpu_state))
|
||||||
|
host_arm_STRB_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state);
|
||||||
|
else
|
||||||
|
fatal("codegen_STORE_PTR_IMM - not in range\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uOpFn uop_handlers[UOP_MAX] =
|
||||||
|
{
|
||||||
|
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||||
|
|
||||||
|
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM,
|
||||||
|
|
||||||
|
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||||
|
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
156
src/codegen_backend_x86-64.c
Normal file
156
src/codegen_backend_x86-64.c
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
#ifdef __amd64__
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void *mem_abrt_rout;
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
#endif
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
start = (void *)((long)codeblock & pagemask);
|
||||||
|
len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask;
|
||||||
|
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||||
|
{
|
||||||
|
perror("mprotect");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void call(codeblock_t *block, uintptr_t func)
|
||||||
|
{
|
||||||
|
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||||
|
|
||||||
|
if (diff >= -0x80000000 && diff < 0x7fffffff)
|
||||||
|
{
|
||||||
|
addbyte(0xE8); /*CALL*/
|
||||||
|
addlong((uint32_t)diff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addbyte(0x48); /*MOV RAX, func*/
|
||||||
|
addbyte(0xb8);
|
||||||
|
addquad(func);
|
||||||
|
addbyte(0xff); /*CALL RAX*/
|
||||||
|
addbyte(0xd0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
block_pos = 0; /*Entry code*/
|
||||||
|
addbyte(0x53); /*PUSH RBX*/
|
||||||
|
addbyte(0x55); /*PUSH RBP*/
|
||||||
|
addbyte(0x56); /*PUSH RSI*/
|
||||||
|
addbyte(0x57); /*PUSH RDI*/
|
||||||
|
addbyte(0x41); /*PUSH R12*/
|
||||||
|
addbyte(0x54);
|
||||||
|
addbyte(0x41); /*PUSH R13*/
|
||||||
|
addbyte(0x55);
|
||||||
|
addbyte(0x41); /*PUSH R14*/
|
||||||
|
addbyte(0x56);
|
||||||
|
addbyte(0x41); /*PUSH R15*/
|
||||||
|
addbyte(0x57);
|
||||||
|
addbyte(0x48); /*SUBL $40,%rsp*/
|
||||||
|
addbyte(0x83);
|
||||||
|
addbyte(0xEC);
|
||||||
|
addbyte(0x28);
|
||||||
|
addbyte(0x48); /*MOVL RBP, &cpu_state*/
|
||||||
|
addbyte(0xBD);
|
||||||
|
addquad(((uintptr_t)&cpu_state) + 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
addbyte(0x48); /*ADDL $40,%rsp*/
|
||||||
|
addbyte(0x83);
|
||||||
|
addbyte(0xC4);
|
||||||
|
addbyte(0x28);
|
||||||
|
addbyte(0x41); /*POP R15*/
|
||||||
|
addbyte(0x5f);
|
||||||
|
addbyte(0x41); /*POP R14*/
|
||||||
|
addbyte(0x5e);
|
||||||
|
addbyte(0x41); /*POP R13*/
|
||||||
|
addbyte(0x5d);
|
||||||
|
addbyte(0x41); /*POP R12*/
|
||||||
|
addbyte(0x5c);
|
||||||
|
addbyte(0x5f); /*POP RDI*/
|
||||||
|
addbyte(0x5e); /*POP RSI*/
|
||||||
|
addbyte(0x5d); /*POP RBP*/
|
||||||
|
addbyte(0x5b); /*POP RDX*/
|
||||||
|
addbyte(0xC3); /*RET*/
|
||||||
|
|
||||||
|
if (block_pos > BLOCK_GPF_OFFSET)
|
||||||
|
fatal("Over limit!\n");
|
||||||
|
|
||||||
|
block_pos = BLOCK_GPF_OFFSET;
|
||||||
|
#if WIN64
|
||||||
|
addbyte(0x48); /*XOR RCX, RCX*/
|
||||||
|
addbyte(0x31);
|
||||||
|
addbyte(0xc9);
|
||||||
|
addbyte(0x31); /*XOR EDX, EDX*/
|
||||||
|
addbyte(0xd2);
|
||||||
|
#else
|
||||||
|
addbyte(0x48); /*XOR RDI, RDI*/
|
||||||
|
addbyte(0x31);
|
||||||
|
addbyte(0xff);
|
||||||
|
addbyte(0x31); /*XOR ESI, ESI*/
|
||||||
|
addbyte(0xf6);
|
||||||
|
#endif
|
||||||
|
call(block, (uintptr_t)x86gpf);
|
||||||
|
while (block_pos < BLOCK_EXIT_OFFSET)
|
||||||
|
addbyte(0x90); /*NOP*/
|
||||||
|
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||||
|
addbyte(0x48); /*ADDL $40,%rsp*/
|
||||||
|
addbyte(0x83);
|
||||||
|
addbyte(0xC4);
|
||||||
|
addbyte(0x28);
|
||||||
|
addbyte(0x41); /*POP R15*/
|
||||||
|
addbyte(0x5f);
|
||||||
|
addbyte(0x41); /*POP R14*/
|
||||||
|
addbyte(0x5e);
|
||||||
|
addbyte(0x41); /*POP R13*/
|
||||||
|
addbyte(0x5d);
|
||||||
|
addbyte(0x41); /*POP R12*/
|
||||||
|
addbyte(0x5c);
|
||||||
|
addbyte(0x5f); /*POP RDI*/
|
||||||
|
addbyte(0x5e); /*POP RSI*/
|
||||||
|
addbyte(0x5d); /*POP RBP*/
|
||||||
|
addbyte(0x5b); /*POP RDX*/
|
||||||
|
addbyte(0xC3); /*RET*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
16
src/codegen_backend_x86-64.h
Normal file
16
src/codegen_backend_x86-64.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#define BLOCK_SIZE 0x4000
|
||||||
|
#define BLOCK_MASK 0x3fff
|
||||||
|
#define BLOCK_START 0
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
/*Hack until better memory management written*/
|
||||||
|
#define BLOCK_EXIT_OFFSET 0xffe0
|
||||||
|
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||||
|
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||||
|
|
||||||
|
/*#define BLOCK_MAX 1720*/
|
||||||
|
#define BLOCK_MAX 65208
|
||||||
8
src/codegen_backend_x86-64_defs.h
Normal file
8
src/codegen_backend_x86-64_defs.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#define REG_EAX 0
|
||||||
|
#define REG_ECX 1
|
||||||
|
#define REG_EDX 2
|
||||||
|
#define REG_EBX 3
|
||||||
|
#define REG_ESP 4
|
||||||
|
#define REG_EBP 5
|
||||||
|
#define REG_ESI 6
|
||||||
|
#define REG_EDI 7
|
||||||
232
src/codegen_backend_x86-64_uops.c
Normal file
232
src/codegen_backend_x86-64_uops.c
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
#ifdef __amd64__
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86-64_defs.h"
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
|
||||||
|
#define STACK_ARG0 (0)
|
||||||
|
#define STACK_ARG1 (4)
|
||||||
|
#define STACK_ARG2 (8)
|
||||||
|
#define STACK_ARG3 (12)
|
||||||
|
|
||||||
|
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = val;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||||
|
// CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = vala;
|
||||||
|
block->data[block_pos++] = valb;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = vala;
|
||||||
|
block->data[block_pos++] = valb;
|
||||||
|
block->data[block_pos++] = valc;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = vala;
|
||||||
|
block->data[block_pos++] = valb;
|
||||||
|
block->data[block_pos++] = valc;
|
||||||
|
block->data[block_pos++] = vald;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||||
|
{
|
||||||
|
*(uint16_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 2;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addword over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
{
|
||||||
|
*(uint32_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addlong over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||||
|
{
|
||||||
|
*(uint64_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 8;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addquad over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void call(codeblock_t *block, uintptr_t func)
|
||||||
|
{
|
||||||
|
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||||
|
|
||||||
|
if (diff >= -0x80000000 && diff < 0x7fffffff)
|
||||||
|
{
|
||||||
|
codegen_addbyte(block, 0xE8); /*CALL*/
|
||||||
|
codegen_addlong(block, (uint32_t)diff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x48, 0xb8); /*MOV RAX, func*/
|
||||||
|
codegen_addquad(block, func);
|
||||||
|
codegen_addbyte2(block, 0xff, 0xd0); /*CALL RAX*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_CALL(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
call(block, (uintptr_t)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_JNZ(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||||
|
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
codegen_addbyte(block, imm_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (reg & 8)
|
||||||
|
fatal("host_x86_MOV32_REG_IMM reg & 8\n");
|
||||||
|
codegen_addbyte(block, 0xb8 | reg); /*MOV reg, imm_data*/
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
else if (offset >= -80 || offset < 0x80)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/
|
||||||
|
codegen_addlong(block, offset);
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||||
|
|
||||||
|
static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, uop->p);
|
||||||
|
host_x86_TEST32_REG(block, REG_EAX, REG_EAX);
|
||||||
|
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
#if WIN64
|
||||||
|
host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||||
|
#else
|
||||||
|
host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
#if WIN64
|
||||||
|
host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data);
|
||||||
|
#else
|
||||||
|
host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
fatal("codegen_LOAD_FUNC_ARG2_IMM\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
fatal("codegen_LOAD_FUNC_ARG3_IMM\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
if (((uintptr_t)uop->p) >> 32)
|
||||||
|
fatal("STORE_PTR_IMM 64-bit addr\n");
|
||||||
|
host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
if (((uintptr_t)uop->p) >> 32)
|
||||||
|
fatal("STORE_PTR_IMM_8 64-bit addr\n");
|
||||||
|
host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uOpFn uop_handlers[UOP_MAX] =
|
||||||
|
{
|
||||||
|
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||||
|
|
||||||
|
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM,
|
||||||
|
|
||||||
|
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||||
|
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
121
src/codegen_backend_x86.c
Normal file
121
src/codegen_backend_x86.c
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void *mem_abrt_rout;
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
#endif
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
start = (void *)((long)codeblock & pagemask);
|
||||||
|
len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask;
|
||||||
|
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||||
|
{
|
||||||
|
perror("mprotect");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
|
||||||
|
block_current = BLOCK_SIZE;
|
||||||
|
block_pos = 0;
|
||||||
|
mem_abrt_rout = &codeblock[block_current].data[block_pos];
|
||||||
|
addbyte(0x83); /*ADDL $16+4,%esp*/
|
||||||
|
addbyte(0xC4);
|
||||||
|
addbyte(0x10+4);
|
||||||
|
addbyte(0x5f); /*POP EDI*/
|
||||||
|
addbyte(0x5e); /*POP ESI*/
|
||||||
|
addbyte(0x5d); /*POP EBP*/
|
||||||
|
addbyte(0x5b); /*POP EDX*/
|
||||||
|
addbyte(0xC3); /*RET*/
|
||||||
|
|
||||||
|
asm(
|
||||||
|
"fstcw %0\n"
|
||||||
|
: "=m" (cpu_state.old_npxc)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
block_pos = 0; /*Entry code*/
|
||||||
|
addbyte(0x53); /*PUSH EBX*/
|
||||||
|
addbyte(0x55); /*PUSH EBP*/
|
||||||
|
addbyte(0x56); /*PUSH ESI*/
|
||||||
|
addbyte(0x57); /*PUSH EDI*/
|
||||||
|
addbyte(0x83); /*SUBL $16,%esp*/
|
||||||
|
addbyte(0xEC);
|
||||||
|
addbyte(0x10);
|
||||||
|
addbyte(0xBD); /*MOVL EBP, &cpu_state*/
|
||||||
|
addlong(((uintptr_t)&cpu_state) + 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
addbyte(0x83); /*ADDL $16,%esp*/
|
||||||
|
addbyte(0xC4);
|
||||||
|
addbyte(0x10);
|
||||||
|
addbyte(0x5f); /*POP EDI*/
|
||||||
|
addbyte(0x5e); /*POP ESI*/
|
||||||
|
addbyte(0x5d); /*POP EBP*/
|
||||||
|
addbyte(0x5b); /*POP EDX*/
|
||||||
|
addbyte(0xC3); /*RET*/
|
||||||
|
|
||||||
|
if (block_pos > BLOCK_GPF_OFFSET)
|
||||||
|
fatal("Over limit!\n");
|
||||||
|
|
||||||
|
block_pos = BLOCK_GPF_OFFSET;
|
||||||
|
addbyte(0xc7); /*MOV [ESP],0*/
|
||||||
|
addbyte(0x04);
|
||||||
|
addbyte(0x24);
|
||||||
|
addlong(0);
|
||||||
|
addbyte(0xc7); /*MOV [ESP+4],0*/
|
||||||
|
addbyte(0x44);
|
||||||
|
addbyte(0x24);
|
||||||
|
addbyte(0x04);
|
||||||
|
addlong(0);
|
||||||
|
addbyte(0xe8); /*CALL x86gpf*/
|
||||||
|
addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||||
|
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||||
|
addbyte(0x83); /*ADDL $16,%esp*/
|
||||||
|
addbyte(0xC4);
|
||||||
|
addbyte(0x10);
|
||||||
|
addbyte(0x5f); /*POP EDI*/
|
||||||
|
addbyte(0x5e); /*POP ESI*/
|
||||||
|
addbyte(0x5d); /*POP EBP*/
|
||||||
|
addbyte(0x5b); /*POP EDX*/
|
||||||
|
addbyte(0xC3); /*RET*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
16
src/codegen_backend_x86.h
Normal file
16
src/codegen_backend_x86.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#define BLOCK_SIZE 0x4000
|
||||||
|
#define BLOCK_MASK 0x3fff
|
||||||
|
#define BLOCK_START 0
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
/*Hack until better memory management written*/
|
||||||
|
#define BLOCK_EXIT_OFFSET 0xfff0
|
||||||
|
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||||
|
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||||
|
|
||||||
|
/*#define BLOCK_MAX 1720*/
|
||||||
|
#define BLOCK_MAX 65208
|
||||||
8
src/codegen_backend_x86_defs.h
Normal file
8
src/codegen_backend_x86_defs.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#define REG_EAX 0
|
||||||
|
#define REG_ECX 1
|
||||||
|
#define REG_EDX 2
|
||||||
|
#define REG_EBX 3
|
||||||
|
#define REG_ESP 4
|
||||||
|
#define REG_EBP 5
|
||||||
|
#define REG_ESI 6
|
||||||
|
#define REG_EDI 7
|
||||||
195
src/codegen_backend_x86_uops.c
Normal file
195
src/codegen_backend_x86_uops.c
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86_defs.h"
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
|
||||||
|
#define STACK_ARG0 (0)
|
||||||
|
#define STACK_ARG1 (4)
|
||||||
|
#define STACK_ARG2 (8)
|
||||||
|
#define STACK_ARG3 (12)
|
||||||
|
|
||||||
|
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = val;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||||
|
// CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = vala;
|
||||||
|
block->data[block_pos++] = valb;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = vala;
|
||||||
|
block->data[block_pos++] = valb;
|
||||||
|
block->data[block_pos++] = valc;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||||
|
{
|
||||||
|
block->data[block_pos++] = vala;
|
||||||
|
block->data[block_pos++] = valb;
|
||||||
|
block->data[block_pos++] = valc;
|
||||||
|
block->data[block_pos++] = vald;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||||
|
{
|
||||||
|
*(uint16_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 2;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addword over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
{
|
||||||
|
*(uint32_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addlong over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||||
|
{
|
||||||
|
*(uint64_t *)&block->data[block_pos] = val;
|
||||||
|
block_pos += 8;
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addquad over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void host_x86_CALL(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
codegen_addbyte(block, 0xe8); /*CALL*/
|
||||||
|
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_JNZ(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||||
|
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
codegen_addbyte(block, imm_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
else if (offset >= -80 || offset < 0x80)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/
|
||||||
|
codegen_addlong(block, offset);
|
||||||
|
codegen_addlong(block, imm_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||||
|
|
||||||
|
static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, uop->p);
|
||||||
|
host_x86_TEST32_REG(block, REG_EAX, REG_EAX);
|
||||||
|
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_STACK_IMM(block, STACK_ARG1, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_STACK_IMM(block, STACK_ARG2, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_STACK_IMM(block, STACK_ARG3, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uOpFn uop_handlers[UOP_MAX] =
|
||||||
|
{
|
||||||
|
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||||
|
|
||||||
|
[UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM,
|
||||||
|
[UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM,
|
||||||
|
|
||||||
|
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||||
|
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
34
src/codegen_ir.c
Normal file
34
src/codegen_ir.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
|
||||||
|
static ir_data_t ir_block;
|
||||||
|
|
||||||
|
ir_data_t *codegen_ir_init()
|
||||||
|
{
|
||||||
|
ir_block.wr_pos = 0;
|
||||||
|
//pclog("codegen_ir_init\n");
|
||||||
|
|
||||||
|
return &ir_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
codegen_backend_prologue(block);
|
||||||
|
|
||||||
|
for (c = 0; c < ir->wr_pos; c++)
|
||||||
|
{
|
||||||
|
uop_t *uop = &ir->uops[c];
|
||||||
|
|
||||||
|
//pclog("uOP %i : %08x\n", c, uop->type);
|
||||||
|
|
||||||
|
uop_handlers[uop->type & UOP_MASK](block, uop);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_backend_epilogue(block);
|
||||||
|
|
||||||
|
// fatal("IR compilation complete\n");
|
||||||
|
}
|
||||||
5
src/codegen_ir.h
Normal file
5
src/codegen_ir.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
|
||||||
|
ir_data_t *codegen_ir_init();
|
||||||
|
|
||||||
|
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block);
|
||||||
152
src/codegen_ir_defs.h
Normal file
152
src/codegen_ir_defs.h
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
#ifndef _CODEGEN_IR_DEFS_
|
||||||
|
#define _CODEGEN_IR_DEFS_
|
||||||
|
|
||||||
|
#define IREG_L (0 << 6)
|
||||||
|
#define IREG_W (1 << 6)
|
||||||
|
#define IREG_B (2 << 6)
|
||||||
|
#define IREG_BH (3 << 6)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ireg_EAX = 0,
|
||||||
|
ireg_ECX = 1,
|
||||||
|
ireg_EDX = 2,
|
||||||
|
ireg_EBX = 3,
|
||||||
|
ireg_ESP = 4,
|
||||||
|
ireg_EBP = 5,
|
||||||
|
ireg_ESI = 6,
|
||||||
|
ireg_EDI = 7,
|
||||||
|
|
||||||
|
ireg_flags_op = 8,
|
||||||
|
ireg_flags_reg = 9,
|
||||||
|
ireg_flags_op1 = 10,
|
||||||
|
ireg_flags_op2 = 11,
|
||||||
|
|
||||||
|
ireg_flags_pc = 12,
|
||||||
|
ireg_flags_oldpc = 13,
|
||||||
|
|
||||||
|
ireg_eaaddr = 14,
|
||||||
|
|
||||||
|
/*Temporary registers are stored on the stack, and are not guaranteed to
|
||||||
|
be preserved across uOPs. They will not be written back if they will
|
||||||
|
not be read again.*/
|
||||||
|
ireg_temp0 = 16,
|
||||||
|
ireg_temp1 = 17,
|
||||||
|
ireg_temp2 = 18,
|
||||||
|
ireg_temp3 = 19
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8))
|
||||||
|
|
||||||
|
#define UOP_REG_UNUSED 0xffff
|
||||||
|
|
||||||
|
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
|
||||||
|
All registers must have been written back or discarded*/
|
||||||
|
#define UOP_TYPE_BARRIER (1 << 31)
|
||||||
|
|
||||||
|
/*uOP uses source and dest registers*/
|
||||||
|
#define UOP_TYPE_PARAMS_REGS (1 << 28)
|
||||||
|
/*uOP uses pointer*/
|
||||||
|
#define UOP_TYPE_PARAMS_POINTER (1 << 29)
|
||||||
|
/*uOP uses immediate data*/
|
||||||
|
#define UOP_TYPE_PARAMS_IMM (1 << 30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b)
|
||||||
|
#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12)
|
||||||
|
#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13)
|
||||||
|
|
||||||
|
#define UOP_MAX 0x14
|
||||||
|
|
||||||
|
#define UOP_MASK 0xffff
|
||||||
|
|
||||||
|
typedef struct uop_t
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
uint16_t dest_reg_a;
|
||||||
|
uint16_t src_reg_a;
|
||||||
|
uint16_t src_reg_b;
|
||||||
|
uint16_t src_reg_c;
|
||||||
|
uint32_t imm_data;
|
||||||
|
void *p;
|
||||||
|
} uop_t;
|
||||||
|
|
||||||
|
#define UOP_NR_MAX 4096
|
||||||
|
|
||||||
|
typedef struct ir_data_t
|
||||||
|
{
|
||||||
|
uop_t uops[UOP_NR_MAX];
|
||||||
|
int wr_pos;
|
||||||
|
} ir_data_t;
|
||||||
|
|
||||||
|
static inline uop_t *uop_alloc(ir_data_t *ir)
|
||||||
|
{
|
||||||
|
uop_t *uop;
|
||||||
|
|
||||||
|
if (ir->wr_pos >= UOP_NR_MAX)
|
||||||
|
fatal("Exceeded uOP max\n");
|
||||||
|
|
||||||
|
uop = &ir->uops[ir->wr_pos++];
|
||||||
|
|
||||||
|
uop->dest_reg_a = UOP_REG_UNUSED;
|
||||||
|
uop->src_reg_a = UOP_REG_UNUSED;
|
||||||
|
uop->src_reg_b = UOP_REG_UNUSED;
|
||||||
|
uop->src_reg_c = UOP_REG_UNUSED;
|
||||||
|
|
||||||
|
return uop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, uint16_t src_reg_a)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = src_reg_a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->p = p;
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
|
||||||
|
|
||||||
|
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
|
||||||
|
|
||||||
|
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
|
||||||
|
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
|
||||||
|
|
||||||
|
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
|
||||||
|
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,591 +0,0 @@
|
||||||
#include "ibm.h"
|
|
||||||
#include "x86.h"
|
|
||||||
#include "x86_ops.h"
|
|
||||||
#include "x86_flags.h"
|
|
||||||
#include "x87.h"
|
|
||||||
#include "386_common.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "codegen.h"
|
|
||||||
#include "codegen_ops.h"
|
|
||||||
|
|
||||||
#ifdef __amd64__
|
|
||||||
#include "codegen_ops_x86-64.h"
|
|
||||||
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
|
||||||
#include "codegen_ops_x86.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "codegen_ops_arith.h"
|
|
||||||
#include "codegen_ops_fpu.h"
|
|
||||||
#include "codegen_ops_jump.h"
|
|
||||||
#include "codegen_ops_logic.h"
|
|
||||||
#include "codegen_ops_misc.h"
|
|
||||||
#include "codegen_ops_mmx.h"
|
|
||||||
#include "codegen_ops_mov.h"
|
|
||||||
#include "codegen_ops_shift.h"
|
|
||||||
#include "codegen_ops_stack.h"
|
|
||||||
#include "codegen_ops_xchg.h"
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16,
|
|
||||||
/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL,
|
|
||||||
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw,
|
|
||||||
/*50*/ ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
|
|
||||||
|
|
||||||
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_w, ropMOV_seg_w, NULL,
|
|
||||||
/*90*/ ropNOP, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
|
|
||||||
|
|
||||||
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES, ropLDS, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32,
|
|
||||||
/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL,
|
|
||||||
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl,
|
|
||||||
/*50*/ ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
|
|
||||||
|
|
||||||
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_w_seg, ropLEA_l, ropMOV_seg_w, NULL,
|
|
||||||
/*90*/ ropNOP, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
|
|
||||||
|
|
||||||
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES, ropLDS, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_0f[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w,
|
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_mm_l, ropMOVQ_mm_q,
|
|
||||||
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm,
|
|
||||||
|
|
||||||
/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l,
|
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
|
|
||||||
/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
|
|
||||||
/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_d8[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
|
||||||
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
|
|
||||||
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
|
|
||||||
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
|
|
||||||
|
|
||||||
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
|
||||||
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
|
|
||||||
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
|
|
||||||
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
|
|
||||||
|
|
||||||
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
|
||||||
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
|
|
||||||
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
|
|
||||||
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
|
|
||||||
|
|
||||||
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
|
|
||||||
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
|
|
||||||
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
|
|
||||||
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
|
||||||
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
|
|
||||||
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
|
|
||||||
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
|
|
||||||
|
|
||||||
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
|
||||||
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
|
|
||||||
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
|
|
||||||
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
|
|
||||||
|
|
||||||
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
|
||||||
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
|
|
||||||
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
|
|
||||||
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
|
|
||||||
|
|
||||||
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
|
|
||||||
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
|
|
||||||
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
|
|
||||||
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_d9[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
|
||||||
|
|
||||||
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
|
||||||
|
|
||||||
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
|
||||||
|
|
||||||
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
|
||||||
|
|
||||||
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
|
||||||
|
|
||||||
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
|
||||||
|
|
||||||
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_da[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
|
||||||
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
|
||||||
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
|
||||||
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
|
||||||
|
|
||||||
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
|
||||||
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
|
||||||
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
|
||||||
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
|
||||||
|
|
||||||
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
|
||||||
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
|
||||||
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
|
||||||
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
|
||||||
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
|
||||||
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
|
||||||
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
|
||||||
|
|
||||||
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
|
||||||
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
|
||||||
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
|
||||||
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
|
||||||
|
|
||||||
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
|
||||||
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
|
||||||
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
|
||||||
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_db[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_dc[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
|
||||||
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
|
|
||||||
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
|
|
||||||
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
|
|
||||||
|
|
||||||
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
|
||||||
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
|
|
||||||
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
|
|
||||||
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
|
|
||||||
|
|
||||||
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
|
||||||
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
|
|
||||||
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
|
|
||||||
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
|
|
||||||
|
|
||||||
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
|
|
||||||
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
|
|
||||||
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
|
|
||||||
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
|
||||||
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
|
|
||||||
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
|
|
||||||
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
|
|
||||||
|
|
||||||
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
|
||||||
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
|
|
||||||
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
|
|
||||||
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
|
|
||||||
|
|
||||||
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
|
||||||
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
|
|
||||||
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
|
|
||||||
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
|
|
||||||
|
|
||||||
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
|
|
||||||
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
|
|
||||||
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
|
|
||||||
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_dd[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_de[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
|
||||||
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
|
||||||
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
|
||||||
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
|
||||||
|
|
||||||
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
|
||||||
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
|
||||||
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
|
||||||
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
|
||||||
|
|
||||||
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
|
||||||
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
|
||||||
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
|
||||||
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
|
||||||
|
|
||||||
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
|
|
||||||
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
|
||||||
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
|
||||||
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
|
||||||
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
|
||||||
|
|
||||||
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
|
||||||
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
|
||||||
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
|
||||||
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
|
||||||
|
|
||||||
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
|
||||||
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
|
||||||
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
|
||||||
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
|
||||||
|
|
||||||
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
|
|
||||||
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_df[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
|
||||||
|
|
||||||
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
|
||||||
|
|
||||||
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
|
||||||
|
|
||||||
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
|
||||||
|
|
||||||
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_REPE[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_REPNE[512] =
|
|
||||||
{
|
|
||||||
/*16-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*32-bit data*/
|
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
|
||||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,270 +0,0 @@
|
||||||
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t offset = fetchdat & 0xff;
|
|
||||||
|
|
||||||
if (offset & 0x80)
|
|
||||||
offset |= 0xffffff00;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint16_t offset = fetchdat & 0xffff;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t offset = fastreadl(cs + op_pc);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t offset = fetchdat & 0xff;
|
|
||||||
|
|
||||||
if (offset & 0x80)
|
|
||||||
offset |= 0xffffff00;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(REG_ECX);
|
|
||||||
TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(REG_CX);
|
|
||||||
TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t offset = fetchdat & 0xff;
|
|
||||||
|
|
||||||
if (offset & 0x80)
|
|
||||||
offset |= 0xffffff00;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(REG_ECX);
|
|
||||||
SUB_HOST_REG_IMM(host_reg, 1);
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(REG_CX);
|
|
||||||
SUB_HOST_REG_IMM(host_reg, 1);
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
|
||||||
{
|
|
||||||
CALL_FUNC((uintptr_t)CF_SET);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
|
||||||
{
|
|
||||||
case FLAGS_ZN8:
|
|
||||||
case FLAGS_ZN16:
|
|
||||||
case FLAGS_ZN32:
|
|
||||||
case FLAGS_ADD8:
|
|
||||||
case FLAGS_ADD16:
|
|
||||||
case FLAGS_ADD32:
|
|
||||||
case FLAGS_SUB8:
|
|
||||||
case FLAGS_SUB16:
|
|
||||||
case FLAGS_SUB32:
|
|
||||||
case FLAGS_SHL8:
|
|
||||||
case FLAGS_SHL16:
|
|
||||||
case FLAGS_SHL32:
|
|
||||||
case FLAGS_SHR8:
|
|
||||||
case FLAGS_SHR16:
|
|
||||||
case FLAGS_SHR32:
|
|
||||||
case FLAGS_SAR8:
|
|
||||||
case FLAGS_SAR16:
|
|
||||||
case FLAGS_SAR32:
|
|
||||||
case FLAGS_INC8:
|
|
||||||
case FLAGS_INC16:
|
|
||||||
case FLAGS_INC32:
|
|
||||||
case FLAGS_DEC8:
|
|
||||||
case FLAGS_DEC16:
|
|
||||||
case FLAGS_DEC32:
|
|
||||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
|
||||||
if (not)
|
|
||||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLAGS_UNKNOWN:
|
|
||||||
CALL_FUNC((uintptr_t)ZF_SET);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
|
||||||
{
|
|
||||||
CALL_FUNC((uintptr_t)VF_SET);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
|
||||||
{
|
|
||||||
CALL_FUNC((uintptr_t)PF_SET);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
|
||||||
{
|
|
||||||
case FLAGS_ZN8:
|
|
||||||
case FLAGS_ADD8:
|
|
||||||
case FLAGS_SUB8:
|
|
||||||
case FLAGS_SHL8:
|
|
||||||
case FLAGS_SHR8:
|
|
||||||
case FLAGS_SAR8:
|
|
||||||
case FLAGS_INC8:
|
|
||||||
case FLAGS_DEC8:
|
|
||||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
|
||||||
AND_HOST_REG_IMM(host_reg, 0x80);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLAGS_ZN16:
|
|
||||||
case FLAGS_ADD16:
|
|
||||||
case FLAGS_SUB16:
|
|
||||||
case FLAGS_SHL16:
|
|
||||||
case FLAGS_SHR16:
|
|
||||||
case FLAGS_SAR16:
|
|
||||||
case FLAGS_INC16:
|
|
||||||
case FLAGS_DEC16:
|
|
||||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
|
||||||
AND_HOST_REG_IMM(host_reg, 0x8000);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLAGS_ZN32:
|
|
||||||
case FLAGS_ADD32:
|
|
||||||
case FLAGS_SUB32:
|
|
||||||
case FLAGS_SHL32:
|
|
||||||
case FLAGS_SHR32:
|
|
||||||
case FLAGS_SAR32:
|
|
||||||
case FLAGS_INC32:
|
|
||||||
case FLAGS_DEC32:
|
|
||||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
|
||||||
AND_HOST_REG_IMM(host_reg, 0x80000000);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLAGS_UNKNOWN:
|
|
||||||
CALL_FUNC((uintptr_t)NF_SET);
|
|
||||||
if (not)
|
|
||||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
else
|
|
||||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ropBRANCH(name, func, not) \
|
|
||||||
static uint32_t rop ## name(uint8_t opcode, uint32_t fetchdat, \
|
|
||||||
uint32_t op_32, uint32_t op_pc, \
|
|
||||||
codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
uint32_t offset = fetchdat & 0xff; \
|
|
||||||
\
|
|
||||||
if (offset & 0x80) \
|
|
||||||
offset |= 0xffffff00; \
|
|
||||||
\
|
|
||||||
func(1, op_pc, offset, not); \
|
|
||||||
\
|
|
||||||
return op_pc+1; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _w(uint8_t opcode, \
|
|
||||||
uint32_t fetchdat, uint32_t op_32, \
|
|
||||||
uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
uint32_t offset = fetchdat & 0xffff; \
|
|
||||||
\
|
|
||||||
if (offset & 0x8000) \
|
|
||||||
offset |= 0xffff0000; \
|
|
||||||
\
|
|
||||||
func(2, op_pc, offset, not); \
|
|
||||||
\
|
|
||||||
return op_pc+2; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _l(uint8_t opcode, \
|
|
||||||
uint32_t fetchdat, uint32_t op_32, \
|
|
||||||
uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
uint32_t offset = fastreadl(cs + op_pc); \
|
|
||||||
\
|
|
||||||
func(4, op_pc, offset, not); \
|
|
||||||
\
|
|
||||||
return op_pc+4; \
|
|
||||||
}
|
|
||||||
|
|
||||||
ropBRANCH(JB, BRANCH_COND_B, 0)
|
|
||||||
ropBRANCH(JNB, BRANCH_COND_B, 1)
|
|
||||||
ropBRANCH(JE, BRANCH_COND_E, 0)
|
|
||||||
ropBRANCH(JNE, BRANCH_COND_E, 1)
|
|
||||||
ropBRANCH(JO, BRANCH_COND_O, 0)
|
|
||||||
ropBRANCH(JNO, BRANCH_COND_O, 1)
|
|
||||||
ropBRANCH(JP, BRANCH_COND_P, 0)
|
|
||||||
ropBRANCH(JNP, BRANCH_COND_P, 1)
|
|
||||||
ropBRANCH(JS, BRANCH_COND_S, 0)
|
|
||||||
ropBRANCH(JNS, BRANCH_COND_S, 1)
|
|
||||||
ropBRANCH(JL, BRANCH_COND_L, 0)
|
|
||||||
ropBRANCH(JNL, BRANCH_COND_L, 1)
|
|
||||||
ropBRANCH(JLE, BRANCH_COND_LE, 0)
|
|
||||||
ropBRANCH(JNLE, BRANCH_COND_LE, 1)
|
|
||||||
ropBRANCH(JBE, BRANCH_COND_BE, 0)
|
|
||||||
ropBRANCH(JNBE, BRANCH_COND_BE, 1)
|
|
||||||
|
|
@ -1,564 +0,0 @@
|
||||||
#define ROP_LOGIC(name, op, writeback) \
|
|
||||||
static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int src_reg, dst_reg; \
|
|
||||||
x86seg *target_seg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
dst_reg = LOAD_REG_B(fetchdat & 7); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
SAVE_EA(); \
|
|
||||||
MEM_CHECK_WRITE(target_seg); \
|
|
||||||
dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \
|
|
||||||
} \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \
|
|
||||||
src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
|
|
||||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \
|
|
||||||
if (writeback) \
|
|
||||||
{ \
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
STORE_REG_B_RELEASE(dst_reg); \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
LOAD_EA(); \
|
|
||||||
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
RELEASE_REG(dst_reg); \
|
|
||||||
RELEASE_REG(src_reg); \
|
|
||||||
\
|
|
||||||
return op_pc + 1; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int src_reg, dst_reg; \
|
|
||||||
x86seg *target_seg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
dst_reg = LOAD_REG_W(fetchdat & 7); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
SAVE_EA(); \
|
|
||||||
MEM_CHECK_WRITE_W(target_seg); \
|
|
||||||
dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \
|
|
||||||
} \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \
|
|
||||||
src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
|
|
||||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \
|
|
||||||
if (writeback) \
|
|
||||||
{ \
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
STORE_REG_W_RELEASE(dst_reg); \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
LOAD_EA(); \
|
|
||||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
RELEASE_REG(dst_reg); \
|
|
||||||
RELEASE_REG(src_reg); \
|
|
||||||
\
|
|
||||||
return op_pc + 1; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int src_reg, dst_reg; \
|
|
||||||
x86seg *target_seg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
dst_reg = LOAD_REG_L(fetchdat & 7); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
SAVE_EA(); \
|
|
||||||
MEM_CHECK_WRITE_L(target_seg); \
|
|
||||||
dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \
|
|
||||||
} \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \
|
|
||||||
src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
|
|
||||||
op ## _HOST_REG_L(dst_reg, src_reg); \
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \
|
|
||||||
if (writeback) \
|
|
||||||
{ \
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
STORE_REG_L_RELEASE(dst_reg); \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
LOAD_EA(); \
|
|
||||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
RELEASE_REG(dst_reg); \
|
|
||||||
RELEASE_REG(src_reg); \
|
|
||||||
\
|
|
||||||
return op_pc + 1; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int src_reg, dst_reg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
src_reg = LOAD_REG_B(fetchdat & 7); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg); \
|
|
||||||
src_reg = 0; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \
|
|
||||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \
|
|
||||||
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
|
|
||||||
else RELEASE_REG(dst_reg); \
|
|
||||||
RELEASE_REG(src_reg); \
|
|
||||||
\
|
|
||||||
return op_pc + 1; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int src_reg, dst_reg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
src_reg = LOAD_REG_W(fetchdat & 7); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg); \
|
|
||||||
src_reg = 0; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \
|
|
||||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \
|
|
||||||
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
|
|
||||||
else RELEASE_REG(dst_reg); \
|
|
||||||
RELEASE_REG(src_reg); \
|
|
||||||
\
|
|
||||||
return op_pc + 1; \
|
|
||||||
} \
|
|
||||||
static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int src_reg, dst_reg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
src_reg = LOAD_REG_L(fetchdat & 7); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
MEM_LOAD_ADDR_EA_L(target_seg); \
|
|
||||||
src_reg = 0; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \
|
|
||||||
op ## _HOST_REG_L(dst_reg, src_reg); \
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \
|
|
||||||
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
|
|
||||||
else RELEASE_REG(dst_reg); \
|
|
||||||
RELEASE_REG(src_reg); \
|
|
||||||
\
|
|
||||||
return op_pc + 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
ROP_LOGIC(AND, AND, 1)
|
|
||||||
ROP_LOGIC(OR, OR, 1)
|
|
||||||
ROP_LOGIC(XOR, XOR, 1)
|
|
||||||
|
|
||||||
static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int src_reg, dst_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
src_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
src_reg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
|
|
||||||
dst_reg = TEST_HOST_REG_B(dst_reg, src_reg);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg);
|
|
||||||
RELEASE_REG(dst_reg);
|
|
||||||
RELEASE_REG(src_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int src_reg, dst_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
src_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
src_reg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
|
|
||||||
dst_reg = TEST_HOST_REG_W(dst_reg, src_reg);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg);
|
|
||||||
RELEASE_REG(dst_reg);
|
|
||||||
RELEASE_REG(src_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int src_reg, dst_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
src_reg = LOAD_REG_L(fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
||||||
src_reg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
|
|
||||||
dst_reg = TEST_HOST_REG_L(dst_reg, src_reg);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg);
|
|
||||||
RELEASE_REG(dst_reg);
|
|
||||||
RELEASE_REG(src_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(REG_AL);
|
|
||||||
|
|
||||||
AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_B_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(REG_AX);
|
|
||||||
|
|
||||||
AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(REG_EAX);
|
|
||||||
|
|
||||||
fetchdat = fastreadl(cs + op_pc);
|
|
||||||
AND_HOST_REG_IMM(host_reg, fetchdat);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(REG_AL);
|
|
||||||
|
|
||||||
OR_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_B_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(REG_AX);
|
|
||||||
|
|
||||||
OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(REG_EAX);
|
|
||||||
|
|
||||||
fetchdat = fastreadl(cs + op_pc);
|
|
||||||
OR_HOST_REG_IMM(host_reg, fetchdat);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(REG_AL);
|
|
||||||
|
|
||||||
host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(REG_AX);
|
|
||||||
|
|
||||||
host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(REG_EAX);
|
|
||||||
|
|
||||||
fetchdat = fastreadl(cs + op_pc);
|
|
||||||
host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(REG_AL);
|
|
||||||
|
|
||||||
XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_B_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(REG_AX);
|
|
||||||
|
|
||||||
XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(REG_EAX);
|
|
||||||
|
|
||||||
fetchdat = fastreadl(cs + op_pc);
|
|
||||||
XOR_HOST_REG_IMM(host_reg, fetchdat);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
|
|
||||||
return op_pc + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg;
|
|
||||||
int host_reg;
|
|
||||||
uint8_t imm;
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*TEST b,#8*/
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
imm = (fetchdat >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
imm = fastreadb(cs + op_pc + 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
host_reg = 0;
|
|
||||||
}
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
|
|
||||||
host_reg = TEST_HOST_REG_IMM(host_reg, imm);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
return op_pc + 2;
|
|
||||||
|
|
||||||
case 0x10: /*NOT b*/
|
|
||||||
if ((fetchdat & 0xc0) != 0xc0)
|
|
||||||
return 0;
|
|
||||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
XOR_HOST_REG_IMM(host_reg, 0xff);
|
|
||||||
STORE_REG_B_RELEASE(host_reg);
|
|
||||||
return op_pc + 1;
|
|
||||||
|
|
||||||
case 0x18: /*NEG b*/
|
|
||||||
if ((fetchdat & 0xc0) != 0xc0)
|
|
||||||
return 0;
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8);
|
|
||||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, host_reg);
|
|
||||||
NEG_HOST_REG_B(host_reg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0);
|
|
||||||
STORE_REG_B_RELEASE(host_reg);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg;
|
|
||||||
int host_reg;
|
|
||||||
uint16_t imm;
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*TEST w,#*/
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
imm = (fetchdat >> 8) & 0xffff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
imm = fastreadw(cs + op_pc + 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
host_reg = 0;
|
|
||||||
}
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
|
|
||||||
host_reg = TEST_HOST_REG_IMM(host_reg, imm);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
return op_pc + 3;
|
|
||||||
|
|
||||||
case 0x10: /*NOT w*/
|
|
||||||
if ((fetchdat & 0xc0) != 0xc0)
|
|
||||||
return 0;
|
|
||||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
XOR_HOST_REG_IMM(host_reg, 0xffff);
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
return op_pc + 1;
|
|
||||||
|
|
||||||
case 0x18: /*NEG w*/
|
|
||||||
if ((fetchdat & 0xc0) != 0xc0)
|
|
||||||
return 0;
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16);
|
|
||||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, host_reg);
|
|
||||||
NEG_HOST_REG_W(host_reg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0);
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg;
|
|
||||||
int host_reg;
|
|
||||||
uint32_t imm;
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*TEST l,#*/
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
|
||||||
imm = fastreadl(cs + op_pc + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
imm = fastreadl(cs + op_pc + 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
||||||
host_reg = 0;
|
|
||||||
}
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
|
|
||||||
host_reg = TEST_HOST_REG_IMM(host_reg, imm);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
return op_pc + 5;
|
|
||||||
|
|
||||||
case 0x10: /*NOT l*/
|
|
||||||
if ((fetchdat & 0xc0) != 0xc0)
|
|
||||||
return 0;
|
|
||||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
|
||||||
XOR_HOST_REG_IMM(host_reg, 0xffffffff);
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
return op_pc + 1;
|
|
||||||
|
|
||||||
case 0x18: /*NEG l*/
|
|
||||||
if ((fetchdat & 0xc0) != 0xc0)
|
|
||||||
return 0;
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32);
|
|
||||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, host_reg);
|
|
||||||
NEG_HOST_REG_L(host_reg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0);
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,269 +0,0 @@
|
||||||
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
CLEAR_BITS((uintptr_t)&flags, D_FLAG);
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
SET_BITS((uintptr_t)&flags, D_FLAG);
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
|
||||||
return 0;
|
|
||||||
CLEAR_BITS((uintptr_t)&flags, I_FLAG);
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
|
||||||
return 0;
|
|
||||||
SET_BITS((uintptr_t)&flags, I_FLAG);
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) != 0x00)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
SAVE_EA();
|
|
||||||
MEM_CHECK_WRITE(target_seg);
|
|
||||||
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*INC*/
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
|
||||||
ADD_HOST_REG_IMM_B(host_reg, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
break;
|
|
||||||
case 0x08: /*DEC*/
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
|
||||||
SUB_HOST_REG_IMM_B(host_reg, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8);
|
|
||||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
STORE_REG_B_RELEASE(host_reg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOAD_EA();
|
|
||||||
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
|
|
||||||
}
|
|
||||||
codegen_flags_changed = 1;
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t codegen_temp;
|
|
||||||
static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) == 0x00)
|
|
||||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) != 0x00)
|
|
||||||
{
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
host_reg = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SAVE_EA();
|
|
||||||
MEM_CHECK_WRITE_W(target_seg);
|
|
||||||
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*INC*/
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
|
||||||
ADD_HOST_REG_IMM_W(host_reg, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOAD_EA();
|
|
||||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
|
||||||
}
|
|
||||||
codegen_flags_changed = 1;
|
|
||||||
return op_pc + 1;
|
|
||||||
case 0x08: /*DEC*/
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
|
||||||
SUB_HOST_REG_IMM_W(host_reg, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16);
|
|
||||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
STORE_REG_W_RELEASE(host_reg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOAD_EA();
|
|
||||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
|
||||||
}
|
|
||||||
codegen_flags_changed = 1;
|
|
||||||
return op_pc + 1;
|
|
||||||
|
|
||||||
case 0x10: /*CALL*/
|
|
||||||
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-2);
|
|
||||||
host_reg = LOAD_REG_IMM(op_pc + 1);
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-2);
|
|
||||||
|
|
||||||
host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp);
|
|
||||||
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 0x20: /*JMP*/
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 0x30: /*PUSH*/
|
|
||||||
if (!host_reg)
|
|
||||||
host_reg = LOAD_HOST_REG(host_reg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-2);
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-2);
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) == 0x00)
|
|
||||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) != 0x00)
|
|
||||||
{
|
|
||||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
||||||
host_reg = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SAVE_EA();
|
|
||||||
MEM_CHECK_WRITE_L(target_seg);
|
|
||||||
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*INC*/
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
|
|
||||||
ADD_HOST_REG_IMM(host_reg, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOAD_EA();
|
|
||||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
|
||||||
}
|
|
||||||
codegen_flags_changed = 1;
|
|
||||||
return op_pc + 1;
|
|
||||||
case 0x08: /*DEC*/
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
|
|
||||||
SUB_HOST_REG_IMM(host_reg, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
STORE_REG_L_RELEASE(host_reg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOAD_EA();
|
|
||||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
|
||||||
}
|
|
||||||
codegen_flags_changed = 1;
|
|
||||||
return op_pc + 1;
|
|
||||||
|
|
||||||
case 0x10: /*CALL*/
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-4);
|
|
||||||
host_reg = LOAD_REG_IMM(op_pc + 1);
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-4);
|
|
||||||
|
|
||||||
host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 0x20: /*JMP*/
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 0x30: /*PUSH*/
|
|
||||||
if (!host_reg)
|
|
||||||
host_reg = LOAD_HOST_REG(host_reg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-4);
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-4);
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,656 +0,0 @@
|
||||||
static uint32_t ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
fetchdat = fastreadl(cs + op_pc);
|
|
||||||
|
|
||||||
STORE_IMM_REG_L(opcode & 7, fetchdat);
|
|
||||||
|
|
||||||
return op_pc + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
CHECK_SEG_LIMITS(target_seg, 0);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_B(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
CHECK_SEG_LIMITS(target_seg, 1);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
host_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
CHECK_SEG_LIMITS(target_seg, 3);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_L(fetchdat & 7);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
uint32_t imm = fastreadb(cs + op_pc + 1);
|
|
||||||
int host_reg = LOAD_REG_IMM(imm);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_B(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
uint32_t imm = fastreadw(cs + op_pc + 1);
|
|
||||||
int host_reg = LOAD_REG_IMM(imm);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 3;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
uint32_t imm = fastreadl(cs + op_pc + 1);
|
|
||||||
|
|
||||||
STORE_IMM_REG_L(fetchdat & 7, imm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
uint32_t imm = fastreadl(cs + op_pc + 1);
|
|
||||||
int host_reg = LOAD_REG_IMM(imm);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t addr;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
addr = fastreadl(cs + op_pc);
|
|
||||||
else
|
|
||||||
addr = fastreadw(cs + op_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(op_ea_seg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr);
|
|
||||||
STORE_REG_TARGET_B_RELEASE(0, REG_AL);
|
|
||||||
|
|
||||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t addr;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
addr = fastreadl(cs + op_pc);
|
|
||||||
else
|
|
||||||
addr = fastreadw(cs + op_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(op_ea_seg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, REG_AX);
|
|
||||||
|
|
||||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t addr;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
addr = fastreadl(cs + op_pc);
|
|
||||||
else
|
|
||||||
addr = fastreadw(cs + op_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(op_ea_seg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, REG_EAX);
|
|
||||||
|
|
||||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t addr;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
addr = fastreadl(cs + op_pc);
|
|
||||||
else
|
|
||||||
addr = fastreadw(cs + op_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(op_ea_seg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
host_reg = LOAD_REG_B(REG_AL);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t addr;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
addr = fastreadl(cs + op_pc);
|
|
||||||
else
|
|
||||||
addr = fastreadw(cs + op_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(op_ea_seg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
host_reg = LOAD_REG_W(REG_AX);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t addr;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if (op_32 & 0x200)
|
|
||||||
addr = fastreadl(cs + op_pc);
|
|
||||||
else
|
|
||||||
addr = fastreadw(cs + op_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(op_ea_seg);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
host_reg = LOAD_REG_L(REG_EAX);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
|
|
||||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int dest_reg = (fetchdat >> 3) & 7;
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, dest_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int dest_reg = (fetchdat >> 3) & 7;
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, dest_reg);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
host_reg = ZERO_EXTEND_W_B(host_reg);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
ZERO_EXTEND_W_B(0);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
host_reg = ZERO_EXTEND_L_B(host_reg);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
ZERO_EXTEND_L_B(0);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
host_reg = ZERO_EXTEND_L_W(host_reg);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
ZERO_EXTEND_L_W(0);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
host_reg = SIGN_EXTEND_W_B(host_reg);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
SIGN_EXTEND_W_B(0);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
|
||||||
host_reg = SIGN_EXTEND_L_B(host_reg);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
|
||||||
SIGN_EXTEND_L_B(0);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
int host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
host_reg = SIGN_EXTEND_L_W(host_reg);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
SIGN_EXTEND_L_W(0);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*ES*/
|
|
||||||
host_reg = LOAD_VAR_WL((uintptr_t)&ES);
|
|
||||||
break;
|
|
||||||
case 0x08: /*CS*/
|
|
||||||
host_reg = LOAD_VAR_WL((uintptr_t)&CS);
|
|
||||||
break;
|
|
||||||
case 0x18: /*DS*/
|
|
||||||
host_reg = LOAD_VAR_WL((uintptr_t)&DS);
|
|
||||||
break;
|
|
||||||
case 0x10: /*SS*/
|
|
||||||
host_reg = LOAD_VAR_WL((uintptr_t)&SS);
|
|
||||||
break;
|
|
||||||
case 0x20: /*FS*/
|
|
||||||
host_reg = LOAD_VAR_WL((uintptr_t)&FS);
|
|
||||||
break;
|
|
||||||
case 0x28: /*GS*/
|
|
||||||
host_reg = LOAD_VAR_WL((uintptr_t)&GS);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
if (op_32 & 0x100)
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
|
|
||||||
else
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
CHECK_SEG_WRITE(target_seg);
|
|
||||||
CHECK_SEG_LIMITS(target_seg, 1);
|
|
||||||
|
|
||||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
|
||||||
RELEASE_REG(host_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*ES*/
|
|
||||||
case 0x18: /*DS*/
|
|
||||||
case 0x20: /*FS*/
|
|
||||||
case 0x28: /*GS*/
|
|
||||||
break;
|
|
||||||
case 0x10: /*SS*/
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
|
||||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
||||||
|
|
||||||
CHECK_SEG_READ(target_seg);
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
||||||
|
|
||||||
host_reg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
|
||||||
{
|
|
||||||
case 0x00: /*ES*/
|
|
||||||
LOAD_SEG(host_reg, &_es);
|
|
||||||
break;
|
|
||||||
case 0x18: /*DS*/
|
|
||||||
LOAD_SEG(host_reg, &_ds);
|
|
||||||
break;
|
|
||||||
case 0x20: /*FS*/
|
|
||||||
LOAD_SEG(host_reg, &_fs);
|
|
||||||
break;
|
|
||||||
case 0x28: /*GS*/
|
|
||||||
LOAD_SEG(host_reg, &_gs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ropLseg(seg, rseg) \
|
|
||||||
static uint32_t ropL ## seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int dest_reg = (fetchdat >> 3) & 7; \
|
|
||||||
x86seg *target_seg; \
|
|
||||||
\
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
return 0; \
|
|
||||||
\
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
SAVE_EA(); \
|
|
||||||
\
|
|
||||||
if (op_32 & 0x100) \
|
|
||||||
{ \
|
|
||||||
MEM_LOAD_ADDR_EA_L(target_seg); \
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, 0); \
|
|
||||||
LOAD_EA(); \
|
|
||||||
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
MEM_LOAD_ADDR_EA_W(target_seg); \
|
|
||||||
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, 0); \
|
|
||||||
LOAD_EA(); \
|
|
||||||
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \
|
|
||||||
} \
|
|
||||||
LOAD_SEG(0, &rseg); \
|
|
||||||
if (op_32 & 0x100) \
|
|
||||||
{ \
|
|
||||||
\
|
|
||||||
int host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); \
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
int host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); \
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (&rseg == &_ss) \
|
|
||||||
CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \
|
|
||||||
return op_pc + 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
ropLseg(DS, _ds)
|
|
||||||
ropLseg(ES, _es)
|
|
||||||
ropLseg(FS, _fs)
|
|
||||||
ropLseg(GS, _gs)
|
|
||||||
ropLseg(SS, _ss)
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
#define SHIFT(size, size2, res_store, immediate) \
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
{ \
|
|
||||||
reg = LOAD_REG_ ## size(fetchdat & 7); \
|
|
||||||
if (immediate) count = (fetchdat >> 8) & 0x1f; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
SAVE_EA(); \
|
|
||||||
MEM_CHECK_WRITE_ ## size(target_seg); \
|
|
||||||
reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \
|
|
||||||
if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \
|
|
||||||
} \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \
|
|
||||||
\
|
|
||||||
res_store((uintptr_t)&cpu_state.flags_op1, reg); \
|
|
||||||
\
|
|
||||||
switch (fetchdat & 0x38) \
|
|
||||||
{ \
|
|
||||||
case 0x20: case 0x30: /*SHL*/ \
|
|
||||||
SHL_ ## size ## _IMM(reg, count); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \
|
|
||||||
break; \
|
|
||||||
\
|
|
||||||
case 0x28: /*SHR*/ \
|
|
||||||
SHR_ ## size ## _IMM(reg, count); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \
|
|
||||||
break; \
|
|
||||||
\
|
|
||||||
case 0x38: /*SAR*/ \
|
|
||||||
SAR_ ## size ## _IMM(reg, count); \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
res_store((uintptr_t)&cpu_state.flags_res, reg); \
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
|
||||||
STORE_REG_ ## size ## _RELEASE(reg); \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
LOAD_EA(); \
|
|
||||||
MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int count;
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x38) < 0x20)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int count;
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x38) < 0x20)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int count;
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x38) < 0x20)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
|
|
||||||
|
|
||||||
return op_pc + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int count = 1;
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x38) < 0x20)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int count = 1;
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x38) < 0x20)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int count = 1;
|
|
||||||
int reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x38) < 0x20)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
|
|
||||||
|
|
||||||
return op_pc + 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,269 +0,0 @@
|
||||||
static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-2);
|
|
||||||
host_reg = LOAD_REG_W(opcode & 7);
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-2);
|
|
||||||
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-4);
|
|
||||||
host_reg = LOAD_REG_L(opcode & 7);
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-4);
|
|
||||||
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint16_t imm = fetchdat & 0xffff;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-2);
|
|
||||||
host_reg = LOAD_REG_IMM(imm);
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-2);
|
|
||||||
|
|
||||||
return op_pc+2;
|
|
||||||
}
|
|
||||||
static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t imm = fastreadl(cs + op_pc);
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-4);
|
|
||||||
host_reg = LOAD_REG_IMM(imm);
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-4);
|
|
||||||
|
|
||||||
return op_pc+4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint16_t imm = fetchdat & 0xff;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if (imm & 0x80)
|
|
||||||
imm |= 0xff00;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-2);
|
|
||||||
host_reg = LOAD_REG_IMM(imm);
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-2);
|
|
||||||
|
|
||||||
return op_pc+1;
|
|
||||||
}
|
|
||||||
static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t imm = fetchdat & 0xff;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if (imm & 0x80)
|
|
||||||
imm |= 0xffffff00;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-4);
|
|
||||||
host_reg = LOAD_REG_IMM(imm);
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-4);
|
|
||||||
|
|
||||||
return op_pc+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_W(&_ss);
|
|
||||||
SP_MODIFY(2);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
|
|
||||||
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_L(&_ss);
|
|
||||||
SP_MODIFY(4);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
|
|
||||||
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_W(&_ss);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
|
||||||
SP_MODIFY(2);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_L(&_ss);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
|
||||||
SP_MODIFY(4);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint16_t offset = fetchdat & 0xffff;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_W(&_ss);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
|
||||||
SP_MODIFY(2+offset);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint16_t offset = fetchdat & 0xffff;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_L(&_ss);
|
|
||||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
|
||||||
SP_MODIFY(4+offset);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint16_t offset = fetchdat & 0xffff;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-2);
|
|
||||||
host_reg = LOAD_REG_IMM(op_pc+2);
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-2);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
uint32_t offset = fastreadl(cs + op_pc);
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_STACK_TO_EA(-4);
|
|
||||||
host_reg = LOAD_REG_IMM(op_pc+4);
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
|
||||||
SP_MODIFY(-4);
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_EBP_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_W(&_ss);
|
|
||||||
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
|
|
||||||
ADD_HOST_REG_IMM_W(host_reg, 2);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
|
|
||||||
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
|
|
||||||
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
||||||
{
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
||||||
LOAD_EBP_TO_EA(0);
|
|
||||||
MEM_LOAD_ADDR_EA_L(&_ss);
|
|
||||||
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
|
|
||||||
ADD_HOST_REG_IMM(host_reg, 4);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
|
|
||||||
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
|
|
||||||
|
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ROP_PUSH_SEG(seg) \
|
|
||||||
static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int host_reg; \
|
|
||||||
\
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
LOAD_STACK_TO_EA(-2); \
|
|
||||||
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
|
|
||||||
MEM_STORE_ADDR_EA_W(&_ss, host_reg); \
|
|
||||||
SP_MODIFY(-2); \
|
|
||||||
\
|
|
||||||
return op_pc; \
|
|
||||||
} \
|
|
||||||
static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
int host_reg; \
|
|
||||||
\
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
LOAD_STACK_TO_EA(-4); \
|
|
||||||
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
|
|
||||||
MEM_STORE_ADDR_EA_L(&_ss, host_reg); \
|
|
||||||
SP_MODIFY(-4); \
|
|
||||||
\
|
|
||||||
return op_pc; \
|
|
||||||
}
|
|
||||||
|
|
||||||
ROP_PUSH_SEG(CS)
|
|
||||||
ROP_PUSH_SEG(DS)
|
|
||||||
ROP_PUSH_SEG(ES)
|
|
||||||
ROP_PUSH_SEG(FS)
|
|
||||||
ROP_PUSH_SEG(GS)
|
|
||||||
ROP_PUSH_SEG(SS)
|
|
||||||
|
|
||||||
#define ROP_POP_SEG(seg, rseg) \
|
|
||||||
static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
LOAD_STACK_TO_EA(0); \
|
|
||||||
MEM_LOAD_ADDR_EA_W(&_ss); \
|
|
||||||
LOAD_SEG(0, &rseg); \
|
|
||||||
SP_MODIFY(2); \
|
|
||||||
\
|
|
||||||
return op_pc; \
|
|
||||||
} \
|
|
||||||
static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
||||||
{ \
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
||||||
LOAD_STACK_TO_EA(0); \
|
|
||||||
MEM_LOAD_ADDR_EA_W(&_ss); \
|
|
||||||
LOAD_SEG(0, &rseg); \
|
|
||||||
SP_MODIFY(4); \
|
|
||||||
\
|
|
||||||
return op_pc; \
|
|
||||||
}
|
|
||||||
|
|
||||||
ROP_POP_SEG(DS, _ds)
|
|
||||||
ROP_POP_SEG(ES, _es)
|
|
||||||
ROP_POP_SEG(FS, _fs)
|
|
||||||
ROP_POP_SEG(GS, _gs)
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
}
|
|
||||||
2180
src/codegen_x86.c
2180
src/codegen_x86.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#include <wx/progdlg.h>
|
#include <wx/progdlg.h>
|
||||||
#include <wx/choicebk.h>
|
#include <wx/choicebk.h>
|
||||||
|
#include <wx/combobox.h>
|
||||||
|
|
||||||
#include "wx-dialogbox.h"
|
#include "wx-dialogbox.h"
|
||||||
#include "wx-app.h"
|
#include "wx-app.h"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue