Merge from trunk
This commit is contained in:
commit
50e7de5214
282 changed files with 51494 additions and 22451 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.
|
||||||
|
|
|
||||||
129
src/386.c
129
src/386.c
|
|
@ -2,7 +2,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ibm.h"
|
#include "ibm.h"
|
||||||
#include "386.h"
|
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "x87.h"
|
#include "x87.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
@ -13,56 +12,15 @@
|
||||||
#include "nmi.h"
|
#include "nmi.h"
|
||||||
|
|
||||||
#include "386_common.h"
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
|
||||||
|
#undef CPU_BLOCK_END
|
||||||
#define CPU_BLOCK_END()
|
#define CPU_BLOCK_END()
|
||||||
|
|
||||||
extern int codegen_flags_changed;
|
|
||||||
|
|
||||||
extern int nmi_enable;
|
|
||||||
|
|
||||||
int inscounts[256];
|
|
||||||
uint32_t oldpc2;
|
|
||||||
|
|
||||||
int trap;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern int cpl_override;
|
|
||||||
|
|
||||||
int has_fpu;
|
|
||||||
extern int fpucount;
|
|
||||||
uint16_t rds;
|
|
||||||
uint16_t ea_rseg;
|
|
||||||
|
|
||||||
int is486;
|
|
||||||
int cgate32;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t romext[32768];
|
|
||||||
uint8_t *ram,*rom;
|
|
||||||
|
|
||||||
uint32_t rmdat32;
|
|
||||||
#define rmdat rmdat32
|
|
||||||
#define fetchdat rmdat32
|
|
||||||
uint32_t backupregs[16];
|
|
||||||
extern int oddeven;
|
|
||||||
int inttype;
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t oldcs2;
|
|
||||||
uint32_t oldecx;
|
|
||||||
|
|
||||||
uint32_t *eal_r, *eal_w;
|
|
||||||
|
|
||||||
uint16_t *mod1add[2][8];
|
|
||||||
uint32_t *mod1seg[8];
|
|
||||||
|
|
||||||
static inline void fetch_ea_32_long(uint32_t rmdat)
|
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;
|
|
||||||
if (cpu_rm == 4)
|
if (cpu_rm == 4)
|
||||||
{
|
{
|
||||||
uint8_t sib = rmdat >> 8;
|
uint8_t sib = rmdat >> 8;
|
||||||
|
|
@ -89,8 +47,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
|
||||||
else if ((sib & 6) == 4 && !cpu_state.ssegs)
|
else if ((sib & 6) == 4 && !cpu_state.ssegs)
|
||||||
{
|
{
|
||||||
easeg = ss;
|
easeg = ss;
|
||||||
ea_rseg = SS;
|
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||||
cpu_state.ea_seg = &_ss;
|
|
||||||
}
|
}
|
||||||
if (((sib >> 3) & 7) != 4)
|
if (((sib >> 3) & 7) != 4)
|
||||||
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
|
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
|
||||||
|
|
@ -103,8 +60,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
|
||||||
if (cpu_rm == 5 && !cpu_state.ssegs)
|
if (cpu_rm == 5 && !cpu_state.ssegs)
|
||||||
{
|
{
|
||||||
easeg = ss;
|
easeg = ss;
|
||||||
ea_rseg = SS;
|
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||||
cpu_state.ea_seg = &_ss;
|
|
||||||
}
|
}
|
||||||
if (cpu_mod == 1)
|
if (cpu_mod == 1)
|
||||||
{
|
{
|
||||||
|
|
@ -135,7 +91,6 @@ 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;
|
|
||||||
if (!cpu_mod && cpu_rm == 6)
|
if (!cpu_mod && cpu_rm == 6)
|
||||||
{
|
{
|
||||||
cpu_state.eaaddr = getword();
|
cpu_state.eaaddr = getword();
|
||||||
|
|
@ -158,8 +113,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
|
||||||
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
|
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
|
||||||
{
|
{
|
||||||
easeg = ss;
|
easeg = ss;
|
||||||
ea_rseg = SS;
|
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||||
cpu_state.ea_seg = &_ss;
|
|
||||||
}
|
}
|
||||||
cpu_state.eaaddr &= 0xFFFF;
|
cpu_state.eaaddr &= 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
@ -182,19 +136,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
|
||||||
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
|
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
|
||||||
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
|
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
|
||||||
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
|
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
|
||||||
extern int xout;
|
|
||||||
|
|
||||||
int oldi;
|
|
||||||
|
|
||||||
uint32_t testr[9];
|
|
||||||
extern int dontprint;
|
|
||||||
|
|
||||||
#undef NOTRM
|
|
||||||
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
|
|
||||||
{ \
|
|
||||||
x86_int(6); \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define OP_TABLE(name) ops_ ## name
|
#define OP_TABLE(name) ops_ ## name
|
||||||
|
|
||||||
|
|
@ -203,13 +145,6 @@ extern int dontprint;
|
||||||
|
|
||||||
#include "x86_ops.h"
|
#include "x86_ops.h"
|
||||||
|
|
||||||
#undef NOTRM
|
|
||||||
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
|
|
||||||
{ \
|
|
||||||
x86_int(6); \
|
|
||||||
break; \
|
|
||||||
}
|
|
||||||
|
|
||||||
void exec386(int cycs)
|
void exec386(int cycs)
|
||||||
{
|
{
|
||||||
uint8_t temp;
|
uint8_t temp;
|
||||||
|
|
@ -222,42 +157,31 @@ void exec386(int cycs)
|
||||||
// output=3;
|
// output=3;
|
||||||
while (cycles>0)
|
while (cycles>0)
|
||||||
{
|
{
|
||||||
int cycle_period = (timer_count >> TIMER_SHIFT) + 1;
|
int cycle_period = (timer_target - (uint32_t)tsc) + 1;
|
||||||
|
|
||||||
x86_was_reset = 0;
|
x86_was_reset = 0;
|
||||||
cycdiff=0;
|
cycdiff=0;
|
||||||
oldcyc=cycles;
|
oldcyc=cycles;
|
||||||
timer_start_period(cycles << TIMER_SHIFT);
|
|
||||||
// pclog("%i %02X\n", ins, ram[8]);
|
// pclog("%i %02X\n", ins, ram[8]);
|
||||||
while (cycdiff < cycle_period)
|
while (cycdiff < cycle_period)
|
||||||
{
|
{
|
||||||
/* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX;
|
|
||||||
testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/
|
|
||||||
/* testr[8]=flags;*/
|
|
||||||
// oldcs2=oldcs;
|
|
||||||
// oldpc2=oldpc;
|
|
||||||
|
|
||||||
oldcs=CS;
|
|
||||||
cpu_state.oldpc = cpu_state.pc;
|
cpu_state.oldpc = cpu_state.pc;
|
||||||
oldcpl=CPL;
|
|
||||||
cpu_state.op32 = use32;
|
cpu_state.op32 = use32;
|
||||||
|
|
||||||
dontprint=0;
|
cpu_state.ea_seg = &cpu_state.seg_ds;
|
||||||
|
|
||||||
cpu_state.ea_seg = &_ds;
|
|
||||||
cpu_state.ssegs = 0;
|
cpu_state.ssegs = 0;
|
||||||
|
|
||||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||||
|
|
||||||
if (!cpu_state.abrt)
|
if (!cpu_state.abrt)
|
||||||
{
|
{
|
||||||
trap = flags & T_FLAG;
|
uint8_t opcode = fetchdat & 0xFF;
|
||||||
opcode = fetchdat & 0xFF;
|
|
||||||
fetchdat >>= 8;
|
fetchdat >>= 8;
|
||||||
|
trap = cpu_state.flags & T_FLAG;
|
||||||
|
|
||||||
if (output == 3)
|
if (output == 3)
|
||||||
{
|
{
|
||||||
pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]);
|
pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,cpu_state.flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask);
|
||||||
}
|
}
|
||||||
cpu_state.pc++;
|
cpu_state.pc++;
|
||||||
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
||||||
|
|
@ -265,29 +189,17 @@ dontprint=0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use32) cpu_state.pc &= 0xffff;
|
|
||||||
|
|
||||||
if (cpu_state.abrt)
|
if (cpu_state.abrt)
|
||||||
{
|
{
|
||||||
flags_rebuild();
|
flags_rebuild();
|
||||||
// pclog("Abort\n");
|
// pclog("Abort\n");
|
||||||
// if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
|
// if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
|
||||||
/* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc);
|
|
||||||
if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc);
|
|
||||||
if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc);
|
|
||||||
if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc);
|
|
||||||
if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc);
|
|
||||||
if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc);
|
|
||||||
if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc);
|
|
||||||
if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/
|
|
||||||
/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/
|
|
||||||
tempi = cpu_state.abrt;
|
tempi = cpu_state.abrt;
|
||||||
cpu_state.abrt = 0;
|
cpu_state.abrt = 0;
|
||||||
x86_doabrt(tempi);
|
x86_doabrt(tempi);
|
||||||
if (cpu_state.abrt)
|
if (cpu_state.abrt)
|
||||||
{
|
{
|
||||||
cpu_state.abrt = 0;
|
cpu_state.abrt = 0;
|
||||||
CS = oldcs;
|
|
||||||
cpu_state.pc = cpu_state.oldpc;
|
cpu_state.pc = cpu_state.oldpc;
|
||||||
pclog("Double fault %i\n", ins);
|
pclog("Double fault %i\n", ins);
|
||||||
pmodeint(8, 0);
|
pmodeint(8, 0);
|
||||||
|
|
@ -306,20 +218,19 @@ dontprint=0;
|
||||||
{
|
{
|
||||||
flags_rebuild();
|
flags_rebuild();
|
||||||
// oldpc=pc;
|
// oldpc=pc;
|
||||||
// oldcs=CS;
|
|
||||||
if (msw&1)
|
if (msw&1)
|
||||||
{
|
{
|
||||||
pmodeint(1,0);
|
pmodeint(1,0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writememw(ss,(SP-2)&0xFFFF,flags);
|
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
|
||||||
writememw(ss,(SP-4)&0xFFFF,CS);
|
writememw(ss,(SP-4)&0xFFFF,CS);
|
||||||
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
|
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
|
||||||
SP-=6;
|
SP-=6;
|
||||||
addr = (1 << 2) + idt.base;
|
addr = (1 << 2) + idt.base;
|
||||||
flags&=~I_FLAG;
|
cpu_state.flags &= ~I_FLAG;
|
||||||
flags&=~T_FLAG;
|
cpu_state.flags &= ~T_FLAG;
|
||||||
cpu_state.pc=readmemw(0,addr);
|
cpu_state.pc=readmemw(0,addr);
|
||||||
loadcs(readmemw(0,addr+2));
|
loadcs(readmemw(0,addr+2));
|
||||||
}
|
}
|
||||||
|
|
@ -327,7 +238,6 @@ dontprint=0;
|
||||||
else if (nmi && nmi_enable && nmi_mask)
|
else if (nmi && nmi_enable && nmi_mask)
|
||||||
{
|
{
|
||||||
cpu_state.oldpc = cpu_state.pc;
|
cpu_state.oldpc = cpu_state.pc;
|
||||||
oldcs = CS;
|
|
||||||
// pclog("NMI\n");
|
// pclog("NMI\n");
|
||||||
x86_int(2);
|
x86_int(2);
|
||||||
nmi_enable = 0;
|
nmi_enable = 0;
|
||||||
|
|
@ -337,7 +247,7 @@ dontprint=0;
|
||||||
nmi = 0;
|
nmi = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((flags&I_FLAG) && pic_intpending)
|
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
|
||||||
{
|
{
|
||||||
temp=picinterrupt();
|
temp=picinterrupt();
|
||||||
if (temp!=0xFF)
|
if (temp!=0xFF)
|
||||||
|
|
@ -353,14 +263,13 @@ dontprint=0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writememw(ss,(SP-2)&0xFFFF,flags);
|
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
|
||||||
writememw(ss,(SP-4)&0xFFFF,CS);
|
writememw(ss,(SP-4)&0xFFFF,CS);
|
||||||
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
|
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
|
||||||
SP-=6;
|
SP-=6;
|
||||||
addr = (temp << 2) + idt.base;
|
addr = (temp << 2) + idt.base;
|
||||||
flags&=~I_FLAG;
|
cpu_state.flags &= ~I_FLAG;
|
||||||
flags&=~T_FLAG;
|
cpu_state.flags &= ~T_FLAG;
|
||||||
oxpc=cpu_state.pc;
|
|
||||||
cpu_state.pc=readmemw(0,addr);
|
cpu_state.pc=readmemw(0,addr);
|
||||||
loadcs(readmemw(0,addr+2));
|
loadcs(readmemw(0,addr+2));
|
||||||
// if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
|
// if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
|
||||||
|
|
@ -381,7 +290,7 @@ dontprint=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tsc += cycdiff;
|
tsc += cycdiff;
|
||||||
|
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
|
||||||
timer_end_period(cycles << TIMER_SHIFT);
|
timer_process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
src/386.h
13
src/386.h
|
|
@ -1,13 +0,0 @@
|
||||||
extern void cpu_386_flags_extract();
|
|
||||||
extern void cpu_386_flags_rebuild();
|
|
||||||
|
|
||||||
void pmodeint(int num, int soft);
|
|
||||||
void loadcscall(uint16_t seg);
|
|
||||||
void loadcsjmp(uint16_t seg, uint32_t oxpc);
|
|
||||||
void pmoderetf(int is32, uint16_t off);
|
|
||||||
void pmodeiret(int is32);
|
|
||||||
void x86_int_sw(int num);
|
|
||||||
int x86_int_sw_rm(int num);
|
|
||||||
|
|
||||||
int divl(uint32_t val);
|
|
||||||
int idivl(int32_t val);
|
|
||||||
249
src/386_common.c
Normal file
249
src/386_common.c
Normal file
|
|
@ -0,0 +1,249 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
|
||||||
|
x86seg gdt, ldt, idt, tr;
|
||||||
|
|
||||||
|
uint32_t cr2, cr3, cr4;
|
||||||
|
uint32_t dr[8];
|
||||||
|
|
||||||
|
uint32_t use32;
|
||||||
|
int stack32;
|
||||||
|
int optype;
|
||||||
|
|
||||||
|
int trap;
|
||||||
|
|
||||||
|
uint32_t rmdat;
|
||||||
|
|
||||||
|
uint32_t *eal_r, *eal_w;
|
||||||
|
|
||||||
|
int nmi_enable = 1;
|
||||||
|
|
||||||
|
int cpl_override=0;
|
||||||
|
|
||||||
|
int fpucount=0;
|
||||||
|
|
||||||
|
uint16_t cpu_cur_status = 0;
|
||||||
|
|
||||||
|
uint32_t pccache;
|
||||||
|
uint8_t *pccache2;
|
||||||
|
|
||||||
|
void x86_int(int num)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
// pclog("x86_int %02x %04x:%04x\n", num, CS,pc);
|
||||||
|
flags_rebuild();
|
||||||
|
cpu_state.pc=cpu_state.oldpc;
|
||||||
|
if (msw&1)
|
||||||
|
{
|
||||||
|
pmodeint(num,0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = (num << 2) + idt.base;
|
||||||
|
|
||||||
|
if ((num << 2) + 3 > idt.limit)
|
||||||
|
{
|
||||||
|
if (idt.limit < 35)
|
||||||
|
{
|
||||||
|
cpu_state.abrt = 0;
|
||||||
|
softresetx86();
|
||||||
|
cpu_set_edx();
|
||||||
|
pclog("Triple fault in real mode - reset\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
x86_int(8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
writememw(ss,ESP-2,cpu_state.flags);
|
||||||
|
writememw(ss,ESP-4,CS);
|
||||||
|
writememw(ss,ESP-6,cpu_state.pc);
|
||||||
|
ESP-=6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
|
||||||
|
writememw(ss,((SP-4)&0xFFFF),CS);
|
||||||
|
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
|
||||||
|
SP-=6;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_state.flags &= ~I_FLAG;
|
||||||
|
cpu_state.flags &= ~T_FLAG;
|
||||||
|
cpu_state.pc=readmemw(0,addr);
|
||||||
|
loadcs(readmemw(0,addr+2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cycles-=70;
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
void x86_int_sw(int num)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
// pclog("x86_int_sw %02x %04x:%04x\n", num, CS,pc);
|
||||||
|
// pclog("x86_int\n");
|
||||||
|
flags_rebuild();
|
||||||
|
cycles -= timing_int;
|
||||||
|
if (msw&1)
|
||||||
|
{
|
||||||
|
pmodeint(num,1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = (num << 2) + idt.base;
|
||||||
|
|
||||||
|
if ((num << 2) + 3 > idt.limit)
|
||||||
|
{
|
||||||
|
x86_int(13);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
writememw(ss,ESP-2,cpu_state.flags);
|
||||||
|
writememw(ss,ESP-4,CS);
|
||||||
|
writememw(ss,ESP-6,cpu_state.pc);
|
||||||
|
ESP-=6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
|
||||||
|
writememw(ss,((SP-4)&0xFFFF),CS);
|
||||||
|
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
|
||||||
|
SP-=6;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_state.flags &= ~I_FLAG;
|
||||||
|
cpu_state.flags &= ~T_FLAG;
|
||||||
|
cpu_state.pc=readmemw(0,addr);
|
||||||
|
loadcs(readmemw(0,addr+2));
|
||||||
|
cycles -= timing_int_rm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trap = 0;
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
int x86_int_sw_rm(int num)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
uint16_t new_pc, new_cs;
|
||||||
|
|
||||||
|
flags_rebuild();
|
||||||
|
cycles -= timing_int;
|
||||||
|
|
||||||
|
addr = num << 2;
|
||||||
|
new_pc = readmemw(0, addr);
|
||||||
|
new_cs = readmemw(0, addr + 2);
|
||||||
|
|
||||||
|
if (cpu_state.abrt) return 1;
|
||||||
|
|
||||||
|
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; }
|
||||||
|
writememw(ss,((SP-4)&0xFFFF),CS);
|
||||||
|
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; }
|
||||||
|
SP-=6;
|
||||||
|
|
||||||
|
cpu_state.eflags &= ~VIF_FLAG;
|
||||||
|
cpu_state.flags &= ~T_FLAG;
|
||||||
|
cpu_state.pc = new_pc;
|
||||||
|
loadcs(new_cs);
|
||||||
|
|
||||||
|
cycles -= timing_int_rm;
|
||||||
|
trap = 0;
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void x86illegal()
|
||||||
|
{
|
||||||
|
// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);
|
||||||
|
|
||||||
|
// if (output)
|
||||||
|
// {
|
||||||
|
// dumpregs();
|
||||||
|
// exit(-1);
|
||||||
|
// }
|
||||||
|
x86_int(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkio(int port)
|
||||||
|
{
|
||||||
|
uint16_t t;
|
||||||
|
uint8_t d;
|
||||||
|
cpl_override = 1;
|
||||||
|
t = readmemw(tr.base, 0x66);
|
||||||
|
cpl_override = 0;
|
||||||
|
// pclog("CheckIO 1 %08X %04x %02x\n",tr.base, eflags, _cs.access);
|
||||||
|
if (cpu_state.abrt) return 0;
|
||||||
|
// pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3));
|
||||||
|
if ((t+(port>>3))>tr.limit) return 1;
|
||||||
|
cpl_override = 1;
|
||||||
|
d = readmembl(tr.base + t + (port >> 3));
|
||||||
|
// d=readmemb(tr.base,t+(port>>3));
|
||||||
|
cpl_override = 0;
|
||||||
|
// pclog("%02X %02X\n",d,d&(1<<(port&7)));
|
||||||
|
return d&(1<<(port&7));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define divexcp() { \
|
||||||
|
pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \
|
||||||
|
x86_int(0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
int divl(uint32_t val)
|
||||||
|
{
|
||||||
|
if (val==0)
|
||||||
|
{
|
||||||
|
divexcp();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint64_t num=(((uint64_t)EDX)<<32)|EAX;
|
||||||
|
uint64_t quo=num/val;
|
||||||
|
uint32_t rem=num%val;
|
||||||
|
uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF);
|
||||||
|
if (quo!=(uint64_t)quo32)
|
||||||
|
{
|
||||||
|
divexcp();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
EDX=rem;
|
||||||
|
EAX=quo32;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int idivl(int32_t val)
|
||||||
|
{
|
||||||
|
if (val==0)
|
||||||
|
{
|
||||||
|
divexcp();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int64_t num=(((uint64_t)EDX)<<32)|EAX;
|
||||||
|
int64_t quo=num/val;
|
||||||
|
int32_t rem=num%val;
|
||||||
|
int32_t quo32=(int32_t)(quo&0xFFFFFFFF);
|
||||||
|
if (quo!=(int64_t)quo32)
|
||||||
|
{
|
||||||
|
divexcp();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
EDX=rem;
|
||||||
|
EAX=quo32;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cpu_386_flags_extract()
|
||||||
|
{
|
||||||
|
flags_extract();
|
||||||
|
}
|
||||||
|
void cpu_386_flags_rebuild()
|
||||||
|
{
|
||||||
|
flags_rebuild();
|
||||||
|
}
|
||||||
100
src/386_common.h
100
src/386_common.h
|
|
@ -1,21 +1,19 @@
|
||||||
extern uint16_t ea_rseg;
|
#ifndef _386_COMMON_H_
|
||||||
|
#define _386_COMMON_H_
|
||||||
|
|
||||||
#undef readmemb
|
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
|
||||||
#undef writememb
|
#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
|
||||||
|
#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
|
||||||
|
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
|
||||||
|
|
||||||
|
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
||||||
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
|
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
||||||
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
|
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
||||||
|
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
||||||
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
|
||||||
|
|
||||||
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
|
||||||
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
|
||||||
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
|
|
||||||
|
|
||||||
int checkio(int port);
|
int checkio(int port);
|
||||||
|
|
||||||
#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
|
#define check_io_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \
|
||||||
{ \
|
{ \
|
||||||
int tempi = checkio(port); \
|
int tempi = checkio(port); \
|
||||||
if (cpu_state.abrt) return 1; \
|
if (cpu_state.abrt) return 1; \
|
||||||
|
|
@ -26,26 +24,35 @@ int checkio(int port);
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
|
#define SEG_CHECK_READ(seg) \
|
||||||
{ \
|
do \
|
||||||
int tempi = checkio(port); \
|
{ \
|
||||||
if (cpu_state.abrt) break; \
|
if ((seg)->base == 0xffffffff) \
|
||||||
if (tempi) \
|
{ \
|
||||||
{ \
|
x86gpf("Segment can't read", 0);\
|
||||||
x86gpf(NULL,0); \
|
return 1; \
|
||||||
break; \
|
} \
|
||||||
} \
|
} while (0)
|
||||||
}
|
|
||||||
|
#define SEG_CHECK_WRITE(seg) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if ((seg)->base == 0xffffffff) \
|
||||||
|
{ \
|
||||||
|
x86gpf("Segment can't write", 0);\
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define CHECK_READ(seg, low, high) \
|
#define CHECK_READ(seg, low, high) \
|
||||||
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \
|
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \
|
||||||
{ \
|
{ \
|
||||||
x86gpf("Limit check", 0); \
|
x86gpf("Limit check", 0); \
|
||||||
return 1; \
|
return 1; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_WRITE(seg, low, high) \
|
#define CHECK_WRITE(seg, low, high) \
|
||||||
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(eflags & VM_FLAG) && ((seg)->access & 8))) \
|
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((seg)->access & 8))) \
|
||||||
{ \
|
{ \
|
||||||
x86gpf("Limit check", 0); \
|
x86gpf("Limit check", 0); \
|
||||||
return 1; \
|
return 1; \
|
||||||
|
|
@ -59,7 +66,7 @@ int checkio(int port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
|
#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
|
||||||
{ \
|
{ \
|
||||||
x86_int(6); \
|
x86_int(6); \
|
||||||
return 1; \
|
return 1; \
|
||||||
|
|
@ -124,6 +131,17 @@ static inline uint32_t fastreadl(uint32_t a)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void *get_ram_ptr(uint32_t a)
|
||||||
|
{
|
||||||
|
if ((a >> 12) == pccache)
|
||||||
|
return &pccache2[a];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t *t = getpccache(a);
|
||||||
|
return &t[a];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint8_t getbyte()
|
static inline uint8_t getbyte()
|
||||||
{
|
{
|
||||||
cpu_state.pc++;
|
cpu_state.pc++;
|
||||||
|
|
@ -156,32 +174,30 @@ static inline uint8_t geteab()
|
||||||
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
|
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
|
||||||
if (eal_r)
|
if (eal_r)
|
||||||
return *(uint8_t *)eal_r;
|
return *(uint8_t *)eal_r;
|
||||||
return readmemb(easeg, cpu_state.eaaddr);
|
return readmemb(easeg,cpu_state.eaaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t geteaw()
|
static inline uint16_t geteaw()
|
||||||
{
|
{
|
||||||
if (cpu_mod == 3)
|
if (cpu_mod == 3)
|
||||||
return cpu_state.regs[cpu_rm].w;
|
return cpu_state.regs[cpu_rm].w;
|
||||||
// cycles-=3;
|
|
||||||
if (eal_r)
|
if (eal_r)
|
||||||
return *(uint16_t *)eal_r;
|
return *(uint16_t *)eal_r;
|
||||||
return readmemw(easeg, cpu_state.eaaddr);
|
return readmemw(easeg,cpu_state.eaaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t geteal()
|
static inline uint32_t geteal()
|
||||||
{
|
{
|
||||||
if (cpu_mod == 3)
|
if (cpu_mod == 3)
|
||||||
return cpu_state.regs[cpu_rm].l;
|
return cpu_state.regs[cpu_rm].l;
|
||||||
// cycles-=3;
|
|
||||||
if (eal_r)
|
if (eal_r)
|
||||||
return *eal_r;
|
return *eal_r;
|
||||||
return readmeml(easeg, cpu_state.eaaddr);
|
return readmeml(easeg,cpu_state.eaaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t geteaq()
|
static inline uint64_t geteaq()
|
||||||
{
|
{
|
||||||
return readmemq(easeg, cpu_state.eaaddr);
|
return readmemq(easeg,cpu_state.eaaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t geteab_mem()
|
static inline uint8_t geteab_mem()
|
||||||
|
|
@ -202,24 +218,20 @@ static inline uint32_t geteal_mem()
|
||||||
|
|
||||||
static inline void seteaq(uint64_t v)
|
static inline void seteaq(uint64_t v)
|
||||||
{
|
{
|
||||||
writememql(easeg, cpu_state.eaaddr, v);
|
writememql(easeg+cpu_state.eaaddr, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
|
#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
|
||||||
#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
|
#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
|
||||||
#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
|
#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
|
||||||
|
|
||||||
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v);
|
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v);
|
||||||
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v);
|
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v);
|
||||||
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v);
|
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v);
|
||||||
|
|
||||||
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
|
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
|
||||||
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
|
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
|
||||||
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
|
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
|
||||||
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
|
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
|
||||||
|
|
||||||
|
#endif
|
||||||
#define rmdat rmdat32
|
|
||||||
#define fetchdat rmdat32
|
|
||||||
|
|
||||||
void x86_int(int num);
|
|
||||||
|
|
|
||||||
1016
src/386_dynarec.c
1016
src/386_dynarec.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,5 @@
|
||||||
#include "ibm.h"
|
#include "ibm.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "386.h"
|
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "x86_ops.h"
|
#include "x86_ops.h"
|
||||||
#include "x87.h"
|
#include "x87.h"
|
||||||
|
|
@ -15,14 +14,10 @@
|
||||||
#include "386_common.h"
|
#include "386_common.h"
|
||||||
|
|
||||||
|
|
||||||
extern uint16_t *mod1add[2][8];
|
|
||||||
extern uint32_t *mod1seg[8];
|
|
||||||
|
|
||||||
static inline void fetch_ea_32_long(uint32_t rmdat)
|
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;
|
|
||||||
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;
|
||||||
|
|
@ -37,7 +32,6 @@ 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;
|
|
||||||
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;
|
||||||
|
|
@ -57,6 +51,7 @@ 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
|
||||||
|
/*Temporary*/
|
||||||
#define CLOCK_CYCLES(c)
|
#define CLOCK_CYCLES(c)
|
||||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||||
|
|
||||||
|
|
|
||||||
110
src/386_ops.h
110
src/386_ops.h
|
|
@ -104,6 +104,15 @@ static inline uint32_t POP_L_seg(uint32_t seg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ILLEGAL(uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
cpu_state.pc = cpu_state.oldpc;
|
||||||
|
|
||||||
|
// fatal("Illegal instruction %08X\n", fetchdat);
|
||||||
|
x86illegal();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#include "x86_ops_arith.h"
|
#include "x86_ops_arith.h"
|
||||||
#include "x86_ops_atomic.h"
|
#include "x86_ops_atomic.h"
|
||||||
#include "x86_ops_bcd.h"
|
#include "x86_ops_bcd.h"
|
||||||
|
|
@ -118,6 +127,7 @@ static inline uint32_t POP_L_seg(uint32_t seg)
|
||||||
#include "x86_ops_jump.h"
|
#include "x86_ops_jump.h"
|
||||||
#include "x86_ops_misc.h"
|
#include "x86_ops_misc.h"
|
||||||
#include "x86_ops_mmx.h"
|
#include "x86_ops_mmx.h"
|
||||||
|
#include "x86_ops_3dnow.h"
|
||||||
#include "x86_ops_mmx_arith.h"
|
#include "x86_ops_mmx_arith.h"
|
||||||
#include "x86_ops_mmx_cmp.h"
|
#include "x86_ops_mmx_cmp.h"
|
||||||
#include "x86_ops_mmx_logic.h"
|
#include "x86_ops_mmx_logic.h"
|
||||||
|
|
@ -140,15 +150,6 @@ static inline uint32_t POP_L_seg(uint32_t seg)
|
||||||
#include "x86_ops_string.h"
|
#include "x86_ops_string.h"
|
||||||
#include "x86_ops_xchg.h"
|
#include "x86_ops_xchg.h"
|
||||||
|
|
||||||
static int ILLEGAL(uint32_t fetchdat)
|
|
||||||
{
|
|
||||||
cpu_state.pc = cpu_state.oldpc;
|
|
||||||
|
|
||||||
// fatal("Illegal instruction %08X\n", fetchdat);
|
|
||||||
x86illegal();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int op0F_w_a16(uint32_t fetchdat)
|
static int op0F_w_a16(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
int opcode = fetchdat & 0xff;
|
int opcode = fetchdat & 0xff;
|
||||||
|
|
@ -455,6 +456,97 @@ OpFn OP_TABLE(winchip_0f)[1024] =
|
||||||
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OpFn OP_TABLE(winchip2_0f)[1024] =
|
||||||
|
{
|
||||||
|
/*16-bit data, 16-bit addr*/
|
||||||
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
|
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
|
||||||
|
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
|
||||||
|
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
|
||||||
|
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
|
||||||
|
|
||||||
|
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
|
||||||
|
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
|
||||||
|
/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
|
||||||
|
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
|
||||||
|
|
||||||
|
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||||
|
/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
|
||||||
|
/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
|
||||||
|
/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
|
||||||
|
|
||||||
|
/*32-bit data, 16-bit addr*/
|
||||||
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
|
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
|
||||||
|
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
|
||||||
|
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
|
||||||
|
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
|
||||||
|
|
||||||
|
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
|
||||||
|
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
|
||||||
|
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
|
||||||
|
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
|
||||||
|
|
||||||
|
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||||
|
/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
|
||||||
|
/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
|
||||||
|
/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
|
||||||
|
|
||||||
|
/*16-bit data, 32-bit addr*/
|
||||||
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
|
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
|
||||||
|
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
|
||||||
|
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
|
||||||
|
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
|
||||||
|
|
||||||
|
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
|
||||||
|
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
|
||||||
|
/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
|
||||||
|
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
|
||||||
|
|
||||||
|
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||||
|
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
|
||||||
|
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
|
||||||
|
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
||||||
|
|
||||||
|
/*32-bit data, 32-bit addr*/
|
||||||
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
|
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
|
||||||
|
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
|
||||||
|
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||||
|
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
|
||||||
|
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
|
||||||
|
|
||||||
|
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
|
||||||
|
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
|
||||||
|
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
|
||||||
|
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
|
||||||
|
|
||||||
|
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
|
||||||
|
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
|
||||||
|
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
|
||||||
|
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
|
||||||
|
};
|
||||||
|
|
||||||
OpFn OP_TABLE(pentium_0f)[1024] =
|
OpFn OP_TABLE(pentium_0f)[1024] =
|
||||||
{
|
{
|
||||||
/*16-bit data, 16-bit addr*/
|
/*16-bit data, 16-bit addr*/
|
||||||
|
|
|
||||||
1050
src/808x.c
1050
src/808x.c
File diff suppressed because it is too large
Load diff
|
|
@ -23,24 +23,26 @@ wx-resources.cpp : pc.xrc
|
||||||
-wxrc -c pc.xrc -o wx-resources.cpp
|
-wxrc -c pc.xrc -o wx-resources.cpp
|
||||||
|
|
||||||
# PCem
|
# PCem
|
||||||
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acc2168.c acc3221.c acer386sx.c ali1429.c amstrad.c cassette.c cbm_io.c cdrom-image.cc cdrom-null.c \
|
pcem_SOURCES = 386.c 386_common.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \
|
||||||
cmd640.c codegen.c codegen_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_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_helpers.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \
|
||||||
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 \
|
codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \
|
||||||
hdd.c hdd_esdi.c hdd_file.c headland.c i430hx.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
|
cpu_tables.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
|
||||||
|
hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c ide_sff8038i.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
|
||||||
joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
|
joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
|
||||||
laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \
|
laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c mvp3.c neat.c nmi.c nvr.c olivetti_m24.c \
|
||||||
opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \
|
opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \
|
||||||
serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c sound_emu8k.c sound_gus.c \
|
serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c sound_emu8k.c sound_gus.c \
|
||||||
sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \
|
sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \
|
||||||
sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c \
|
sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c sst39sf010.c tandy_eeprom.c tandy_rom.c \
|
||||||
t1000.c t3100e.c \
|
t1000.c t3100e.c \
|
||||||
timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \
|
timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \
|
||||||
vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c \
|
vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c \
|
||||||
vid_ht216.c vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c \
|
vid_ht216.c vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c \
|
||||||
vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c vid_sigma.c \
|
vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c vid_sigma.c \
|
||||||
vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \
|
vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \
|
||||||
vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c \
|
vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c vt82c586b.c \
|
||||||
x86seg.c x87.c xi8088.c xtide.c zenith.c sound_dbopl.cc sound_resid.cc
|
w83877tf.c x86seg.c x87.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc \
|
||||||
|
codegen_ops_mmx_arith.c codegen_ops_mmx_cmp.c codegen_ops_mmx_loadstore.c codegen_ops_mmx_logic.c codegen_ops_mmx_pack.c codegen_ops_mmx_shift.c
|
||||||
|
|
||||||
# DOSBox
|
# DOSBox
|
||||||
pcem_SOURCES += dosbox/cdrom_image.cpp dosbox/dbopl.cpp dosbox/nukedopl.cpp dosbox/vid_cga_comp.c
|
pcem_SOURCES += dosbox/cdrom_image.cpp dosbox/dbopl.cpp dosbox/nukedopl.cpp dosbox/vid_cga_comp.c
|
||||||
|
|
@ -70,12 +72,20 @@ pcem_SOURCES += wx-sdl2-midi.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CPU_I386
|
if CPU_I386
|
||||||
pcem_SOURCES += codegen_x86.c
|
pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_ops.c codegen_backend_x86_ops_fpu.c codegen_backend_x86_ops_sse.c codegen_backend_x86_uops.c
|
||||||
pcem_CFLAGS += -msse2
|
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_ops.c codegen_backend_x86-64_ops_sse.c codegen_backend_x86-64_uops.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if CPU_ARM
|
||||||
|
pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_ops.c codegen_backend_arm_uops.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if CPU_ARM64
|
||||||
|
pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_imm.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_NETWORKING
|
if USE_NETWORKING
|
||||||
|
|
@ -114,10 +124,18 @@ pcem_LDADD += wx.res
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !HAS_OFF64T
|
if !HAS_OFF64T
|
||||||
pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell
|
#pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if RELEASE_BUILD
|
if RELEASE_BUILD
|
||||||
pcem_CFLAGS += -DRELEASE_BUILD
|
pcem_CFLAGS += -DRELEASE_BUILD
|
||||||
pcem_CXXFLAGS += -DRELEASE_BUILD
|
pcem_CXXFLAGS += -DRELEASE_BUILD
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
pcem_CFLAGS += -mtune=cortex-a53
|
||||||
|
pcem_CXXFLAGS += -mtune=cortex-a53
|
||||||
|
#pcem_LDFLAGS = -flto -O3 -mtune=cortex-a15
|
||||||
|
|
||||||
|
# pcem_CFLAGS += -fprofile-use
|
||||||
|
# pcem_CXXFLAGS += -fprofile-use
|
||||||
|
# pcem_LDFLAGS = -fprofile-use
|
||||||
|
|
|
||||||
1620
src/Makefile.in
1620
src/Makefile.in
File diff suppressed because it is too large
Load diff
|
|
@ -6,25 +6,43 @@ WXVERSION = 31
|
||||||
WXINCLUDE = e:/MinGWget/include/wx/
|
WXINCLUDE = e:/MinGWget/include/wx/
|
||||||
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing
|
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing
|
||||||
CXXFLAGS = $(CFLAGS)
|
CXXFLAGS = $(CFLAGS)
|
||||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2168.o acc3221.o acer386sx.o ali1429.o amstrad.o cassette.o cbm_io.o cdrom-ioctl.o cdrom-image.o \
|
OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o \
|
||||||
cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o \
|
cbm_io.o cdrom-ioctl.o cdrom-image.o cmd640.o codegen.o codegen_accumulate.o codegen_allocator.o \
|
||||||
device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o \
|
codegen_backend.o codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \
|
||||||
i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o codegen_ir.o codegen_ops.o \
|
||||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o \
|
codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \
|
||||||
mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o \
|
codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \
|
||||||
scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \
|
codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \
|
||||||
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
|
codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \
|
||||||
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
|
codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \
|
||||||
sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
|
codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \
|
||||||
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o \
|
codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o device.o \
|
||||||
vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
|
dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o \
|
||||||
|
fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o \
|
||||||
|
ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \
|
||||||
|
joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||||
|
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \
|
||||||
|
mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \
|
||||||
|
mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \
|
||||||
|
piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o \
|
||||||
|
scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
|
||||||
|
sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \
|
||||||
|
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
|
||||||
|
sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
|
||||||
|
sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \
|
||||||
|
vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
|
||||||
|
vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \
|
||||||
|
vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
|
||||||
vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
|
vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
|
||||||
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \
|
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \
|
||||||
vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
|
vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
|
||||||
vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o \
|
vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o \
|
||||||
wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o \
|
vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o wx-main.o \
|
||||||
wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
|
wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \
|
||||||
wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o zenith.o wx.res
|
wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \
|
||||||
|
wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
|
||||||
|
wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o \
|
||||||
|
wx-joystickconfig.o wx-createdisc.o wx.res
|
||||||
DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
|
DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
|
||||||
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
|
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,6 @@ void ali1429_write(uint16_t port, uint8_t val, void *priv)
|
||||||
ali1429_recalc();
|
ali1429_recalc();
|
||||||
break;
|
break;
|
||||||
case 0x14:
|
case 0x14:
|
||||||
shadowbios = val & 1;
|
|
||||||
shadowbios_write = val & 2;
|
|
||||||
ali1429_recalc();
|
ali1429_recalc();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ibm.h"
|
#include "ibm.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "x86.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "pzx.h"
|
#include "pzx.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ static ATAPI ioctl_atapi;
|
||||||
static uint32_t last_block = 0;
|
static uint32_t last_block = 0;
|
||||||
static uint32_t cdrom_capacity = 0;
|
static uint32_t cdrom_capacity = 0;
|
||||||
static int ioctl_inited = 0;
|
static int ioctl_inited = 0;
|
||||||
static char ioctl_path[8];
|
|
||||||
static int tocvalid = 0;
|
static int tocvalid = 0;
|
||||||
static struct cdrom_tocentry toc[256];
|
static struct cdrom_tocentry toc[256];
|
||||||
static int toc_tracks;
|
static int toc_tracks;
|
||||||
|
|
@ -209,7 +208,7 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc)
|
||||||
first_track = toc_hdr.cdth_trk0;
|
first_track = toc_hdr.cdth_trk0;
|
||||||
last_track = toc_hdr.cdth_trk1;
|
last_track = toc_hdr.cdth_trk1;
|
||||||
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
|
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
|
||||||
memset(btoc, 0, sizeof(btoc));
|
memset(btoc, 0, sizeof(struct cdrom_tocentry));
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for (track = 0; track < 256; track++)
|
for (track = 0; track < 256; track++)
|
||||||
|
|
@ -233,8 +232,6 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc)
|
||||||
|
|
||||||
static int ioctl_ready(void)
|
static int ioctl_ready(void)
|
||||||
{
|
{
|
||||||
long size;
|
|
||||||
int temp;
|
|
||||||
struct cdrom_tochdr toc_hdr;
|
struct cdrom_tochdr toc_hdr;
|
||||||
struct cdrom_tocentry toc_entry;
|
struct cdrom_tocentry toc_entry;
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -266,7 +263,6 @@ static int ioctl_ready(void)
|
||||||
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ) ||
|
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ) ||
|
||||||
!tocvalid)
|
!tocvalid)
|
||||||
{
|
{
|
||||||
int track;
|
|
||||||
ioctl_cd_state = CD_STOPPED;
|
ioctl_cd_state = CD_STOPPED;
|
||||||
|
|
||||||
tocvalid = read_toc(ioctl_fd, toc);
|
tocvalid = read_toc(ioctl_fd, toc);
|
||||||
|
|
@ -306,8 +302,6 @@ static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, i
|
||||||
|
|
||||||
static int ioctl_medium_changed(void)
|
static int ioctl_medium_changed(void)
|
||||||
{
|
{
|
||||||
long size;
|
|
||||||
int temp;
|
|
||||||
struct cdrom_tochdr toc_hdr;
|
struct cdrom_tochdr toc_hdr;
|
||||||
struct cdrom_tocentry toc_entry;
|
struct cdrom_tocentry toc_entry;
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -338,15 +332,12 @@ static int ioctl_medium_changed(void)
|
||||||
|
|
||||||
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
|
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
|
||||||
{
|
{
|
||||||
struct cdrom_subchnl sub;
|
|
||||||
uint32_t cdpos = ioctl_cd_pos;
|
uint32_t cdpos = ioctl_cd_pos;
|
||||||
int track = get_track_nr(cdpos);
|
int track = get_track_nr(cdpos);
|
||||||
uint32_t track_address = toc[track].cdte_addr.msf.frame +
|
uint32_t track_address = toc[track].cdte_addr.msf.frame +
|
||||||
(toc[track].cdte_addr.msf.second * 75) +
|
(toc[track].cdte_addr.msf.second * 75) +
|
||||||
(toc[track].cdte_addr.msf.minute * 75 * 60);
|
(toc[track].cdte_addr.msf.minute * 75 * 60);
|
||||||
long size;
|
|
||||||
int pos=0;
|
int pos=0;
|
||||||
int err;
|
|
||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
//pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i\n", cdpos, track_address, track);
|
//pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i\n", cdpos, track_address, track);
|
||||||
if (ioctl_cd_state == CD_PLAYING)
|
if (ioctl_cd_state == CD_PLAYING)
|
||||||
|
|
@ -460,7 +451,6 @@ static void ioctl_readsector_raw(uint8_t *b, int sector)
|
||||||
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
|
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
|
||||||
{
|
{
|
||||||
int len=4;
|
int len=4;
|
||||||
long size;
|
|
||||||
int c,d;
|
int c,d;
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
uint32_t last_address = 0;
|
uint32_t last_address = 0;
|
||||||
|
|
@ -644,7 +634,7 @@ static uint32_t ioctl_size()
|
||||||
|
|
||||||
static int ioctl_status()
|
static int ioctl_status()
|
||||||
{
|
{
|
||||||
if (!(ioctl_ready) && (cdrom_drive <= 0)) return CD_STATUS_EMPTY;
|
if (!ioctl_ready() && (cdrom_drive <= 0)) return CD_STATUS_EMPTY;
|
||||||
|
|
||||||
switch(ioctl_cd_state)
|
switch(ioctl_cd_state)
|
||||||
{
|
{
|
||||||
|
|
@ -653,6 +643,7 @@ static int ioctl_status()
|
||||||
case CD_PAUSED:
|
case CD_PAUSED:
|
||||||
return CD_STATUS_PAUSED;
|
return CD_STATUS_PAUSED;
|
||||||
case CD_STOPPED:
|
case CD_STOPPED:
|
||||||
|
default:
|
||||||
return CD_STATUS_STOPPED;
|
return CD_STATUS_STOPPED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
752
src/codegen.c
752
src/codegen.c
|
|
@ -2,12 +2,63 @@
|
||||||
#include "x86_ops.h"
|
#include "x86_ops.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#include "386_common.h"
|
||||||
|
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
#define MAX_INSTRUCTION_COUNT 50
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
uint32_t pc;
|
||||||
|
int op_ssegs;
|
||||||
|
x86seg *op_ea_seg;
|
||||||
|
uint32_t op_32;
|
||||||
|
int first_uop;
|
||||||
|
} codegen_instructions[MAX_INSTRUCTION_COUNT];
|
||||||
|
|
||||||
|
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < block->ins; c++)
|
||||||
|
{
|
||||||
|
if (codegen_instructions[c].pc == pc)
|
||||||
|
{
|
||||||
|
*first_instruction = c;
|
||||||
|
return codegen_instructions[c].first_uop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*first_instruction = block->ins;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_loop_start(ir_data_t *ir, int first_instruction)
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32);
|
||||||
|
uop_MOV_PTR(ir, IREG_ea_seg, (void *)codegen_instructions[first_instruction].op_ea_seg);
|
||||||
|
uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int has_ea;
|
||||||
|
|
||||||
|
codeblock_t *codeblock;
|
||||||
|
uint16_t *codeblock_hash;
|
||||||
|
|
||||||
void (*codegen_timing_start)();
|
void (*codegen_timing_start)();
|
||||||
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||||
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
|
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||||
void (*codegen_timing_block_start)();
|
void (*codegen_timing_block_start)();
|
||||||
void (*codegen_timing_block_end)();
|
void (*codegen_timing_block_end)();
|
||||||
|
int (*codegen_timing_jump_cycles)();
|
||||||
|
|
||||||
void codegen_timing_set(codegen_timing_t *timing)
|
void codegen_timing_set(codegen_timing_t *timing)
|
||||||
{
|
{
|
||||||
|
|
@ -16,6 +67,705 @@ void codegen_timing_set(codegen_timing_t *timing)
|
||||||
codegen_timing_opcode = timing->opcode;
|
codegen_timing_opcode = timing->opcode;
|
||||||
codegen_timing_block_start = timing->block_start;
|
codegen_timing_block_start = timing->block_start;
|
||||||
codegen_timing_block_end = timing->block_end;
|
codegen_timing_block_end = timing->block_end;
|
||||||
|
codegen_timing_jump_cycles = timing->jump_cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
int codegen_in_recompile;
|
int codegen_in_recompile;
|
||||||
|
|
||||||
|
static int last_op_ssegs;
|
||||||
|
static x86seg *last_op_ea_seg;
|
||||||
|
static uint32_t last_op_32;
|
||||||
|
|
||||||
|
void codegen_generate_reset()
|
||||||
|
{
|
||||||
|
last_op_ssegs = -1;
|
||||||
|
last_op_ea_seg = NULL;
|
||||||
|
last_op_32 = -1;
|
||||||
|
has_ea = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg)
|
||||||
|
{
|
||||||
|
/*Segments always valid in real/V86 mode*/
|
||||||
|
if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG))
|
||||||
|
return;
|
||||||
|
/*CS and SS must always be valid*/
|
||||||
|
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
|
||||||
|
return;
|
||||||
|
if (seg->checked)
|
||||||
|
return;
|
||||||
|
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout);
|
||||||
|
|
||||||
|
seg->checked = 1;
|
||||||
|
}
|
||||||
|
void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg)
|
||||||
|
{
|
||||||
|
/*Segments always valid in real/V86 mode*/
|
||||||
|
if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG))
|
||||||
|
return;
|
||||||
|
/*CS and SS must always be valid*/
|
||||||
|
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
|
||||||
|
return;
|
||||||
|
if (seg->checked)
|
||||||
|
return;
|
||||||
|
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout);
|
||||||
|
|
||||||
|
seg->checked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc)
|
||||||
|
{
|
||||||
|
uint32_t old_pc = (*op_pc) + 1;
|
||||||
|
// pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat);
|
||||||
|
if (!cpu_mod && cpu_rm == 6)
|
||||||
|
{
|
||||||
|
uint16_t addr = (fetchdat >> 8) & 0xffff;
|
||||||
|
uop_MOV_IMM(ir, IREG_eaaddr, addr);
|
||||||
|
(*op_pc) += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int base_reg, index_reg, offset;
|
||||||
|
|
||||||
|
switch (cpu_rm & 7)
|
||||||
|
{
|
||||||
|
case 0: case 1: case 7:
|
||||||
|
base_reg = IREG_EBX;
|
||||||
|
break;
|
||||||
|
case 2: case 3: case 6:
|
||||||
|
base_reg = IREG_EBP;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
base_reg = IREG_ESI;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
base_reg = IREG_EDI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uop_MOV(ir, IREG_eaaddr, base_reg);
|
||||||
|
|
||||||
|
if (!(cpu_rm & 4))
|
||||||
|
{
|
||||||
|
if (!(cpu_rm & 1))
|
||||||
|
index_reg = IREG_ESI;
|
||||||
|
else
|
||||||
|
index_reg = IREG_EDI;
|
||||||
|
|
||||||
|
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cpu_mod)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
offset = (int)(int8_t)((fetchdat >> 8) & 0xff);
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset);
|
||||||
|
(*op_pc)++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
offset = (fetchdat >> 8) & 0xffff;
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset);
|
||||||
|
(*op_pc) += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff);
|
||||||
|
|
||||||
|
if (mod1seg[cpu_rm] == &ss && !op_ssegs)
|
||||||
|
{
|
||||||
|
op_ea_seg = &cpu_state.seg_ss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-old_pc);
|
||||||
|
return op_ea_seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset)
|
||||||
|
{
|
||||||
|
codeblock_t *block = ir->block;
|
||||||
|
uint32_t old_pc = (*op_pc) + 1;
|
||||||
|
uint32_t new_eaaddr;
|
||||||
|
int extra_bytes = 0;
|
||||||
|
|
||||||
|
if (cpu_rm == 4)
|
||||||
|
{
|
||||||
|
uint8_t sib = fetchdat >> 8;
|
||||||
|
(*op_pc)++;
|
||||||
|
|
||||||
|
switch (cpu_mod)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if ((sib & 7) == 5)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
|
||||||
|
extra_bytes = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||||
|
extra_bytes = 5;
|
||||||
|
}
|
||||||
|
(*op_pc) += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV(ir, IREG_eaaddr, sib & 7);
|
||||||
|
extra_bytes = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff);
|
||||||
|
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||||
|
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
|
||||||
|
(*op_pc)++;
|
||||||
|
extra_bytes = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
|
||||||
|
extra_bytes = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||||
|
extra_bytes = 5;
|
||||||
|
}
|
||||||
|
(*op_pc) += 4;
|
||||||
|
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset);
|
||||||
|
// addbyte(0x05);
|
||||||
|
// addlong(stack_offset);
|
||||||
|
}
|
||||||
|
if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs)
|
||||||
|
op_ea_seg = &cpu_state.seg_ss;
|
||||||
|
if (((sib >> 3) & 7) != 4)
|
||||||
|
{
|
||||||
|
switch (sib >> 6)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!cpu_mod && cpu_rm == 5)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
|
||||||
|
extra_bytes = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*op_pc) += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV(ir, IREG_eaaddr, cpu_rm);
|
||||||
|
if (cpu_mod)
|
||||||
|
{
|
||||||
|
if (cpu_rm == 5 && !op_ssegs)
|
||||||
|
op_ea_seg = &cpu_state.seg_ss;
|
||||||
|
if (cpu_mod == 1)
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8));
|
||||||
|
(*op_pc)++;
|
||||||
|
extra_bytes = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1);
|
||||||
|
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr);
|
||||||
|
extra_bytes = 4;
|
||||||
|
}
|
||||||
|
(*op_pc) += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extra_bytes)
|
||||||
|
codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes);
|
||||||
|
|
||||||
|
return op_ea_seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset)
|
||||||
|
{
|
||||||
|
cpu_mod = (fetchdat >> 6) & 3;
|
||||||
|
cpu_reg = (fetchdat >> 3) & 7;
|
||||||
|
cpu_rm = fetchdat & 7;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
return NULL;
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset);
|
||||||
|
|
||||||
|
return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t opcode_modrm[256] =
|
||||||
|
{
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
|
||||||
|
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/
|
||||||
|
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/
|
||||||
|
|
||||||
|
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/
|
||||||
|
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/
|
||||||
|
};
|
||||||
|
static uint8_t opcode_0f_modrm[256] =
|
||||||
|
{
|
||||||
|
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/
|
||||||
|
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/
|
||||||
|
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/
|
||||||
|
0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /*a0*/
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/
|
||||||
|
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
|
||||||
|
0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/
|
||||||
|
0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/
|
||||||
|
0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/
|
||||||
|
};
|
||||||
|
|
||||||
|
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc)
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
ir_data_t *ir = codegen_get_ir_data();
|
||||||
|
uint32_t op_pc = new_pc;
|
||||||
|
OpFn *op_table = x86_dynarec_opcodes;
|
||||||
|
RecompOpFn *recomp_op_table = recomp_opcodes;
|
||||||
|
int opcode_shift = 0;
|
||||||
|
int opcode_mask = 0x3ff;
|
||||||
|
uint32_t recomp_opcode_mask = 0x1ff;
|
||||||
|
uint32_t op_32 = use32;
|
||||||
|
int over = 0;
|
||||||
|
int test_modrm = 1;
|
||||||
|
int pc_off = 0;
|
||||||
|
uint32_t next_pc = 0;
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
uint8_t last_prefix = 0;
|
||||||
|
#endif
|
||||||
|
op_ea_seg = &cpu_state.seg_ds;
|
||||||
|
op_ssegs = 0;
|
||||||
|
|
||||||
|
codegen_timing_start();
|
||||||
|
|
||||||
|
while (!over)
|
||||||
|
{
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case 0x0f:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0x0f;
|
||||||
|
#endif
|
||||||
|
op_table = x86_dynarec_opcodes_0f;
|
||||||
|
recomp_op_table = recomp_opcodes_0f;
|
||||||
|
over = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x26: /*ES:*/
|
||||||
|
op_ea_seg = &cpu_state.seg_es;
|
||||||
|
op_ssegs = 1;
|
||||||
|
break;
|
||||||
|
case 0x2e: /*CS:*/
|
||||||
|
op_ea_seg = &cpu_state.seg_cs;
|
||||||
|
op_ssegs = 1;
|
||||||
|
break;
|
||||||
|
case 0x36: /*SS:*/
|
||||||
|
op_ea_seg = &cpu_state.seg_ss;
|
||||||
|
op_ssegs = 1;
|
||||||
|
break;
|
||||||
|
case 0x3e: /*DS:*/
|
||||||
|
op_ea_seg = &cpu_state.seg_ds;
|
||||||
|
op_ssegs = 1;
|
||||||
|
break;
|
||||||
|
case 0x64: /*FS:*/
|
||||||
|
op_ea_seg = &cpu_state.seg_fs;
|
||||||
|
op_ssegs = 1;
|
||||||
|
break;
|
||||||
|
case 0x65: /*GS:*/
|
||||||
|
op_ea_seg = &cpu_state.seg_gs;
|
||||||
|
op_ssegs = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x66: /*Data size select*/
|
||||||
|
op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200);
|
||||||
|
break;
|
||||||
|
case 0x67: /*Address size select*/
|
||||||
|
op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xd8:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xd8;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_d8;
|
||||||
|
opcode_shift = 3;
|
||||||
|
opcode_mask = 0x1f;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xd9:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xd9;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_d9;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xda:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xda;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_da;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xdb:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xdb;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_db;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xdc:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xdc;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_dc;
|
||||||
|
opcode_shift = 3;
|
||||||
|
opcode_mask = 0x1f;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xdd:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xdd;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_dd;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xde:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xde;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_de;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
case 0xdf:
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xdf;
|
||||||
|
#endif
|
||||||
|
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
|
||||||
|
recomp_op_table = recomp_opcodes_df;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
over = 1;
|
||||||
|
pc_off = -1;
|
||||||
|
test_modrm = 0;
|
||||||
|
block->flags |= CODEBLOCK_HAS_FPU;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xf0: /*LOCK*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xf2: /*REPNE*/
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xf2;
|
||||||
|
#endif
|
||||||
|
op_table = x86_dynarec_opcodes_REPNE;
|
||||||
|
recomp_op_table = NULL;//recomp_opcodes_REPNE;
|
||||||
|
break;
|
||||||
|
case 0xf3: /*REPE*/
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
last_prefix = 0xf3;
|
||||||
|
#endif
|
||||||
|
op_table = x86_dynarec_opcodes_REPE;
|
||||||
|
recomp_op_table = NULL;//recomp_opcodes_REPE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto generate_call;
|
||||||
|
}
|
||||||
|
fetchdat = fastreadl(cs + op_pc);
|
||||||
|
codegen_timing_prefix(opcode, fetchdat);
|
||||||
|
if (cpu_state.abrt)
|
||||||
|
return;
|
||||||
|
opcode = fetchdat & 0xff;
|
||||||
|
if (!pc_off)
|
||||||
|
fetchdat >>= 8;
|
||||||
|
|
||||||
|
op_pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_call:
|
||||||
|
codegen_instructions[block->ins].pc = cpu_state.oldpc;
|
||||||
|
codegen_instructions[block->ins].op_ssegs = last_op_ssegs;
|
||||||
|
codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg;
|
||||||
|
codegen_instructions[block->ins].op_32 = last_op_32;
|
||||||
|
codegen_instructions[block->ins].first_uop = ir->wr_pos;
|
||||||
|
|
||||||
|
codegen_timing_opcode(opcode, fetchdat, op_32, op_pc);
|
||||||
|
|
||||||
|
codegen_accumulate(ACCREG_ins, 1);
|
||||||
|
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
|
||||||
|
codegen_block_cycles = 0;
|
||||||
|
|
||||||
|
if ((op_table == x86_dynarec_opcodes &&
|
||||||
|
((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 ||
|
||||||
|
(opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 ||
|
||||||
|
(opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) ||
|
||||||
|
(op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))
|
||||||
|
{
|
||||||
|
/*On some CPUs (eg K6), a jump/branch instruction may be able to pair with
|
||||||
|
subsequent instructions, so no cycles may have been deducted for it yet.
|
||||||
|
To prevent having zero cycle blocks (eg with a jump instruction pointing
|
||||||
|
to itself), apply the cycles that would be taken if this jump is taken,
|
||||||
|
then reverse it for subsequent instructions if the jump is not taken*/
|
||||||
|
int jump_cycles = codegen_timing_jump_cycles();
|
||||||
|
|
||||||
|
if (jump_cycles)
|
||||||
|
codegen_accumulate(ACCREG_cycles, -jump_cycles);
|
||||||
|
codegen_accumulate_flush(ir);
|
||||||
|
if (jump_cycles)
|
||||||
|
codegen_accumulate(ACCREG_cycles, jump_cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f)
|
||||||
|
{
|
||||||
|
/*3DNow opcodes are stored after ModR/M, SIB and any offset*/
|
||||||
|
uint8_t modrm = fetchdat & 0xff;
|
||||||
|
uint8_t sib = (fetchdat >> 8) & 0xff;
|
||||||
|
uint32_t opcode_pc = op_pc + 1;
|
||||||
|
uint8_t opcode_3dnow;
|
||||||
|
|
||||||
|
if ((modrm & 0xc0) != 0xc0)
|
||||||
|
{
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
{
|
||||||
|
if ((modrm & 7) == 4)
|
||||||
|
{
|
||||||
|
/* Has SIB*/
|
||||||
|
opcode_pc++;
|
||||||
|
if ((modrm & 0xc0) == 0x40)
|
||||||
|
opcode_pc++;
|
||||||
|
else if ((modrm & 0xc0) == 0x80)
|
||||||
|
opcode_pc += 4;
|
||||||
|
else if ((sib & 0x07) == 0x05)
|
||||||
|
opcode_pc += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((modrm & 0xc0) == 0x40)
|
||||||
|
opcode_pc++;
|
||||||
|
else if ((modrm & 0xc0) == 0x80)
|
||||||
|
opcode_pc += 4;
|
||||||
|
else if ((modrm & 0xc7) == 0x05)
|
||||||
|
opcode_pc += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((modrm & 0xc0) == 0x40)
|
||||||
|
opcode_pc++;
|
||||||
|
else if ((modrm & 0xc0) == 0x80)
|
||||||
|
opcode_pc += 2;
|
||||||
|
else if ((modrm & 0xc7) == 0x06)
|
||||||
|
opcode_pc += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opcode_3dnow = fastreadb(cs + opcode_pc);
|
||||||
|
// pclog("recomp_opcodes_3DNOW[%02x]=%p\n", opcode, recomp_opcodes_3DNOW[opcode]);
|
||||||
|
if (recomp_opcodes_3DNOW[opcode_3dnow])
|
||||||
|
{
|
||||||
|
next_pc = opcode_pc + 1;
|
||||||
|
|
||||||
|
op_table = x86_dynarec_opcodes_3DNOW;
|
||||||
|
recomp_op_table = recomp_opcodes_3DNOW;
|
||||||
|
opcode = opcode_3dnow;
|
||||||
|
recomp_opcode_mask = 0xff;
|
||||||
|
opcode_mask = 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off);
|
||||||
|
// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
|
||||||
|
if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask])
|
||||||
|
{
|
||||||
|
uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc);
|
||||||
|
if (new_pc)
|
||||||
|
{
|
||||||
|
if (new_pc != -1)
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, new_pc);
|
||||||
|
|
||||||
|
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||||
|
|
||||||
|
block->ins++;
|
||||||
|
|
||||||
|
if (block->ins >= MAX_INSTRUCTION_COUNT)
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32])
|
||||||
|
{
|
||||||
|
op_table = x86_dynarec_opcodes;
|
||||||
|
recomp_op_table = recomp_opcodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||||
|
|
||||||
|
if (!test_modrm ||
|
||||||
|
(op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) ||
|
||||||
|
(op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) ||
|
||||||
|
(op_table == x86_dynarec_opcodes_3DNOW))
|
||||||
|
{
|
||||||
|
int stack_offset = 0;
|
||||||
|
|
||||||
|
if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/
|
||||||
|
stack_offset = (op_32 & 0x100) ? 4 : 2;
|
||||||
|
|
||||||
|
cpu_mod = (fetchdat >> 6) & 3;
|
||||||
|
cpu_reg = (fetchdat >> 3) & 7;
|
||||||
|
cpu_rm = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16));
|
||||||
|
|
||||||
|
op_pc += pc_off;
|
||||||
|
if (cpu_mod != 3 && !(op_32 & 0x200))
|
||||||
|
{
|
||||||
|
op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc);
|
||||||
|
// has_ea = 1;
|
||||||
|
}
|
||||||
|
if (cpu_mod != 3 && (op_32 & 0x200))
|
||||||
|
{
|
||||||
|
op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset);
|
||||||
|
// has_ea = 1;
|
||||||
|
}
|
||||||
|
// op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset);
|
||||||
|
op_pc -= pc_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
uop_LOG_INSTR(ir, opcode | (last_prefix << 8));
|
||||||
|
#endif
|
||||||
|
codegen_accumulate_flush(ir);
|
||||||
|
if (op_table == x86_dynarec_opcodes_3DNOW)
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, next_pc);
|
||||||
|
else
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, old_pc);
|
||||||
|
if (op_32 != last_op_32)
|
||||||
|
uop_MOV_IMM(ir, IREG_op32, op_32);
|
||||||
|
if (op_ea_seg != last_op_ea_seg)
|
||||||
|
uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg);
|
||||||
|
if (op_ssegs != last_op_ssegs)
|
||||||
|
uop_MOV_IMM(ir, IREG_ssegs, op_ssegs);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat);
|
||||||
|
uop_CALL_INSTRUCTION_FUNC(ir, op);
|
||||||
|
codegen_mark_code_present(block, cs+cpu_state.pc, 8);
|
||||||
|
|
||||||
|
last_op_32 = op_32;
|
||||||
|
last_op_ea_seg = op_ea_seg;
|
||||||
|
last_op_ssegs = op_ssegs;
|
||||||
|
//codegen_block_ins++;
|
||||||
|
|
||||||
|
block->ins++;
|
||||||
|
|
||||||
|
if (block->ins >= MAX_INSTRUCTION_COUNT)
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
|
||||||
|
codegen_endpc = (cs + cpu_state.pc) + 8;
|
||||||
|
|
||||||
|
// if (has_ea)
|
||||||
|
// fatal("Has EA\n");
|
||||||
|
}
|
||||||
|
|
|
||||||
302
src/codegen.h
302
src/codegen.h
|
|
@ -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
|
||||||
|
|
@ -39,60 +31,88 @@
|
||||||
|
|
||||||
typedef struct codeblock_t
|
typedef struct codeblock_t
|
||||||
{
|
{
|
||||||
|
uint32_t pc;
|
||||||
|
uint32_t _cs;
|
||||||
|
uint32_t phys, phys_2;
|
||||||
|
uint16_t status;
|
||||||
|
uint16_t flags;
|
||||||
|
uint8_t ins;
|
||||||
|
uint8_t TOP;
|
||||||
|
|
||||||
|
/*Pointers for codeblock tree, used to search for blocks when hash lookup
|
||||||
|
fails.*/
|
||||||
|
uint16_t parent, left, right;
|
||||||
|
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
uint64_t page_mask, page_mask2;
|
uint64_t page_mask, page_mask2;
|
||||||
uint64_t *dirty_mask, *dirty_mask2;
|
uint64_t *dirty_mask, *dirty_mask2;
|
||||||
uint64_t cmp;
|
|
||||||
|
|
||||||
/*Previous and next pointers, for the codeblock list associated with
|
/*Previous and next pointers, for the codeblock list associated with
|
||||||
each physical page. Two sets of pointers, as a codeblock can be
|
each physical page. Two sets of pointers, as a codeblock can be
|
||||||
present in two pages.*/
|
present in two pages.*/
|
||||||
struct codeblock_t *prev, *next;
|
uint16_t prev, next;
|
||||||
struct codeblock_t *prev_2, *next_2;
|
uint16_t prev_2, next_2;
|
||||||
|
|
||||||
/*Pointers for codeblock tree, used to search for blocks when hash lookup
|
/*First mem_block_t used by this block. Any subsequent mem_block_ts
|
||||||
fails.*/
|
will be in the list starting at head_mem_block->next.*/
|
||||||
struct codeblock_t *parent, *left, *right;
|
struct mem_block_t *head_mem_block;
|
||||||
|
|
||||||
int pnt;
|
|
||||||
int ins;
|
|
||||||
|
|
||||||
int was_recompiled;
|
|
||||||
int TOP;
|
|
||||||
|
|
||||||
uint32_t pc;
|
|
||||||
uint32_t _cs;
|
|
||||||
uint32_t endpc;
|
|
||||||
uint32_t phys, phys_2;
|
|
||||||
uint32_t status;
|
|
||||||
uint32_t flags;
|
|
||||||
|
|
||||||
uint8_t data[2048];
|
|
||||||
} codeblock_t;
|
} codeblock_t;
|
||||||
|
|
||||||
|
extern codeblock_t *codeblock;
|
||||||
|
|
||||||
|
extern uint16_t *codeblock_hash;
|
||||||
|
|
||||||
|
extern uint8_t *block_write_data;
|
||||||
|
|
||||||
/*Code block uses FPU*/
|
/*Code block uses FPU*/
|
||||||
#define CODEBLOCK_HAS_FPU 1
|
#define CODEBLOCK_HAS_FPU 1
|
||||||
/*Code block is always entered with the same FPU top-of-stack*/
|
/*Code block is always entered with the same FPU top-of-stack*/
|
||||||
#define CODEBLOCK_STATIC_TOP 2
|
#define CODEBLOCK_STATIC_TOP 2
|
||||||
|
/*Code block has been compiled*/
|
||||||
|
#define CODEBLOCK_WAS_RECOMPILED 4
|
||||||
|
/*Code block is in free list and is not valid*/
|
||||||
|
#define CODEBLOCK_IN_FREE_LIST 8
|
||||||
|
/*Code block spans two pages, page_mask2 and dirty_mask2 are valid*/
|
||||||
|
#define CODEBLOCK_HAS_PAGE2 0x10
|
||||||
|
/*Code block is using a byte mask for code present and dirty*/
|
||||||
|
#define CODEBLOCK_BYTE_MASK 0x20
|
||||||
|
/*Code block is in dirty list*/
|
||||||
|
#define CODEBLOCK_IN_DIRTY_LIST 0x40
|
||||||
|
/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/
|
||||||
|
#define CODEBLOCK_NO_IMMEDIATES 0x80
|
||||||
|
|
||||||
#define BLOCK_PC_INVALID 0xffffffff
|
#define BLOCK_PC_INVALID 0xffffffff
|
||||||
|
|
||||||
|
#define BLOCK_INVALID 0
|
||||||
|
|
||||||
|
static inline int get_block_nr(codeblock_t *block)
|
||||||
|
{
|
||||||
|
return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t);
|
||||||
|
}
|
||||||
|
|
||||||
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
||||||
{
|
{
|
||||||
codeblock_t *block = pages[phys >> 12].head;
|
codeblock_t *block;
|
||||||
uint64_t a = _cs | ((uint64_t)phys << 32);
|
uint64_t a = _cs | ((uint64_t)phys << 32);
|
||||||
|
|
||||||
|
if (!pages[phys >> 12].head)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
block = &codeblock[pages[phys >> 12].head];
|
||||||
while (block)
|
while (block)
|
||||||
{
|
{
|
||||||
if (a == block->cmp)
|
uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32);
|
||||||
|
if (a == block_cmp)
|
||||||
{
|
{
|
||||||
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
|
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
|
||||||
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (a < block->cmp)
|
if (a < block_cmp)
|
||||||
block = block->left;
|
block = block->left ? &codeblock[block->left] : NULL;
|
||||||
else
|
else
|
||||||
block = block->right;
|
block = block->right ? &codeblock[block->right] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
|
|
@ -100,75 +120,87 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
||||||
|
|
||||||
static inline void codeblock_tree_add(codeblock_t *new_block)
|
static inline void codeblock_tree_add(codeblock_t *new_block)
|
||||||
{
|
{
|
||||||
codeblock_t *block = pages[new_block->phys >> 12].head;
|
codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
|
||||||
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
|
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
|
||||||
new_block->cmp = a;
|
|
||||||
|
|
||||||
if (!block)
|
if (!pages[new_block->phys >> 12].head)
|
||||||
{
|
{
|
||||||
pages[new_block->phys >> 12].head = new_block;
|
pages[new_block->phys >> 12].head = get_block_nr(new_block);
|
||||||
new_block->parent = new_block->left = new_block->right = NULL;
|
new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
codeblock_t *old_block = NULL;
|
codeblock_t *old_block = NULL;
|
||||||
|
uint64_t old_block_cmp = 0;
|
||||||
|
|
||||||
while (block)
|
while (block)
|
||||||
{
|
{
|
||||||
old_block = block;
|
old_block = block;
|
||||||
if (a < old_block->cmp)
|
old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32);
|
||||||
block = block->left;
|
|
||||||
|
if (a < old_block_cmp)
|
||||||
|
block = block->left ? &codeblock[block->left] : NULL;
|
||||||
else
|
else
|
||||||
block = block->right;
|
block = block->right ? &codeblock[block->right] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a < old_block->cmp)
|
if (a < old_block_cmp)
|
||||||
old_block->left = new_block;
|
old_block->left = get_block_nr(new_block);
|
||||||
else
|
else
|
||||||
old_block->right = new_block;
|
old_block->right = get_block_nr(new_block);
|
||||||
|
|
||||||
new_block->parent = old_block;
|
new_block->parent = get_block_nr(old_block);
|
||||||
new_block->left = new_block->right = NULL;
|
new_block->left = new_block->right = BLOCK_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void codeblock_tree_delete(codeblock_t *block)
|
static inline void codeblock_tree_delete(codeblock_t *block)
|
||||||
{
|
{
|
||||||
codeblock_t *parent = block->parent;
|
uint16_t parent_nr = block->parent;
|
||||||
|
codeblock_t *parent;
|
||||||
|
|
||||||
|
if (block->parent)
|
||||||
|
parent = &codeblock[block->parent];
|
||||||
|
else
|
||||||
|
parent = NULL;
|
||||||
|
|
||||||
if (!block->left && !block->right)
|
if (!block->left && !block->right)
|
||||||
{
|
{
|
||||||
/*Easy case - remove from parent*/
|
/*Easy case - remove from parent*/
|
||||||
if (!parent)
|
if (!parent)
|
||||||
pages[block->phys >> 12].head = NULL;
|
pages[block->phys >> 12].head = BLOCK_INVALID;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parent->left == block)
|
uint16_t block_nr = get_block_nr(block);
|
||||||
parent->left = NULL;
|
|
||||||
if (parent->right == block)
|
if (parent->left == block_nr)
|
||||||
parent->right = NULL;
|
parent->left = BLOCK_INVALID;
|
||||||
|
if (parent->right == block_nr)
|
||||||
|
parent->right = BLOCK_INVALID;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!block->left)
|
else if (!block->left)
|
||||||
{
|
{
|
||||||
/*Only right node*/
|
/*Only right node*/
|
||||||
if (!parent)
|
if (!parent_nr)
|
||||||
{
|
{
|
||||||
pages[block->phys >> 12].head = block->right;
|
pages[block->phys >> 12].head = block->right;
|
||||||
pages[block->phys >> 12].head->parent = NULL;
|
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parent->left == block)
|
uint16_t block_nr = get_block_nr(block);
|
||||||
|
|
||||||
|
if (parent->left == block_nr)
|
||||||
{
|
{
|
||||||
parent->left = block->right;
|
parent->left = block->right;
|
||||||
parent->left->parent = parent;
|
codeblock[parent->left].parent = parent_nr;
|
||||||
}
|
}
|
||||||
if (parent->right == block)
|
if (parent->right == block_nr)
|
||||||
{
|
{
|
||||||
parent->right = block->right;
|
parent->right = block->right;
|
||||||
parent->right->parent = parent;
|
codeblock[parent->right].parent = parent_nr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -176,22 +208,24 @@ static inline void codeblock_tree_delete(codeblock_t *block)
|
||||||
else if (!block->right)
|
else if (!block->right)
|
||||||
{
|
{
|
||||||
/*Only left node*/
|
/*Only left node*/
|
||||||
if (!parent)
|
if (!parent_nr)
|
||||||
{
|
{
|
||||||
pages[block->phys >> 12].head = block->left;
|
pages[block->phys >> 12].head = block->left;
|
||||||
pages[block->phys >> 12].head->parent = NULL;
|
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parent->left == block)
|
uint16_t block_nr = get_block_nr(block);
|
||||||
|
|
||||||
|
if (parent->left == block_nr)
|
||||||
{
|
{
|
||||||
parent->left = block->left;
|
parent->left = block->left;
|
||||||
parent->left->parent = parent;
|
codeblock[parent->left].parent = parent_nr;
|
||||||
}
|
}
|
||||||
if (parent->right == block)
|
if (parent->right == block_nr)
|
||||||
{
|
{
|
||||||
parent->right = block->left;
|
parent->right = block->left;
|
||||||
parent->right->parent = parent;
|
codeblock[parent->right].parent = parent_nr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -199,75 +233,109 @@ static inline void codeblock_tree_delete(codeblock_t *block)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*Difficult case - node has two children. Walk right child to find lowest node*/
|
/*Difficult case - node has two children. Walk right child to find lowest node*/
|
||||||
codeblock_t *lowest = block->right, *highest;
|
codeblock_t *lowest = &codeblock[block->right], *highest;
|
||||||
codeblock_t *old_parent;
|
codeblock_t *old_parent;
|
||||||
|
uint16_t lowest_nr;
|
||||||
|
|
||||||
while (lowest->left)
|
while (lowest->left)
|
||||||
lowest = lowest->left;
|
lowest = &codeblock[lowest->left];
|
||||||
|
lowest_nr = get_block_nr(lowest);
|
||||||
|
|
||||||
old_parent = lowest->parent;
|
old_parent = &codeblock[lowest->parent];
|
||||||
|
|
||||||
/*Replace deleted node with lowest node*/
|
/*Replace deleted node with lowest node*/
|
||||||
if (!parent)
|
if (!parent_nr)
|
||||||
pages[block->phys >> 12].head = lowest;
|
pages[block->phys >> 12].head = lowest_nr;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parent->left == block)
|
uint16_t block_nr = get_block_nr(block);
|
||||||
parent->left = lowest;
|
|
||||||
if (parent->right == block)
|
if (parent->left == block_nr)
|
||||||
parent->right = lowest;
|
parent->left = lowest_nr;
|
||||||
|
if (parent->right == block_nr)
|
||||||
|
parent->right = lowest_nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
lowest->parent = parent;
|
lowest->parent = parent_nr;
|
||||||
lowest->left = block->left;
|
lowest->left = block->left;
|
||||||
if (lowest->left)
|
if (lowest->left)
|
||||||
lowest->left->parent = lowest;
|
codeblock[lowest->left].parent = lowest_nr;
|
||||||
|
|
||||||
old_parent->left = NULL;
|
old_parent->left = BLOCK_INVALID;
|
||||||
|
|
||||||
highest = lowest->right;
|
highest = &codeblock[lowest->right];
|
||||||
if (!highest)
|
if (!lowest->right)
|
||||||
{
|
{
|
||||||
if (lowest != block->right)
|
if (lowest_nr != block->right)
|
||||||
{
|
{
|
||||||
lowest->right = block->right;
|
lowest->right = block->right;
|
||||||
block->right->parent = lowest;
|
codeblock[block->right].parent = lowest_nr;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (highest->right)
|
while (highest->right)
|
||||||
highest = highest->right;
|
highest = &codeblock[highest->right];
|
||||||
|
|
||||||
if (block->right && block->right != lowest)
|
if (block->right && block->right != lowest_nr)
|
||||||
{
|
{
|
||||||
highest->right = block->right;
|
highest->right = block->right;
|
||||||
block->right->parent = highest;
|
codeblock[block->right].parent = get_block_nr(highest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PAGE_MASK_INDEX_MASK 3
|
|
||||||
#define PAGE_MASK_INDEX_SHIFT 10
|
|
||||||
#define PAGE_MASK_MASK 63
|
#define PAGE_MASK_MASK 63
|
||||||
#define PAGE_MASK_SHIFT 4
|
#define PAGE_MASK_SHIFT 6
|
||||||
|
|
||||||
extern codeblock_t *codeblock;
|
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len);
|
||||||
|
|
||||||
extern codeblock_t **codeblock_hash;
|
static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
|
||||||
|
{
|
||||||
|
if (len == 1)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
{
|
||||||
|
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
|
||||||
|
block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
|
||||||
|
else
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
|
||||||
|
block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||||
|
else
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
codegen_mark_code_present_multibyte(block, start_pc, len);
|
||||||
|
}
|
||||||
|
|
||||||
void codegen_init();
|
void codegen_init();
|
||||||
|
void codegen_close();
|
||||||
void codegen_reset();
|
void codegen_reset();
|
||||||
void codegen_block_init(uint32_t phys_addr);
|
void codegen_block_init(uint32_t phys_addr);
|
||||||
void codegen_block_remove();
|
void codegen_block_remove();
|
||||||
void codegen_block_start_recompile(codeblock_t *block);
|
void codegen_block_start_recompile(codeblock_t *block);
|
||||||
void codegen_block_end_recompile(codeblock_t *block);
|
void codegen_block_end_recompile(codeblock_t *block);
|
||||||
void codegen_block_end();
|
void codegen_block_end();
|
||||||
|
void codegen_delete_block(codeblock_t *block);
|
||||||
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
|
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
|
||||||
void codegen_generate_seg_restore();
|
void codegen_generate_seg_restore();
|
||||||
void codegen_set_op32();
|
void codegen_set_op32();
|
||||||
void codegen_flush();
|
void codegen_flush();
|
||||||
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
|
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
|
||||||
|
struct ir_data_t;
|
||||||
|
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
|
||||||
|
void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||||
|
void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||||
|
|
||||||
|
int codegen_purge_purgable_list();
|
||||||
|
/*Delete a random code block to free memory. This is obviously quite expensive, and
|
||||||
|
will only be called when the allocator is out of memory*/
|
||||||
|
void codegen_delete_random_block(int required_mem_block);
|
||||||
|
|
||||||
extern int cpu_block_end;
|
extern int cpu_block_end;
|
||||||
extern uint32_t codegen_endpc;
|
extern uint32_t codegen_endpc;
|
||||||
|
|
@ -286,23 +354,27 @@ extern int codegen_block_cycles;
|
||||||
|
|
||||||
extern void (*codegen_timing_start)();
|
extern void (*codegen_timing_start)();
|
||||||
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||||
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
|
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||||
extern void (*codegen_timing_block_start)();
|
extern void (*codegen_timing_block_start)();
|
||||||
extern void (*codegen_timing_block_end)();
|
extern void (*codegen_timing_block_end)();
|
||||||
|
extern int (*codegen_timing_jump_cycles)();
|
||||||
|
|
||||||
typedef struct codegen_timing_t
|
typedef struct codegen_timing_t
|
||||||
{
|
{
|
||||||
void (*start)();
|
void (*start)();
|
||||||
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
|
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||||
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
|
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||||
void (*block_start)();
|
void (*block_start)();
|
||||||
void (*block_end)();
|
void (*block_end)();
|
||||||
|
int (*jump_cycles)();
|
||||||
} codegen_timing_t;
|
} codegen_timing_t;
|
||||||
|
|
||||||
extern codegen_timing_t codegen_timing_pentium;
|
extern codegen_timing_t codegen_timing_pentium;
|
||||||
extern codegen_timing_t codegen_timing_686;
|
extern codegen_timing_t codegen_timing_686;
|
||||||
extern codegen_timing_t codegen_timing_486;
|
extern codegen_timing_t codegen_timing_486;
|
||||||
extern codegen_timing_t codegen_timing_winchip;
|
extern codegen_timing_t codegen_timing_winchip;
|
||||||
|
extern codegen_timing_t codegen_timing_winchip2;
|
||||||
|
extern codegen_timing_t codegen_timing_k6;
|
||||||
|
|
||||||
void codegen_timing_set(codegen_timing_t *timing);
|
void codegen_timing_set(codegen_timing_t *timing);
|
||||||
|
|
||||||
|
|
@ -311,45 +383,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;
|
||||||
|
|
||||||
|
|
@ -369,4 +402,13 @@ extern int codegen_reg_loaded[8];
|
||||||
|
|
||||||
extern int codegen_in_recompile;
|
extern int codegen_in_recompile;
|
||||||
|
|
||||||
|
void codegen_generate_reset();
|
||||||
|
|
||||||
|
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction);
|
||||||
|
void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction);
|
||||||
|
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
extern uint32_t instr_counts[256*256];
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
50
src/codegen_accumulate.c
Normal file
50
src/codegen_accumulate.c
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
int dest_reg;
|
||||||
|
} acc_regs[] =
|
||||||
|
{
|
||||||
|
[ACCREG_ins] = {0, IREG_ins},
|
||||||
|
[ACCREG_cycles] = {0, IREG_cycles},
|
||||||
|
};
|
||||||
|
|
||||||
|
void codegen_accumulate(int acc_reg, int delta)
|
||||||
|
{
|
||||||
|
if (acc_reg == ACCREG_cycles)
|
||||||
|
{
|
||||||
|
// pclog("cycles %04x:%04x %i\n", CS, cpu_state.pc, delta);
|
||||||
|
// if (CS == 0x1000 && cpu_state.pc == 0x863)
|
||||||
|
// fatal("Here\n");
|
||||||
|
}
|
||||||
|
acc_regs[acc_reg].count += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_accumulate_flush(ir_data_t *ir)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < ACCREG_COUNT; c++)
|
||||||
|
{
|
||||||
|
if (acc_regs[c].count)
|
||||||
|
{
|
||||||
|
// if (c == ACCREG_cycles)
|
||||||
|
// pclog("accumulate %i %i %i\n", c, acc_regs[c].dest_reg, acc_regs[c].count);
|
||||||
|
uop_ADD_IMM(ir, acc_regs[c].dest_reg, acc_regs[c].dest_reg, acc_regs[c].count);
|
||||||
|
}
|
||||||
|
|
||||||
|
acc_regs[c].count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_accumulate_reset()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < ACCREG_COUNT; c++)
|
||||||
|
acc_regs[c].count = 0;
|
||||||
|
}
|
||||||
13
src/codegen_accumulate.h
Normal file
13
src/codegen_accumulate.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ACCREG_ins = 0,
|
||||||
|
ACCREG_cycles = 1,
|
||||||
|
|
||||||
|
ACCREG_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ir_data_t;
|
||||||
|
|
||||||
|
void codegen_accumulate(int acc_reg, int delta);
|
||||||
|
void codegen_accumulate_flush(struct ir_data_t *ir);
|
||||||
|
void codegen_accumulate_reset();
|
||||||
126
src/codegen_allocator.c
Normal file
126
src/codegen_allocator.c
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
|
||||||
|
typedef struct mem_block_t
|
||||||
|
{
|
||||||
|
uint32_t offset; /*Offset into mem_block_alloc*/
|
||||||
|
uint32_t next;
|
||||||
|
uint16_t code_block;
|
||||||
|
} mem_block_t;
|
||||||
|
|
||||||
|
static mem_block_t mem_blocks[MEM_BLOCK_NR];
|
||||||
|
static uint32_t mem_block_free_list;
|
||||||
|
static uint8_t *mem_block_alloc = NULL;
|
||||||
|
|
||||||
|
int codegen_allocator_usage = 0;
|
||||||
|
|
||||||
|
void codegen_allocator_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (c = 0; c < MEM_BLOCK_NR; c++)
|
||||||
|
{
|
||||||
|
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
|
||||||
|
mem_blocks[c].code_block = BLOCK_INVALID;
|
||||||
|
if (c < MEM_BLOCK_NR-1)
|
||||||
|
mem_blocks[c].next = c+2;
|
||||||
|
else
|
||||||
|
mem_blocks[c].next = 0;
|
||||||
|
}
|
||||||
|
mem_block_free_list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block)
|
||||||
|
{
|
||||||
|
mem_block_t *block;
|
||||||
|
uint32_t block_nr;
|
||||||
|
|
||||||
|
while (!mem_block_free_list)
|
||||||
|
{
|
||||||
|
/*Pick a random memory block and free the owning code block*/
|
||||||
|
block_nr = rand() & MEM_BLOCK_MASK;
|
||||||
|
block = &mem_blocks[block_nr];
|
||||||
|
|
||||||
|
if (block->code_block && block->code_block != code_block)
|
||||||
|
codegen_delete_block(&codeblock[block->code_block]);
|
||||||
|
}
|
||||||
|
// fatal("codegen_allocator_allocate: free list empty!\n");
|
||||||
|
|
||||||
|
/*Remove from free list*/
|
||||||
|
block_nr = mem_block_free_list;
|
||||||
|
block = &mem_blocks[block_nr-1];
|
||||||
|
mem_block_free_list = block->next;
|
||||||
|
|
||||||
|
block->code_block = code_block;
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
/*Add to parent list*/
|
||||||
|
block->next = parent->next;
|
||||||
|
parent->next = block_nr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
block->next = 0;
|
||||||
|
|
||||||
|
codegen_allocator_usage++;
|
||||||
|
/* if (parent)
|
||||||
|
pclog("codegen_allocator_allocate with parent: %p %i %i %p\n", block, block_nr, codegen_allocator_usage, parent);
|
||||||
|
else
|
||||||
|
pclog("codegen_allocator_allocate: %p %i %i\n", block, block_nr, codegen_allocator_usage);*/
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
void codegen_allocator_free(mem_block_t *block)
|
||||||
|
{
|
||||||
|
int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1;
|
||||||
|
|
||||||
|
// pclog("codegen_allocator_free: %p %i %i %i\n", block, block_nr, codegen_allocator_usage, block->next);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int next_block_nr = block->next;
|
||||||
|
// pclog(" free next=%i\n", next_block_nr);
|
||||||
|
codegen_allocator_usage--;
|
||||||
|
|
||||||
|
block->next = mem_block_free_list;
|
||||||
|
block->code_block = BLOCK_INVALID;
|
||||||
|
mem_block_free_list = block_nr;
|
||||||
|
block_nr = next_block_nr;
|
||||||
|
|
||||||
|
if (block_nr)
|
||||||
|
block = &mem_blocks[block_nr - 1];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *codeblock_allocator_get_ptr(mem_block_t *block)
|
||||||
|
{
|
||||||
|
return &mem_block_alloc[block->offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_allocator_clean_blocks(struct mem_block_t *block)
|
||||||
|
{
|
||||||
|
#if defined __ARM_EABI__ || defined __aarch64__
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
|
||||||
|
if (block->next)
|
||||||
|
block = &mem_blocks[block->next - 1];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
39
src/codegen_allocator.h
Normal file
39
src/codegen_allocator.h
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef _CODEGEN_ALLOCATOR_H_
|
||||||
|
#define _CODEGEN_ALLOCATOR_H_
|
||||||
|
|
||||||
|
/*The allocator handles all allocation of executable memory. Since the two-pass
|
||||||
|
recompiler design makes applying hard limits to codeblock size difficult, the
|
||||||
|
allocator allows memory to be provided as and when required.
|
||||||
|
|
||||||
|
The allocator provides a block size of a little under 1 kB (slightly lower to
|
||||||
|
limit cache aliasing). Each generated codeblock is allocated one block by default,
|
||||||
|
and will allocate additional block(s) once the existing memory is sorted. Blocks
|
||||||
|
are chained together by jump instructions.
|
||||||
|
|
||||||
|
Due to the chaining, the total memory size is limited by the range of a jump
|
||||||
|
instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to
|
||||||
|
+/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/
|
||||||
|
#ifdef __ARM_EABI__
|
||||||
|
#define MEM_BLOCK_NR 32768
|
||||||
|
#else
|
||||||
|
#define MEM_BLOCK_NR 131072
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1)
|
||||||
|
#define MEM_BLOCK_SIZE 0x3c0
|
||||||
|
|
||||||
|
void codegen_allocator_init();
|
||||||
|
/*Allocate a mem_block_t, and the associated backing memory.
|
||||||
|
If parent is non-NULL, then the new block will be added to the list in
|
||||||
|
parent->next*/
|
||||||
|
struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent, int code_block);
|
||||||
|
/*Free a mem_block_t, and any subsequent blocks in the list at block->next*/
|
||||||
|
void codegen_allocator_free(struct mem_block_t *block);
|
||||||
|
/*Get a pointer to the backing memory associated with block*/
|
||||||
|
uint8_t *codeblock_allocator_get_ptr(struct mem_block_t *block);
|
||||||
|
/*Cache clean memory block list*/
|
||||||
|
void codegen_allocator_clean_blocks(struct mem_block_t *block);
|
||||||
|
|
||||||
|
extern int codegen_allocator_usage;
|
||||||
|
|
||||||
|
#endif
|
||||||
889
src/codegen_backend.c
Normal file
889
src/codegen_backend.c
Normal file
|
|
@ -0,0 +1,889 @@
|
||||||
|
#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_accumulate.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
|
||||||
|
uint8_t *block_write_data = NULL;
|
||||||
|
|
||||||
|
int codegen_flat_ds, codegen_flat_ss;
|
||||||
|
int mmx_ebx_ecx_loaded;
|
||||||
|
int codegen_flags_changed = 0;
|
||||||
|
int codegen_fpu_entered = 0;
|
||||||
|
int codegen_mmx_entered = 0;
|
||||||
|
int codegen_fpu_loaded_iq[8];
|
||||||
|
x86seg *op_ea_seg;
|
||||||
|
int op_ssegs;
|
||||||
|
uint32_t op_old_pc;
|
||||||
|
|
||||||
|
uint32_t recomp_page = -1;
|
||||||
|
|
||||||
|
int block_current = 0;
|
||||||
|
static int block_num;
|
||||||
|
int block_pos;
|
||||||
|
|
||||||
|
int cpu_recomp_flushes, cpu_recomp_flushes_latched;
|
||||||
|
int cpu_recomp_evicted, cpu_recomp_evicted_latched;
|
||||||
|
int cpu_recomp_reuse, cpu_recomp_reuse_latched;
|
||||||
|
int cpu_recomp_removed, cpu_recomp_removed_latched;
|
||||||
|
|
||||||
|
uint32_t codegen_endpc;
|
||||||
|
|
||||||
|
int codegen_block_cycles;
|
||||||
|
static int codegen_block_ins;
|
||||||
|
static int codegen_block_full_ins;
|
||||||
|
|
||||||
|
static uint32_t last_op32;
|
||||||
|
static x86seg *last_ea_seg;
|
||||||
|
static int last_ssegs;
|
||||||
|
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
uint32_t instr_counts[256*256];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint16_t block_free_list;
|
||||||
|
static void delete_block(codeblock_t *block);
|
||||||
|
static void delete_dirty_block(codeblock_t *block);
|
||||||
|
|
||||||
|
/*Temporary list of code blocks that have recently been evicted. This allows for
|
||||||
|
some historical state to be kept when a block is the target of self-modifying
|
||||||
|
code.
|
||||||
|
|
||||||
|
The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is
|
||||||
|
exceeded the oldest entry will be moved to the free list.*/
|
||||||
|
static uint16_t block_dirty_list_head, block_dirty_list_tail;
|
||||||
|
static int dirty_list_size = 0;
|
||||||
|
#define DIRTY_LIST_MAX_SIZE 64
|
||||||
|
|
||||||
|
static void block_free_list_add(codeblock_t *block)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||||
|
fatal("block_free_list_add: block=%p in dirty list\n", block);
|
||||||
|
if (block_free_list)
|
||||||
|
block->next = block_free_list;
|
||||||
|
else
|
||||||
|
block->next = 0;
|
||||||
|
block_free_list = get_block_nr(block);
|
||||||
|
block->flags = CODEBLOCK_IN_FREE_LIST;
|
||||||
|
// pclog("block_free_list_add: %p %p\n", block, block->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void block_dirty_list_add(codeblock_t *block)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||||
|
fatal("block_dirty_list_add: block=%p already in dirty list\n", block);
|
||||||
|
// pclog("block_dirty_list_add: block=%i size=%i %i head=%i tail=%i\n", get_block_nr(block), dirty_list_size, dirty_list_check_size(), block_dirty_list_head, block_dirty_list_tail);
|
||||||
|
if (block_dirty_list_head != BLOCK_INVALID)
|
||||||
|
{
|
||||||
|
codeblock_t *old_head = &codeblock[block_dirty_list_head];
|
||||||
|
|
||||||
|
block->next = block_dirty_list_head;
|
||||||
|
block->prev = BLOCK_INVALID;
|
||||||
|
block_dirty_list_head = old_head->prev = get_block_nr(block);
|
||||||
|
// pclog(" next=%p,%i prev=%i\n", old_head, block->next, old_head->prev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*List empty*/
|
||||||
|
block->prev = block->next = BLOCK_INVALID;
|
||||||
|
block_dirty_list_head = block_dirty_list_tail = get_block_nr(block);
|
||||||
|
}
|
||||||
|
block->flags |= CODEBLOCK_IN_DIRTY_LIST;
|
||||||
|
// pclog(" block_dirty_list_add: %p flags = %x\n", block, block->flags);
|
||||||
|
dirty_list_size++;
|
||||||
|
if (dirty_list_size > DIRTY_LIST_MAX_SIZE)
|
||||||
|
{
|
||||||
|
/*Evict oldest block to the free list*/
|
||||||
|
codeblock_t *evict_block = &codeblock[block_dirty_list_tail];
|
||||||
|
|
||||||
|
if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST))
|
||||||
|
fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags);
|
||||||
|
if (!block_dirty_list_tail)
|
||||||
|
fatal("block_dirty_list_add - !block_dirty_list_tail\n");
|
||||||
|
if (evict_block->prev == BLOCK_INVALID)
|
||||||
|
fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n");
|
||||||
|
|
||||||
|
block_dirty_list_tail = evict_block->prev;
|
||||||
|
codeblock[evict_block->prev].next = BLOCK_INVALID;
|
||||||
|
|
||||||
|
dirty_list_size--;
|
||||||
|
evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
|
||||||
|
// pclog(" block_dirty_list_add: %p flags = %x\n", evict_block, evict_block->flags);
|
||||||
|
delete_dirty_block(evict_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pclog("block_free_list_add: %p %p\n", block, block->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void block_dirty_list_remove(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codeblock_t *prev_block = &codeblock[block->prev];
|
||||||
|
codeblock_t *next_block = &codeblock[block->next];
|
||||||
|
|
||||||
|
if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST))
|
||||||
|
fatal("block_dirty_list_remove: block=%p not in dirty list\n", block);
|
||||||
|
|
||||||
|
/*Is block head of list*/
|
||||||
|
if (block->prev == BLOCK_INVALID)
|
||||||
|
block_dirty_list_head = block->next;
|
||||||
|
else
|
||||||
|
prev_block->next = block->next;
|
||||||
|
|
||||||
|
/*Is block tail of list?*/
|
||||||
|
if (block->next == BLOCK_INVALID)
|
||||||
|
block_dirty_list_tail = block->prev;
|
||||||
|
else
|
||||||
|
next_block->prev = block->prev;
|
||||||
|
|
||||||
|
dirty_list_size--;
|
||||||
|
if (dirty_list_size < 0)
|
||||||
|
fatal("remove - dirty_list_size < 0!\n");
|
||||||
|
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
|
||||||
|
// pclog(" block_dirty_list_remove: %p flags = %x\n", block, block->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int codegen_purge_purgable_list()
|
||||||
|
{
|
||||||
|
if (purgable_page_list_head)
|
||||||
|
{
|
||||||
|
page_t *page = &pages[purgable_page_list_head];
|
||||||
|
|
||||||
|
if (page->code_present_mask & page->dirty_mask)
|
||||||
|
{
|
||||||
|
codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12);
|
||||||
|
|
||||||
|
if (block_free_list)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static codeblock_t *block_free_list_get()
|
||||||
|
{
|
||||||
|
codeblock_t *block = NULL;
|
||||||
|
|
||||||
|
while (!block_free_list)
|
||||||
|
{
|
||||||
|
/*Free list is empty, check the dirty list*/
|
||||||
|
if (block_dirty_list_tail)
|
||||||
|
{
|
||||||
|
if (dirty_list_size <= 0)
|
||||||
|
fatal("get - dirty_list_size <= 0!\n");
|
||||||
|
|
||||||
|
/*Reuse oldest block*/
|
||||||
|
block = &codeblock[block_dirty_list_tail];
|
||||||
|
|
||||||
|
// pclog("block_free_list_get: remove block=%p size=%i\n", block, dirty_list_size);
|
||||||
|
block_dirty_list_tail = block->prev;
|
||||||
|
if (block->prev == BLOCK_INVALID)
|
||||||
|
block_dirty_list_head = BLOCK_INVALID;
|
||||||
|
else
|
||||||
|
codeblock[block->prev].next = BLOCK_INVALID;
|
||||||
|
dirty_list_size--;
|
||||||
|
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
|
||||||
|
delete_dirty_block(block);
|
||||||
|
block_free_list = get_block_nr(block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*Free list is empty - free up a block*/
|
||||||
|
if (!codegen_purge_purgable_list())
|
||||||
|
codegen_delete_random_block(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
block = &codeblock[block_free_list];
|
||||||
|
block_free_list = block->next;
|
||||||
|
block->flags &= ~CODEBLOCK_IN_FREE_LIST;
|
||||||
|
// pclog(" block_free_list_get: %p flags = %x\n", block, block->flags);
|
||||||
|
block->next = 0;
|
||||||
|
// pclog("block_free_list_get: %p %p\n", block, block_free_list);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_init()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
codegen_allocator_init();
|
||||||
|
|
||||||
|
codegen_backend_init();
|
||||||
|
block_free_list = 0;
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
block_free_list_add(&codeblock[c]);
|
||||||
|
block_dirty_list_head = block_dirty_list_tail = 0;
|
||||||
|
dirty_list_size = 0;
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
memset(instr_counts, 0, sizeof(instr_counts));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_close()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
pclog("Instruction counts :\n");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
uint32_t highest_num = 0, highest_idx = 0;
|
||||||
|
|
||||||
|
for (c = 0; c < 256*256; c++)
|
||||||
|
{
|
||||||
|
if (instr_counts[c] > highest_num)
|
||||||
|
{
|
||||||
|
highest_num = instr_counts[c];
|
||||||
|
highest_idx = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!highest_num)
|
||||||
|
break;
|
||||||
|
|
||||||
|
instr_counts[highest_idx] = 0;
|
||||||
|
if (highest_idx > 256)
|
||||||
|
pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num);
|
||||||
|
else
|
||||||
|
pclog(" %02x = %u\n", highest_idx & 0xff, highest_num);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_reset()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 1; c < BLOCK_SIZE; c++)
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[c];
|
||||||
|
|
||||||
|
if (block->pc != BLOCK_PC_INVALID)
|
||||||
|
{
|
||||||
|
block->phys = 0;
|
||||||
|
block->phys_2 = 0;
|
||||||
|
delete_block(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t));
|
||||||
|
mem_reset_page_blocks();
|
||||||
|
|
||||||
|
block_free_list = 0;
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
{
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
block_free_list_add(&codeblock[c]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_block()
|
||||||
|
{
|
||||||
|
/* codeblock_t *block = pages[0x119000 >> 12].block;
|
||||||
|
|
||||||
|
pclog("dump_block:\n");
|
||||||
|
while (block)
|
||||||
|
{
|
||||||
|
uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff);
|
||||||
|
uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff);
|
||||||
|
pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next);
|
||||||
|
if (!block->pc)
|
||||||
|
fatal("Dead PC=0\n");
|
||||||
|
|
||||||
|
block = block->next;
|
||||||
|
}
|
||||||
|
pclog("dump_block done\n");*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_to_block_list(codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t block_prev_nr = pages[block->phys >> 12].block;
|
||||||
|
uint16_t block_nr = get_block_nr(block);
|
||||||
|
//pclog("Add to block list %p %08x %llx %x\n", block, block->phys, block->page_mask2, block->flags);
|
||||||
|
|
||||||
|
if (!block->page_mask)
|
||||||
|
fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2);
|
||||||
|
|
||||||
|
if (block_prev_nr)
|
||||||
|
{
|
||||||
|
block->next = block_prev_nr;
|
||||||
|
codeblock[block_prev_nr].prev = block_nr;
|
||||||
|
pages[block->phys >> 12].block = block_nr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block->next = BLOCK_INVALID;
|
||||||
|
pages[block->phys >> 12].block = block_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->next)
|
||||||
|
{
|
||||||
|
if (codeblock[block->next].pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->page_mask2)
|
||||||
|
{
|
||||||
|
block->flags |= CODEBLOCK_HAS_PAGE2;
|
||||||
|
|
||||||
|
block_prev_nr = pages[block->phys_2 >> 12].block_2;
|
||||||
|
|
||||||
|
if (block_prev_nr)
|
||||||
|
{
|
||||||
|
block->next_2 = block_prev_nr;
|
||||||
|
codeblock[block_prev_nr].prev_2 = block_nr;
|
||||||
|
pages[block->phys_2 >> 12].block_2 = block_nr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block->next_2 = BLOCK_INVALID;
|
||||||
|
pages[block->phys_2 >> 12].block_2 = block_nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pclog(" add_to_block_list: %p flags = %x\n", block, block->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_from_block_list(codeblock_t *block, uint32_t pc)
|
||||||
|
{
|
||||||
|
if (!block->page_mask)
|
||||||
|
return;
|
||||||
|
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||||
|
fatal("remove_from_block_list: in dirty list\n");
|
||||||
|
|
||||||
|
if (block->prev)
|
||||||
|
{
|
||||||
|
codeblock[block->prev].next = block->next;
|
||||||
|
if (block->next)
|
||||||
|
codeblock[block->next].prev = block->prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pages[block->phys >> 12].block = block->next;
|
||||||
|
if (block->next)
|
||||||
|
codeblock[block->next].prev = BLOCK_INVALID;
|
||||||
|
else
|
||||||
|
mem_flush_write_page(block->phys, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(block->flags & CODEBLOCK_HAS_PAGE2))
|
||||||
|
{
|
||||||
|
if (block->prev_2 || block->next_2)
|
||||||
|
fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
block->flags &= ~CODEBLOCK_HAS_PAGE2;
|
||||||
|
// pclog(" remove_from_block_list: %p flags = %x\n", block, block->flags);
|
||||||
|
|
||||||
|
if (block->prev_2)
|
||||||
|
{
|
||||||
|
codeblock[block->prev_2].next_2 = block->next_2;
|
||||||
|
if (block->next_2)
|
||||||
|
codeblock[block->next_2].prev_2 = block->prev_2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2);
|
||||||
|
pages[block->phys_2 >> 12].block_2 = block->next_2;
|
||||||
|
if (block->next_2)
|
||||||
|
codeblock[block->next_2].prev_2 = BLOCK_INVALID;
|
||||||
|
else
|
||||||
|
mem_flush_write_page(block->phys_2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invalidate_block(codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t old_pc = block->pc;
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||||
|
fatal("invalidate_block: already in dirty list\n");
|
||||||
|
if (block->pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("Invalidating deleted block\n");
|
||||||
|
|
||||||
|
remove_from_block_list(block, old_pc);
|
||||||
|
block_dirty_list_add(block);
|
||||||
|
if (block->head_mem_block)
|
||||||
|
codegen_allocator_free(block->head_mem_block);
|
||||||
|
block->head_mem_block = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delete_block(codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t old_pc = block->pc;
|
||||||
|
|
||||||
|
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
|
||||||
|
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
|
||||||
|
|
||||||
|
if (block->pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("Deleting deleted block\n");
|
||||||
|
block->pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
codeblock_tree_delete(block);
|
||||||
|
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||||
|
block_dirty_list_remove(block);
|
||||||
|
else
|
||||||
|
remove_from_block_list(block, old_pc);
|
||||||
|
if (block->head_mem_block)
|
||||||
|
codegen_allocator_free(block->head_mem_block);
|
||||||
|
block->head_mem_block = NULL;
|
||||||
|
block_free_list_add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delete_dirty_block(codeblock_t *block)
|
||||||
|
{
|
||||||
|
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
|
||||||
|
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
|
||||||
|
|
||||||
|
if (block->pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("Deleting deleted block\n");
|
||||||
|
block->pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
codeblock_tree_delete(block);
|
||||||
|
block_free_list_add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_delete_block(codeblock_t *block)
|
||||||
|
{
|
||||||
|
if (block->pc != BLOCK_PC_INVALID)
|
||||||
|
delete_block(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_delete_random_block(int required_mem_block)
|
||||||
|
{
|
||||||
|
int block_nr = rand() & BLOCK_MASK;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (block_nr && block_nr != block_current)
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_nr];
|
||||||
|
|
||||||
|
if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block))
|
||||||
|
{
|
||||||
|
delete_block(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block_nr = (block_nr + 1) & BLOCK_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
|
||||||
|
{
|
||||||
|
uint16_t block_nr = page->block;
|
||||||
|
int remove_from_evict_list = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while (block_nr)
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_nr];
|
||||||
|
uint16_t next_block = block->next;
|
||||||
|
|
||||||
|
if (*block->dirty_mask & block->page_mask)
|
||||||
|
{
|
||||||
|
// pclog("Delete block from codegen_check_flush %08x %08x %016llx %016llx %016llx %02x\n", phys_addr, block->pc, *block->dirty_mask, block->page_mask, *block->dirty_mask & block->page_mask, block->flags);
|
||||||
|
invalidate_block(block);
|
||||||
|
cpu_recomp_evicted++;
|
||||||
|
}
|
||||||
|
if (block_nr == next_block)
|
||||||
|
fatal("Broken 1\n");
|
||||||
|
block_nr = next_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_nr = page->block_2;
|
||||||
|
|
||||||
|
while (block_nr)
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_nr];
|
||||||
|
uint16_t next_block = block->next_2;
|
||||||
|
|
||||||
|
if (*block->dirty_mask2 & block->page_mask2)
|
||||||
|
{
|
||||||
|
// pclog("Delete block from codegen_check_flush2 %08x %08x\n", phys_addr, block->pc);*/
|
||||||
|
invalidate_block(block);
|
||||||
|
cpu_recomp_evicted++;
|
||||||
|
}
|
||||||
|
if (block_nr == next_block)
|
||||||
|
fatal("Broken 2\n");
|
||||||
|
block_nr = next_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page->code_present_mask & page->dirty_mask)
|
||||||
|
remove_from_evict_list = 1;
|
||||||
|
page->code_present_mask &= ~page->dirty_mask;
|
||||||
|
page->dirty_mask = 0;
|
||||||
|
|
||||||
|
for (c = 0; c < 64; c++)
|
||||||
|
{
|
||||||
|
if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c])
|
||||||
|
remove_from_evict_list = 0;
|
||||||
|
page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c];
|
||||||
|
page->byte_dirty_mask[c] = 0;
|
||||||
|
}
|
||||||
|
if (remove_from_evict_list)
|
||||||
|
page_remove_from_evict_list(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_init(uint32_t phys_addr)
|
||||||
|
{
|
||||||
|
codeblock_t *block;
|
||||||
|
page_t *page = &pages[phys_addr >> 12];
|
||||||
|
|
||||||
|
if (!page->block)
|
||||||
|
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
|
||||||
|
block = block_free_list_get();
|
||||||
|
if (!block)
|
||||||
|
fatal("codegen_block_init: block_free_list_get() returned NULL\n");
|
||||||
|
block_current = get_block_nr(block);
|
||||||
|
|
||||||
|
block_num = HASH(phys_addr);
|
||||||
|
codeblock_hash[block_num] = block_current;
|
||||||
|
|
||||||
|
block->ins = 0;
|
||||||
|
block->pc = cs + cpu_state.pc;
|
||||||
|
block->_cs = cs;
|
||||||
|
block->phys = phys_addr;
|
||||||
|
block->dirty_mask = &page->dirty_mask;
|
||||||
|
block->dirty_mask2 = NULL;
|
||||||
|
block->next = block->prev = BLOCK_INVALID;
|
||||||
|
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||||
|
block->page_mask = block->page_mask2 = 0;
|
||||||
|
block->flags = CODEBLOCK_STATIC_TOP;
|
||||||
|
// pclog(" block_init: %p flags = %x\n", block, block->flags);
|
||||||
|
block->status = cpu_cur_status;
|
||||||
|
|
||||||
|
recomp_page = block->phys & ~0xfff;
|
||||||
|
// pclog("codegen_block_init: %08x\n", block->pc);
|
||||||
|
codeblock_tree_add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ir_data_t *ir_data;
|
||||||
|
|
||||||
|
ir_data_t *codegen_get_ir_data()
|
||||||
|
{
|
||||||
|
return ir_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_start_recompile(codeblock_t *block)
|
||||||
|
{
|
||||||
|
page_t *page = &pages[block->phys >> 12];
|
||||||
|
|
||||||
|
if (!page->block)
|
||||||
|
mem_flush_write_page(block->phys, cs+cpu_state.pc);
|
||||||
|
|
||||||
|
block_num = HASH(block->phys);
|
||||||
|
block_current = get_block_nr(block);//block->pnt;
|
||||||
|
|
||||||
|
if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED))
|
||||||
|
fatal("Recompile to used block!\n");
|
||||||
|
|
||||||
|
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||||
|
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||||
|
|
||||||
|
block->status = cpu_cur_status;
|
||||||
|
|
||||||
|
block->page_mask = block->page_mask2 = 0;
|
||||||
|
block->ins = 0;
|
||||||
|
|
||||||
|
cpu_block_end = 0;
|
||||||
|
|
||||||
|
// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num);
|
||||||
|
|
||||||
|
last_op32 = -1;
|
||||||
|
last_ea_seg = NULL;
|
||||||
|
last_ssegs = -1;
|
||||||
|
|
||||||
|
codegen_block_cycles = 0;
|
||||||
|
codegen_timing_block_start();
|
||||||
|
|
||||||
|
codegen_block_ins = 0;
|
||||||
|
codegen_block_full_ins = 0;
|
||||||
|
|
||||||
|
recomp_page = block->phys & ~0xfff;
|
||||||
|
|
||||||
|
codegen_flags_changed = 0;
|
||||||
|
codegen_fpu_entered = 0;
|
||||||
|
codegen_mmx_entered = 0;
|
||||||
|
|
||||||
|
codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
|
||||||
|
codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
|
||||||
|
|
||||||
|
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1;
|
||||||
|
|
||||||
|
block->TOP = cpu_state.TOP & 7;
|
||||||
|
block->flags |= CODEBLOCK_WAS_RECOMPILED;
|
||||||
|
|
||||||
|
codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);
|
||||||
|
codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS);
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
{
|
||||||
|
block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK];
|
||||||
|
block->dirty_mask2 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir_data = codegen_ir_init();
|
||||||
|
ir_data->block = block;
|
||||||
|
codegen_reg_reset();
|
||||||
|
codegen_accumulate_reset();
|
||||||
|
codegen_generate_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void codegen_block_remove()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
|
||||||
|
delete_block(block);
|
||||||
|
cpu_recomp_removed++;
|
||||||
|
|
||||||
|
recomp_page = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_generate_end_mask_recompile()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
page_t *p;
|
||||||
|
//pclog("gen_end_mask: %08x %08x %016llx %016llx\n", block->pc, codegen_endpc, block->page_mask,block->page_mask2);
|
||||||
|
|
||||||
|
p = &pages[block->phys >> 12];
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
{
|
||||||
|
int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||||
|
|
||||||
|
p->byte_code_present_mask[offset] |= block->page_mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p->code_present_mask |= block->page_mask;
|
||||||
|
|
||||||
|
if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p))
|
||||||
|
page_add_to_evict_list(p);
|
||||||
|
|
||||||
|
block->phys_2 = -1;
|
||||||
|
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||||
|
if (block->page_mask2)
|
||||||
|
{
|
||||||
|
block->phys_2 = get_phys_noabrt(codegen_endpc);
|
||||||
|
if (block->phys_2 != -1)
|
||||||
|
{
|
||||||
|
page_t *page_2 = &pages[block->phys_2 >> 12];
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
{
|
||||||
|
int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
|
||||||
|
|
||||||
|
page_2->byte_code_present_mask[offset] |= block->page_mask2;
|
||||||
|
block->dirty_mask2 = &page_2->byte_dirty_mask[offset];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page_2->code_present_mask |= block->page_mask2;
|
||||||
|
block->dirty_mask2 = &page_2->dirty_mask;
|
||||||
|
}
|
||||||
|
if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2))
|
||||||
|
page_add_to_evict_list(page_2);
|
||||||
|
|
||||||
|
if (!pages[block->phys_2 >> 12].block_2)
|
||||||
|
mem_flush_write_page(block->phys_2, codegen_endpc);
|
||||||
|
|
||||||
|
if (!block->page_mask2)
|
||||||
|
fatal("!page_mask2\n");
|
||||||
|
if (block->next_2)
|
||||||
|
{
|
||||||
|
// pclog(" next_2->pc=%08x\n", block->next_2->pc);
|
||||||
|
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*Second page not present. page_mask2 is most likely set only because
|
||||||
|
the recompiler didn't know how long the last instruction was, so
|
||||||
|
clear it*/
|
||||||
|
block->page_mask2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask);
|
||||||
|
recomp_page = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_generate_end_mask_mark()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
uint32_t start_pc;
|
||||||
|
uint32_t end_pc;
|
||||||
|
page_t *p;
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n");
|
||||||
|
|
||||||
|
block->page_mask = 0;
|
||||||
|
start_pc = (block->pc & 0xfff) & ~63;
|
||||||
|
if ((block->pc ^ codegen_endpc) & ~0xfff)
|
||||||
|
end_pc = 0xfff & ~63;
|
||||||
|
else
|
||||||
|
end_pc = (codegen_endpc & 0xfff) & ~63;
|
||||||
|
if (end_pc < start_pc)
|
||||||
|
end_pc = 0xfff;
|
||||||
|
start_pc >>= PAGE_MASK_SHIFT;
|
||||||
|
end_pc >>= PAGE_MASK_SHIFT;
|
||||||
|
|
||||||
|
// pclog("block_end: %08x %08x\n", start_pc, end_pc);
|
||||||
|
for (; start_pc <= end_pc; start_pc++)
|
||||||
|
{
|
||||||
|
block->page_mask |= ((uint64_t)1 << start_pc);
|
||||||
|
// pclog(" %08x %llx\n", start_pc, block->page_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = &pages[block->phys >> 12];
|
||||||
|
p->code_present_mask |= block->page_mask;
|
||||||
|
if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p))
|
||||||
|
page_add_to_evict_list(p);
|
||||||
|
|
||||||
|
block->phys_2 = -1;
|
||||||
|
block->page_mask2 = 0;
|
||||||
|
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||||
|
if ((block->pc ^ codegen_endpc) & ~0xfff)
|
||||||
|
{
|
||||||
|
block->phys_2 = get_phys_noabrt(codegen_endpc);
|
||||||
|
if (block->phys_2 != -1)
|
||||||
|
{
|
||||||
|
page_t *page_2 = &pages[block->phys_2 >> 12];
|
||||||
|
|
||||||
|
start_pc = 0;
|
||||||
|
end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT;
|
||||||
|
for (; start_pc <= end_pc; start_pc++)
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << start_pc);
|
||||||
|
|
||||||
|
page_2->code_present_mask |= block->page_mask2;
|
||||||
|
if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2))
|
||||||
|
page_add_to_evict_list(page_2);
|
||||||
|
|
||||||
|
if (!pages[block->phys_2 >> 12].block_2)
|
||||||
|
mem_flush_write_page(block->phys_2, codegen_endpc);
|
||||||
|
|
||||||
|
if (!block->page_mask2)
|
||||||
|
fatal("!page_mask2\n");
|
||||||
|
if (block->next_2)
|
||||||
|
{
|
||||||
|
// pclog(" next_2->pc=%08x\n", block->next_2->pc);
|
||||||
|
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
|
||||||
|
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
block->dirty_mask2 = &page_2->dirty_mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*Second page not present. page_mask2 is most likely set only because
|
||||||
|
the recompiler didn't know how long the last instruction was, so
|
||||||
|
clear it*/
|
||||||
|
block->page_mask2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask);
|
||||||
|
recomp_page = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_end()
|
||||||
|
{
|
||||||
|
codeblock_t *block = &codeblock[block_current];
|
||||||
|
|
||||||
|
codegen_block_generate_end_mask_mark();
|
||||||
|
add_to_block_list(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_block_end_recompile(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_timing_block_end();
|
||||||
|
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
|
||||||
|
block_dirty_list_remove(block);
|
||||||
|
else
|
||||||
|
remove_from_block_list(block, block->pc);
|
||||||
|
block->next = block->prev = BLOCK_INVALID;
|
||||||
|
block->next_2 = block->prev_2 = BLOCK_INVALID;
|
||||||
|
codegen_block_generate_end_mask_recompile();
|
||||||
|
add_to_block_list(block);
|
||||||
|
// pclog("End block %i\n", block_num);
|
||||||
|
|
||||||
|
if (!(block->flags & CODEBLOCK_HAS_FPU))
|
||||||
|
block->flags &= ~CODEBLOCK_STATIC_TOP;
|
||||||
|
|
||||||
|
codegen_accumulate_flush(ir_data);
|
||||||
|
codegen_ir_compile(ir_data, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_flush()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len)
|
||||||
|
{
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
uint32_t end_pc = start_pc + (len-1);
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
{
|
||||||
|
uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK;
|
||||||
|
uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK;
|
||||||
|
|
||||||
|
if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/
|
||||||
|
{
|
||||||
|
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
|
||||||
|
}
|
||||||
|
else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/
|
||||||
|
{
|
||||||
|
for (; start_pc_masked <= 63; start_pc_masked++)
|
||||||
|
block->page_mask |= ((uint64_t)1 << start_pc_masked);
|
||||||
|
for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++)
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
|
||||||
|
}
|
||||||
|
else /*First page only*/
|
||||||
|
{
|
||||||
|
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
|
||||||
|
block->page_mask |= ((uint64_t)1 << start_pc_masked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT;
|
||||||
|
uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT;
|
||||||
|
start_pc_shifted &= PAGE_MASK_MASK;
|
||||||
|
end_pc_shifted &= PAGE_MASK_MASK;
|
||||||
|
|
||||||
|
if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/
|
||||||
|
{
|
||||||
|
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
|
||||||
|
}
|
||||||
|
else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/
|
||||||
|
{
|
||||||
|
for (; start_pc_shifted <= 63; start_pc_shifted++)
|
||||||
|
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
|
||||||
|
for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
|
||||||
|
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
|
||||||
|
}
|
||||||
|
else /*First page only*/
|
||||||
|
{
|
||||||
|
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
|
||||||
|
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/codegen_backend.h
Normal file
29
src/codegen_backend.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
//#ifdef __amd64__
|
||||||
|
//#include "codegen_x86-64.h"
|
||||||
|
#if defined __amd64__
|
||||||
|
#include "codegen_backend_x86-64.h"
|
||||||
|
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include "codegen_backend_x86.h"
|
||||||
|
#elif defined __ARM_EABI__
|
||||||
|
#include "codegen_backend_arm.h"
|
||||||
|
#elif defined __aarch64__
|
||||||
|
#include "codegen_backend_arm64.h"
|
||||||
|
#else
|
||||||
|
#error Dynamic recompiler not implemented on your platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void codegen_backend_init();
|
||||||
|
void codegen_backend_prologue(codeblock_t *block);
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block);
|
||||||
|
|
||||||
|
struct ir_data_t;
|
||||||
|
struct uop_t;
|
||||||
|
|
||||||
|
struct ir_data_t *codegen_get_ir_data();
|
||||||
|
|
||||||
|
typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
|
||||||
|
|
||||||
|
extern const uOpFn uop_handlers[];
|
||||||
|
|
||||||
|
extern int codegen_host_reg_list[CODEGEN_HOST_REGS];
|
||||||
|
extern int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];
|
||||||
368
src/codegen_backend_arm.c
Normal file
368
src/codegen_backend_arm.c
Normal file
|
|
@ -0,0 +1,368 @@
|
||||||
|
#ifdef __ARM_EABI__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_arm_defs.h"
|
||||||
|
#include "codegen_backend_arm_ops.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x87.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *codegen_mem_load_byte;
|
||||||
|
void *codegen_mem_load_word;
|
||||||
|
void *codegen_mem_load_long;
|
||||||
|
void *codegen_mem_load_quad;
|
||||||
|
void *codegen_mem_load_single;
|
||||||
|
void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
void *codegen_mem_store_byte;
|
||||||
|
void *codegen_mem_store_word;
|
||||||
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
|
void *codegen_mem_store_single;
|
||||||
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
void *codegen_fp_round;
|
||||||
|
|
||||||
|
void *codegen_gpf_rout;
|
||||||
|
void *codegen_exit_rout;
|
||||||
|
|
||||||
|
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||||
|
{
|
||||||
|
REG_R4,
|
||||||
|
REG_R5,
|
||||||
|
REG_R6,
|
||||||
|
REG_R7,
|
||||||
|
REG_R8,
|
||||||
|
REG_R9,
|
||||||
|
REG_R11,
|
||||||
|
};
|
||||||
|
|
||||||
|
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
|
||||||
|
{
|
||||||
|
REG_D8,
|
||||||
|
REG_D9,
|
||||||
|
REG_D10,
|
||||||
|
REG_D11,
|
||||||
|
REG_D12,
|
||||||
|
REG_D13,
|
||||||
|
REG_D14,
|
||||||
|
REG_D15
|
||||||
|
};
|
||||||
|
|
||||||
|
static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint32_t *branch_offset;
|
||||||
|
uint32_t *misaligned_offset;
|
||||||
|
|
||||||
|
/*In - R0 = address
|
||||||
|
Out - R0 = data, R1 = abrt*/
|
||||||
|
/*MOV R1, R0, LSR #12
|
||||||
|
MOV R2, #readlookup2
|
||||||
|
LDR R1, [R2, R1, LSL #2]
|
||||||
|
CMP R1, #-1
|
||||||
|
BNE +
|
||||||
|
LDRB R0, [R1, R0]
|
||||||
|
MOV R1, #0
|
||||||
|
MOV PC, LR
|
||||||
|
* STR LR, [SP, -4]!
|
||||||
|
BL readmembl
|
||||||
|
LDRB R1, cpu_state.abrt
|
||||||
|
LDR PC, [SP], #4
|
||||||
|
*/
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
|
||||||
|
host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2);
|
||||||
|
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_arm_TST_IMM(block, REG_R0, size-1);
|
||||||
|
misaligned_offset = host_arm_BNE_(block);
|
||||||
|
}
|
||||||
|
host_arm_CMP_IMM(block, REG_R1, -1);
|
||||||
|
branch_offset = host_arm_BEQ_(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
{
|
||||||
|
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
|
||||||
|
host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||||
|
}
|
||||||
|
else if (size == 8)
|
||||||
|
{
|
||||||
|
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
|
||||||
|
host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||||
|
}
|
||||||
|
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||||
|
if (size != 1)
|
||||||
|
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||||
|
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||||
|
if (size == 1)
|
||||||
|
host_arm_BL(block, (uintptr_t)readmembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_arm_BL(block, (uintptr_t)readmemwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_arm_BL(block, (uintptr_t)readmemll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm_BL(block, (uintptr_t)readmemql);
|
||||||
|
else
|
||||||
|
fatal("build_load_routine - unknown size %i\n", size);
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
|
||||||
|
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||||
|
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint32_t *branch_offset;
|
||||||
|
uint32_t *misaligned_offset;
|
||||||
|
|
||||||
|
/*In - R0 = address
|
||||||
|
Out - R0 = data, R1 = abrt*/
|
||||||
|
/*MOV R1, R0, LSR #12
|
||||||
|
MOV R2, #readlookup2
|
||||||
|
LDR R1, [R2, R1, LSL #2]
|
||||||
|
CMP R1, #-1
|
||||||
|
BNE +
|
||||||
|
LDRB R0, [R1, R0]
|
||||||
|
MOV R1, #0
|
||||||
|
MOV PC, LR
|
||||||
|
* STR LR, [SP, -4]!
|
||||||
|
BL readmembl
|
||||||
|
LDRB R1, cpu_state.abrt
|
||||||
|
LDR PC, [SP], #4
|
||||||
|
*/
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
|
||||||
|
host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2);
|
||||||
|
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_arm_TST_IMM(block, REG_R0, size-1);
|
||||||
|
misaligned_offset = host_arm_BNE_(block);
|
||||||
|
}
|
||||||
|
host_arm_CMP_IMM(block, REG_R2, -1);
|
||||||
|
branch_offset = host_arm_BEQ_(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
{
|
||||||
|
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||||
|
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||||
|
}
|
||||||
|
else if (size == 8)
|
||||||
|
{
|
||||||
|
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||||
|
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||||
|
}
|
||||||
|
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||||
|
if (size != 1)
|
||||||
|
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||||
|
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
|
||||||
|
if (size == 1)
|
||||||
|
host_arm_BL(block, (uintptr_t)writemembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_arm_BL(block, (uintptr_t)writememwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_arm_BL(block, (uintptr_t)writememll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm_BL_r1(block, (uintptr_t)writememql);
|
||||||
|
else
|
||||||
|
fatal("build_store_routine - unknown size %i\n", size);
|
||||||
|
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||||
|
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_loadstore_routines(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 1, 0);
|
||||||
|
codegen_mem_load_word = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 2, 0);
|
||||||
|
codegen_mem_load_long = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 4, 0);
|
||||||
|
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 8, 0);
|
||||||
|
codegen_mem_load_single = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 4, 1);
|
||||||
|
codegen_mem_load_double = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 8, 1);
|
||||||
|
|
||||||
|
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 1, 0);
|
||||||
|
codegen_mem_store_word = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 2, 0);
|
||||||
|
codegen_mem_store_long = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
|
codegen_mem_store_single = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 4, 1);
|
||||||
|
codegen_mem_store_double = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*VFP has a specific round-to-zero instruction, and the default rounding mode
|
||||||
|
is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/
|
||||||
|
#define FPCSR_ROUNDING_MASK (3 << 22)
|
||||||
|
#define FPCSR_ROUNDING_UP (1 << 22)
|
||||||
|
#define FPCSR_ROUNDING_DOWN (2 << 22)
|
||||||
|
|
||||||
|
static void build_fp_round_routine(codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t *jump_table;
|
||||||
|
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
|
||||||
|
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
|
||||||
|
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
|
||||||
|
host_arm_NOP(block);
|
||||||
|
|
||||||
|
jump_table = (uint32_t *)&block_write_data[block_pos];
|
||||||
|
host_arm_NOP(block);
|
||||||
|
host_arm_NOP(block);
|
||||||
|
host_arm_NOP(block);
|
||||||
|
host_arm_NOP(block);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
|
||||||
|
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||||
|
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||||
|
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||||
|
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||||
|
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
|
||||||
|
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
codeblock_t *block;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
|
||||||
|
block_current = 0;
|
||||||
|
block_pos = 0;
|
||||||
|
block = &codeblock[block_current];
|
||||||
|
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||||
|
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||||
|
block_write_data = block->data;
|
||||||
|
build_loadstore_routines(&codeblock[block_current]);
|
||||||
|
printf("block_pos=%i\n", block_pos);
|
||||||
|
|
||||||
|
codegen_fp_round = &block_write_data[block_pos];
|
||||||
|
build_fp_round_routine(&codeblock[block_current]);
|
||||||
|
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
codegen_gpf_rout = &block_write_data[block_pos];
|
||||||
|
host_arm_MOV_IMM(block, REG_R0, 0);
|
||||||
|
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||||
|
host_arm_call(block, x86gpf);
|
||||||
|
|
||||||
|
codegen_exit_rout = &block_write_data[block_pos];
|
||||||
|
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||||
|
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||||
|
|
||||||
|
block_write_data = NULL;
|
||||||
|
//fatal("block_pos=%i\n", block_pos);
|
||||||
|
asm("vmrs %0, fpscr\n"
|
||||||
|
: "=r" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
if ((cpu_state.old_fp_control >> 22) & 3)
|
||||||
|
fatal("VFP not in nearest rounding mode\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
if (mode < 0 || mode > 3)
|
||||||
|
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||||
|
cpu_state.new_fp_control = mode << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*R10 - cpu_state*/
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
block_pos = BLOCK_START;
|
||||||
|
|
||||||
|
/*Entry code*/
|
||||||
|
|
||||||
|
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
|
||||||
|
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||||
|
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state);
|
||||||
|
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||||
|
{
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
|
||||||
|
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||||
|
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||||
|
|
||||||
|
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
24
src/codegen_backend_arm.h
Normal file
24
src/codegen_backend_arm.h
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "codegen_backend_arm_defs.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 0x4000
|
||||||
|
#define BLOCK_MASK 0x3fff
|
||||||
|
#define BLOCK_START 0
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
#define BLOCK_MAX 0x3c0
|
||||||
|
|
||||||
|
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||||
|
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||||
|
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
|
||||||
|
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||||
|
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
|
||||||
|
void host_arm_call(codeblock_t *block, void *dst_addr);
|
||||||
|
void host_arm_nop(codeblock_t *block);
|
||||||
|
|
||||||
|
void codegen_alloc(codeblock_t *block, int size);
|
||||||
382
src/codegen_backend_arm64.c
Normal file
382
src/codegen_backend_arm64.c
Normal file
|
|
@ -0,0 +1,382 @@
|
||||||
|
#ifdef __aarch64__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_arm64_defs.h"
|
||||||
|
#include "codegen_backend_arm64_ops.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x87.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *codegen_mem_load_byte;
|
||||||
|
void *codegen_mem_load_word;
|
||||||
|
void *codegen_mem_load_long;
|
||||||
|
void *codegen_mem_load_quad;
|
||||||
|
void *codegen_mem_load_single;
|
||||||
|
void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
void *codegen_mem_store_byte;
|
||||||
|
void *codegen_mem_store_word;
|
||||||
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
|
void *codegen_mem_store_single;
|
||||||
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
void *codegen_fp_round;
|
||||||
|
void *codegen_fp_round_quad;
|
||||||
|
|
||||||
|
void *codegen_gpf_rout;
|
||||||
|
void *codegen_exit_rout;
|
||||||
|
|
||||||
|
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||||
|
{
|
||||||
|
REG_X19,
|
||||||
|
REG_X20,
|
||||||
|
REG_X21,
|
||||||
|
REG_X22,
|
||||||
|
REG_X23,
|
||||||
|
REG_X24,
|
||||||
|
REG_X25,
|
||||||
|
REG_X26,
|
||||||
|
REG_X27,
|
||||||
|
REG_X28
|
||||||
|
};
|
||||||
|
|
||||||
|
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
|
||||||
|
{
|
||||||
|
REG_V8,
|
||||||
|
REG_V9,
|
||||||
|
REG_V10,
|
||||||
|
REG_V11,
|
||||||
|
REG_V12,
|
||||||
|
REG_V13,
|
||||||
|
REG_V14,
|
||||||
|
REG_V15
|
||||||
|
};
|
||||||
|
|
||||||
|
static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint32_t *branch_offset;
|
||||||
|
uint32_t *misaligned_offset;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/*In - W0 = address
|
||||||
|
Out - W0 = data, W1 = abrt*/
|
||||||
|
/*MOV W1, W0, LSR #12
|
||||||
|
MOV X2, #readlookup2
|
||||||
|
LDR X1, [X2, X1, LSL #3]
|
||||||
|
CMP X1, #-1
|
||||||
|
BEQ +
|
||||||
|
LDRB W0, [X1, X0]
|
||||||
|
MOV W1, #0
|
||||||
|
RET
|
||||||
|
* STP X29, X30, [SP, #-16]
|
||||||
|
BL readmembl
|
||||||
|
LDRB R1, cpu_state.abrt
|
||||||
|
LDP X29, X30, [SP, #-16]
|
||||||
|
RET
|
||||||
|
*/
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
|
||||||
|
host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2);
|
||||||
|
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_arm64_TST_IMM(block, REG_W0, size-1);
|
||||||
|
misaligned_offset = host_arm64_BNE_(block);
|
||||||
|
}
|
||||||
|
host_arm64_CMPX_IMM(block, REG_X1, -1);
|
||||||
|
branch_offset = host_arm64_BEQ_(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0);
|
||||||
|
host_arm64_MOVZ_IMM(block, REG_W1, 0);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||||
|
if (size != 1)
|
||||||
|
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||||
|
if (size == 1)
|
||||||
|
host_arm64_call(block, (void *)readmembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_arm64_call(block, (void *)readmemwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_arm64_call(block, (void *)readmemll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm64_call(block, (void *)readmemql);
|
||||||
|
else
|
||||||
|
fatal("build_load_routine - unknown size %i\n", size);
|
||||||
|
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint32_t *branch_offset;
|
||||||
|
uint32_t *misaligned_offset;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/*In - R0 = address, R1 = data
|
||||||
|
Out - R1 = abrt*/
|
||||||
|
/*MOV W2, W0, LSR #12
|
||||||
|
MOV X3, #writelookup2
|
||||||
|
LDR X2, [X3, X2, LSL #3]
|
||||||
|
CMP X2, #-1
|
||||||
|
BEQ +
|
||||||
|
STRB W1, [X2, X0]
|
||||||
|
MOV W1, #0
|
||||||
|
RET
|
||||||
|
* STP X29, X30, [SP, #-16]
|
||||||
|
BL writemembl
|
||||||
|
LDRB R1, cpu_state.abrt
|
||||||
|
LDP X29, X30, [SP, #-16]
|
||||||
|
RET
|
||||||
|
*/
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
|
||||||
|
host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2);
|
||||||
|
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_arm64_TST_IMM(block, REG_W0, size-1);
|
||||||
|
misaligned_offset = host_arm64_BNE_(block);
|
||||||
|
}
|
||||||
|
host_arm64_CMPX_IMM(block, REG_X2, -1);
|
||||||
|
branch_offset = host_arm64_BEQ_(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||||
|
host_arm64_MOVZ_IMM(block, REG_X1, 0);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||||
|
if (size != 1)
|
||||||
|
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
|
||||||
|
if (size == 1)
|
||||||
|
host_arm64_call(block, (void *)writemembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_arm64_call(block, (void *)writememwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_arm64_call(block, (void *)writememll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_arm64_call(block, (void *)writememql);
|
||||||
|
else
|
||||||
|
fatal("build_store_routine - unknown size %i\n", size);
|
||||||
|
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_loadstore_routines(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 1, 0);
|
||||||
|
codegen_mem_load_word = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 2, 0);
|
||||||
|
codegen_mem_load_long = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 4, 0);
|
||||||
|
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 8, 0);
|
||||||
|
codegen_mem_load_single = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 4, 1);
|
||||||
|
codegen_mem_load_double = &block_write_data[block_pos];
|
||||||
|
build_load_routine(block, 8, 1);
|
||||||
|
|
||||||
|
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 1, 0);
|
||||||
|
codegen_mem_store_word = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 2, 0);
|
||||||
|
codegen_mem_store_long = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
|
codegen_mem_store_single = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 4, 1);
|
||||||
|
codegen_mem_store_double = &block_write_data[block_pos];
|
||||||
|
build_store_routine(block, 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_fp_round_routine(codeblock_t *block, int is_quad)
|
||||||
|
{
|
||||||
|
uint64_t *jump_table;
|
||||||
|
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm64_ADR(block, REG_TEMP2, 12);
|
||||||
|
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
|
||||||
|
host_arm64_BR(block, REG_TEMP2);
|
||||||
|
|
||||||
|
jump_table = (uint64_t *)&block_write_data[block_pos];
|
||||||
|
block_pos += 4*8;
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
codeblock_t *block;
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
{
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
|
||||||
|
block_current = 0;
|
||||||
|
block_pos = 0;
|
||||||
|
block = &codeblock[block_current];
|
||||||
|
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||||
|
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||||
|
block_write_data = block->data;
|
||||||
|
build_loadstore_routines(block);
|
||||||
|
|
||||||
|
codegen_fp_round = &block_write_data[block_pos];
|
||||||
|
build_fp_round_routine(block, 0);
|
||||||
|
codegen_fp_round_quad = &block_write_data[block_pos];
|
||||||
|
build_fp_round_routine(block, 1);
|
||||||
|
|
||||||
|
codegen_alloc(block, 80);
|
||||||
|
codegen_gpf_rout = &block_write_data[block_pos];
|
||||||
|
host_arm64_mov_imm(block, REG_ARG0, 0);
|
||||||
|
host_arm64_mov_imm(block, REG_ARG1, 0);
|
||||||
|
host_arm64_call(block, (void *)x86gpf);
|
||||||
|
|
||||||
|
codegen_exit_rout = &block_write_data[block_pos];
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
block_write_data = NULL;
|
||||||
|
|
||||||
|
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||||
|
|
||||||
|
asm("mrs %0, fpcr\n"
|
||||||
|
: "=r" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
if (mode < 0 || mode > 3)
|
||||||
|
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||||
|
cpu_state.new_fp_control = mode << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*R10 - cpu_state*/
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
block_pos = BLOCK_START;
|
||||||
|
|
||||||
|
/*Entry code*/
|
||||||
|
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16);
|
||||||
|
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64);
|
||||||
|
|
||||||
|
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state);
|
||||||
|
|
||||||
|
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||||
|
{
|
||||||
|
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
|
||||||
|
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
|
||||||
|
host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
|
||||||
|
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
31
src/codegen_backend_arm64.h
Normal file
31
src/codegen_backend_arm64.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#include "codegen_backend_arm64_defs.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 0x4000
|
||||||
|
#define BLOCK_MASK 0x3fff
|
||||||
|
#define BLOCK_START 0
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
#define BLOCK_MAX 0x3c0
|
||||||
|
|
||||||
|
|
||||||
|
void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
||||||
|
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
|
||||||
|
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||||
|
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
|
||||||
|
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
|
||||||
|
void host_arm64_NOP(codeblock_t *block);
|
||||||
|
void host_arm64_RET(codeblock_t *block, int reg);
|
||||||
|
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||||
|
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_arm64_call(codeblock_t *block, void *dst_addr);
|
||||||
|
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
uint32_t host_arm64_find_imm(uint32_t data);
|
||||||
135
src/codegen_backend_arm64_defs.h
Normal file
135
src/codegen_backend_arm64_defs.h
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
#define REG_W0 0
|
||||||
|
#define REG_W1 1
|
||||||
|
#define REG_W2 2
|
||||||
|
#define REG_W3 3
|
||||||
|
#define REG_W4 4
|
||||||
|
#define REG_W5 5
|
||||||
|
#define REG_W6 6
|
||||||
|
#define REG_W7 7
|
||||||
|
#define REG_W8 8
|
||||||
|
#define REG_W9 9
|
||||||
|
#define REG_W10 10
|
||||||
|
#define REG_W11 11
|
||||||
|
#define REG_W12 12
|
||||||
|
#define REG_W13 13
|
||||||
|
#define REG_W14 14
|
||||||
|
#define REG_W15 15
|
||||||
|
#define REG_W16 16
|
||||||
|
#define REG_W17 17
|
||||||
|
#define REG_W18 18
|
||||||
|
#define REG_W19 19
|
||||||
|
#define REG_W20 20
|
||||||
|
#define REG_W21 21
|
||||||
|
#define REG_W22 22
|
||||||
|
#define REG_W23 23
|
||||||
|
#define REG_W24 24
|
||||||
|
#define REG_W25 25
|
||||||
|
#define REG_W26 26
|
||||||
|
#define REG_W27 27
|
||||||
|
#define REG_W28 28
|
||||||
|
#define REG_W29 29
|
||||||
|
#define REG_W30 30
|
||||||
|
#define REG_WZR 31
|
||||||
|
|
||||||
|
#define REG_X0 0
|
||||||
|
#define REG_X1 1
|
||||||
|
#define REG_X2 2
|
||||||
|
#define REG_X3 3
|
||||||
|
#define REG_X4 4
|
||||||
|
#define REG_X5 5
|
||||||
|
#define REG_X6 6
|
||||||
|
#define REG_X7 7
|
||||||
|
#define REG_X8 8
|
||||||
|
#define REG_X9 9
|
||||||
|
#define REG_X10 10
|
||||||
|
#define REG_X11 11
|
||||||
|
#define REG_X12 12
|
||||||
|
#define REG_X13 13
|
||||||
|
#define REG_X14 14
|
||||||
|
#define REG_X15 15
|
||||||
|
#define REG_X16 16
|
||||||
|
#define REG_X17 17
|
||||||
|
#define REG_X18 18
|
||||||
|
#define REG_X19 19
|
||||||
|
#define REG_X20 20
|
||||||
|
#define REG_X21 21
|
||||||
|
#define REG_X22 22
|
||||||
|
#define REG_X23 23
|
||||||
|
#define REG_X24 24
|
||||||
|
#define REG_X25 25
|
||||||
|
#define REG_X26 26
|
||||||
|
#define REG_X27 27
|
||||||
|
#define REG_X28 28
|
||||||
|
#define REG_X29 29
|
||||||
|
#define REG_X30 30
|
||||||
|
#define REG_XZR 31
|
||||||
|
|
||||||
|
#define REG_V0 0
|
||||||
|
#define REG_V1 1
|
||||||
|
#define REG_V2 2
|
||||||
|
#define REG_V3 3
|
||||||
|
#define REG_V4 4
|
||||||
|
#define REG_V5 5
|
||||||
|
#define REG_V6 6
|
||||||
|
#define REG_V7 7
|
||||||
|
#define REG_V8 8
|
||||||
|
#define REG_V9 9
|
||||||
|
#define REG_V10 10
|
||||||
|
#define REG_V11 11
|
||||||
|
#define REG_V12 12
|
||||||
|
#define REG_V13 13
|
||||||
|
#define REG_V14 14
|
||||||
|
#define REG_V15 15
|
||||||
|
#define REG_V16 16
|
||||||
|
#define REG_V17 17
|
||||||
|
#define REG_V18 18
|
||||||
|
#define REG_V19 19
|
||||||
|
#define REG_V20 20
|
||||||
|
#define REG_V21 21
|
||||||
|
#define REG_V22 22
|
||||||
|
#define REG_V23 23
|
||||||
|
#define REG_V24 24
|
||||||
|
#define REG_V25 25
|
||||||
|
#define REG_V26 26
|
||||||
|
#define REG_V27 27
|
||||||
|
#define REG_V28 28
|
||||||
|
#define REG_V29 29
|
||||||
|
#define REG_V30 30
|
||||||
|
#define REG_V31 31
|
||||||
|
|
||||||
|
#define REG_XSP 31
|
||||||
|
|
||||||
|
#define REG_ARG0 REG_X0
|
||||||
|
#define REG_ARG1 REG_X1
|
||||||
|
#define REG_ARG2 REG_X2
|
||||||
|
#define REG_ARG3 REG_X3
|
||||||
|
|
||||||
|
#define REG_CPUSTATE REG_X29
|
||||||
|
|
||||||
|
#define REG_TEMP REG_X7
|
||||||
|
#define REG_TEMP2 REG_X6
|
||||||
|
|
||||||
|
#define REG_V_TEMP REG_V0
|
||||||
|
|
||||||
|
#define CODEGEN_HOST_REGS 10
|
||||||
|
#define CODEGEN_HOST_FP_REGS 8
|
||||||
|
|
||||||
|
extern void *codegen_mem_load_byte;
|
||||||
|
extern void *codegen_mem_load_word;
|
||||||
|
extern void *codegen_mem_load_long;
|
||||||
|
extern void *codegen_mem_load_quad;
|
||||||
|
extern void *codegen_mem_load_single;
|
||||||
|
extern void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
extern void *codegen_mem_store_byte;
|
||||||
|
extern void *codegen_mem_store_word;
|
||||||
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
|
extern void *codegen_mem_store_single;
|
||||||
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
extern void *codegen_fp_round;
|
||||||
|
extern void *codegen_fp_round_quad;
|
||||||
|
|
||||||
|
extern void *codegen_gpf_rout;
|
||||||
|
extern void *codegen_exit_rout;
|
||||||
1330
src/codegen_backend_arm64_imm.c
Normal file
1330
src/codegen_backend_arm64_imm.c
Normal file
File diff suppressed because it is too large
Load diff
1382
src/codegen_backend_arm64_ops.c
Normal file
1382
src/codegen_backend_arm64_ops.c
Normal file
File diff suppressed because it is too large
Load diff
264
src/codegen_backend_arm64_ops.h
Normal file
264
src/codegen_backend_arm64_ops.h
Normal file
|
|
@ -0,0 +1,264 @@
|
||||||
|
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset);
|
||||||
|
|
||||||
|
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
|
||||||
|
|
||||||
|
void host_arm64_B(codeblock_t *block, void *dest);
|
||||||
|
|
||||||
|
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||||
|
|
||||||
|
void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
||||||
|
|
||||||
|
void host_arm64_BEQ(codeblock_t *block, void *dest);
|
||||||
|
|
||||||
|
uint32_t *host_arm64_BCC_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BCS_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BEQ_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BGE_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BGT_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BHI_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BLE_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BLS_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BLT_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BMI_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BNE_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BPL_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BVC_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm64_BVS_(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest);
|
||||||
|
|
||||||
|
void host_arm64_BR(codeblock_t *block, int addr_reg);
|
||||||
|
|
||||||
|
void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
|
||||||
|
|
||||||
|
void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
#define host_arm64_CMP_REG(block, src_n_reg, src_m_reg) host_arm64_CMP_REG_LSL(block, src_n_reg, src_m_reg, 0)
|
||||||
|
void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element);
|
||||||
|
|
||||||
|
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
|
||||||
|
void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
|
||||||
|
|
||||||
|
void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data);
|
||||||
|
void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_NOP(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_RET(codeblock_t *block, int reg);
|
||||||
|
|
||||||
|
void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
|
||||||
|
|
||||||
|
void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg);
|
||||||
|
|
||||||
|
void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||||
|
|
||||||
|
void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||||
|
void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||||
|
void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit);
|
||||||
|
|
||||||
|
#define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data)
|
||||||
|
|
||||||
|
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||||
|
|
||||||
|
void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||||
|
|
||||||
|
void host_arm64_call(codeblock_t *block, void *dst_addr);
|
||||||
|
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr);
|
||||||
|
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
|
||||||
|
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
|
||||||
|
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
|
||||||
|
#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1))
|
||||||
|
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
|
||||||
|
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7))
|
||||||
|
|
||||||
|
|
||||||
|
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
|
||||||
|
|
||||||
|
void codegen_alloc(codeblock_t *block, int size);
|
||||||
3367
src/codegen_backend_arm64_uops.c
Normal file
3367
src/codegen_backend_arm64_uops.c
Normal file
File diff suppressed because it is too large
Load diff
89
src/codegen_backend_arm_defs.h
Normal file
89
src/codegen_backend_arm_defs.h
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#define REG_R0 0
|
||||||
|
#define REG_R1 1
|
||||||
|
#define REG_R2 2
|
||||||
|
#define REG_R3 3
|
||||||
|
#define REG_R4 4
|
||||||
|
#define REG_R5 5
|
||||||
|
#define REG_R6 6
|
||||||
|
#define REG_R7 7
|
||||||
|
#define REG_R8 8
|
||||||
|
#define REG_R9 9
|
||||||
|
#define REG_R10 10
|
||||||
|
#define REG_R11 11
|
||||||
|
#define REG_R12 12
|
||||||
|
#define REG_HOST_SP 13
|
||||||
|
#define REG_LR 14
|
||||||
|
#define REG_PC 15
|
||||||
|
|
||||||
|
#define REG_ARG0 REG_R0
|
||||||
|
#define REG_ARG1 REG_R1
|
||||||
|
#define REG_ARG2 REG_R2
|
||||||
|
#define REG_ARG3 REG_R3
|
||||||
|
|
||||||
|
#define REG_CPUSTATE REG_R10
|
||||||
|
|
||||||
|
#define REG_TEMP REG_R3
|
||||||
|
#define REG_TEMP2 REG_R2
|
||||||
|
|
||||||
|
#define REG_D0 0
|
||||||
|
#define REG_D1 1
|
||||||
|
#define REG_D2 2
|
||||||
|
#define REG_D3 3
|
||||||
|
#define REG_D4 4
|
||||||
|
#define REG_D5 5
|
||||||
|
#define REG_D6 6
|
||||||
|
#define REG_D7 7
|
||||||
|
#define REG_D8 8
|
||||||
|
#define REG_D9 9
|
||||||
|
#define REG_D10 10
|
||||||
|
#define REG_D11 11
|
||||||
|
#define REG_D12 12
|
||||||
|
#define REG_D13 13
|
||||||
|
#define REG_D14 14
|
||||||
|
#define REG_D15 15
|
||||||
|
|
||||||
|
#define REG_D_TEMP REG_D0
|
||||||
|
#define REG_Q_TEMP REG_D0
|
||||||
|
#define REG_Q_TEMP_2 REG_D2
|
||||||
|
|
||||||
|
#define REG_MASK_R0 (1 << REG_R0)
|
||||||
|
#define REG_MASK_R1 (1 << REG_R1)
|
||||||
|
#define REG_MASK_R2 (1 << REG_R2)
|
||||||
|
#define REG_MASK_R3 (1 << REG_R3)
|
||||||
|
#define REG_MASK_R4 (1 << REG_R4)
|
||||||
|
#define REG_MASK_R5 (1 << REG_R5)
|
||||||
|
#define REG_MASK_R6 (1 << REG_R6)
|
||||||
|
#define REG_MASK_R7 (1 << REG_R7)
|
||||||
|
#define REG_MASK_R8 (1 << REG_R8)
|
||||||
|
#define REG_MASK_R9 (1 << REG_R9)
|
||||||
|
#define REG_MASK_R10 (1 << REG_R10)
|
||||||
|
#define REG_MASK_R11 (1 << REG_R11)
|
||||||
|
#define REG_MASK_R12 (1 << REG_R12)
|
||||||
|
#define REG_MASK_SP (1 << REG_HOST_SP)
|
||||||
|
#define REG_MASK_LR (1 << REG_LR)
|
||||||
|
#define REG_MASK_PC (1 << REG_PC)
|
||||||
|
|
||||||
|
#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \
|
||||||
|
REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
|
||||||
|
|
||||||
|
#define CODEGEN_HOST_REGS 7
|
||||||
|
#define CODEGEN_HOST_FP_REGS 8
|
||||||
|
|
||||||
|
extern void *codegen_mem_load_byte;
|
||||||
|
extern void *codegen_mem_load_word;
|
||||||
|
extern void *codegen_mem_load_long;
|
||||||
|
extern void *codegen_mem_load_quad;
|
||||||
|
extern void *codegen_mem_load_single;
|
||||||
|
extern void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
extern void *codegen_mem_store_byte;
|
||||||
|
extern void *codegen_mem_store_word;
|
||||||
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
|
extern void *codegen_mem_store_single;
|
||||||
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
extern void *codegen_fp_round;
|
||||||
|
|
||||||
|
extern void *codegen_gpf_rout;
|
||||||
|
extern void *codegen_exit_rout;
|
||||||
1272
src/codegen_backend_arm_ops.c
Normal file
1272
src/codegen_backend_arm_ops.c
Normal file
File diff suppressed because it is too large
Load diff
252
src/codegen_backend_arm_ops.h
Normal file
252
src/codegen_backend_arm_ops.h
Normal file
|
|
@ -0,0 +1,252 @@
|
||||||
|
#define COND_SHIFT 28
|
||||||
|
#define COND_EQ (0x0 << COND_SHIFT)
|
||||||
|
#define COND_NE (0x1 << COND_SHIFT)
|
||||||
|
#define COND_CS (0x2 << COND_SHIFT)
|
||||||
|
#define COND_CC (0x3 << COND_SHIFT)
|
||||||
|
#define COND_MI (0x4 << COND_SHIFT)
|
||||||
|
#define COND_PL (0x5 << COND_SHIFT)
|
||||||
|
#define COND_VS (0x6 << COND_SHIFT)
|
||||||
|
#define COND_VC (0x7 << COND_SHIFT)
|
||||||
|
#define COND_HI (0x8 << COND_SHIFT)
|
||||||
|
#define COND_LS (0x9 << COND_SHIFT)
|
||||||
|
#define COND_GE (0xa << COND_SHIFT)
|
||||||
|
#define COND_LT (0xb << COND_SHIFT)
|
||||||
|
#define COND_GT (0xc << COND_SHIFT)
|
||||||
|
#define COND_LE (0xd << COND_SHIFT)
|
||||||
|
#define COND_AL (0xe << COND_SHIFT)
|
||||||
|
|
||||||
|
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
#define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0)
|
||||||
|
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_B(codeblock_t *block, uintptr_t dest_addr);
|
||||||
|
|
||||||
|
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||||
|
|
||||||
|
void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr);
|
||||||
|
void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr);
|
||||||
|
void host_arm_BLX(codeblock_t *block, int addr_reg);
|
||||||
|
|
||||||
|
uint32_t *host_arm_BCC_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BCS_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BEQ_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BGE_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BGT_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BHI_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BLE_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BLS_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BLT_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BMI_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BNE_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BPL_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BVC_(codeblock_t *block);
|
||||||
|
uint32_t *host_arm_BVS_(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr);
|
||||||
|
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr);
|
||||||
|
|
||||||
|
void host_arm_BX(codeblock_t *block, int addr_reg);
|
||||||
|
|
||||||
|
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm);
|
||||||
|
#define host_arm_CMP_REG(block, src_reg_n, src_reg_m) host_arm_CMP_REG_LSL(block, src_reg_n, src_reg_m, 0)
|
||||||
|
void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||||
|
|
||||||
|
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||||
|
void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||||
|
#define host_arm_LDR_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDR_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
|
||||||
|
void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm_LDRB_ABS(codeblock_t *block, int dst, void *p);
|
||||||
|
void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||||
|
#define host_arm_LDRB_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDRB_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
|
||||||
|
void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||||
|
void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
|
||||||
|
#define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0)
|
||||||
|
void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
|
||||||
|
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
|
||||||
|
void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
|
||||||
|
void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
|
||||||
|
void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
|
||||||
|
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
|
||||||
|
|
||||||
|
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||||
|
|
||||||
|
#define host_arm_NOP(block) host_arm_MOV_REG(block, REG_R0, REG_R0)
|
||||||
|
|
||||||
|
void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm)
|
||||||
|
#define host_arm_ORR_REG_LSL(block, dst_reg, src_reg_a, src_reg_b, shift) host_arm_ORR_REG_LSL_cond(block, COND_AL, dst_reg, src_reg_a, src_reg_b, shift)
|
||||||
|
|
||||||
|
#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm)
|
||||||
|
#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm)
|
||||||
|
#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm)
|
||||||
|
|
||||||
|
void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||||
|
|
||||||
|
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||||
|
void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||||
|
#define host_arm_STR_REG(block, src_reg, addr_reg, offset_reg) host_arm_STR_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
|
||||||
|
void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||||
|
#define host_arm_STRB_REG(block, src_reg, addr_reg, offset_reg) host_arm_STRB_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
|
||||||
|
void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm_STRH_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||||
|
void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg);
|
||||||
|
|
||||||
|
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||||
|
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||||
|
|
||||||
|
void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
|
||||||
|
void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
|
||||||
|
|
||||||
|
void host_arm_TST_IMM(codeblock_t *block, int src_reg1, uint32_t imm);
|
||||||
|
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2);
|
||||||
|
|
||||||
|
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
|
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
|
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
|
||||||
|
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
|
||||||
|
|
||||||
|
void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm);
|
||||||
|
void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg);
|
||||||
|
void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high);
|
||||||
|
void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VMRS_APSR(codeblock_t *block);
|
||||||
|
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHR_D_S16(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHR_D_S32(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHR_D_U16(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||||
|
void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||||
|
void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VSUB_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
|
|
||||||
|
void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg);
|
||||||
|
void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg);
|
||||||
|
void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg);
|
||||||
3499
src/codegen_backend_arm_uops.c
Normal file
3499
src/codegen_backend_arm_uops.c
Normal file
File diff suppressed because it is too large
Load diff
376
src/codegen_backend_x86-64.c
Normal file
376
src/codegen_backend_x86-64.c
Normal file
|
|
@ -0,0 +1,376 @@
|
||||||
|
#ifdef __amd64__
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86-64_defs.h"
|
||||||
|
#include "codegen_backend_x86-64_ops.h"
|
||||||
|
#include "codegen_backend_x86-64_ops_sse.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *codegen_mem_load_byte;
|
||||||
|
void *codegen_mem_load_word;
|
||||||
|
void *codegen_mem_load_long;
|
||||||
|
void *codegen_mem_load_quad;
|
||||||
|
void *codegen_mem_load_single;
|
||||||
|
void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
void *codegen_mem_store_byte;
|
||||||
|
void *codegen_mem_store_word;
|
||||||
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
|
void *codegen_mem_store_single;
|
||||||
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
void *codegen_gpf_rout;
|
||||||
|
void *codegen_exit_rout;
|
||||||
|
|
||||||
|
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||||
|
{
|
||||||
|
REG_EAX,
|
||||||
|
REG_EBX,
|
||||||
|
REG_EDX
|
||||||
|
};
|
||||||
|
|
||||||
|
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
|
||||||
|
{
|
||||||
|
REG_XMM0,
|
||||||
|
REG_XMM1,
|
||||||
|
REG_XMM2,
|
||||||
|
REG_XMM3,
|
||||||
|
REG_XMM4,
|
||||||
|
REG_XMM5,
|
||||||
|
REG_XMM6
|
||||||
|
};
|
||||||
|
|
||||||
|
static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
uint8_t *misaligned_offset;
|
||||||
|
|
||||||
|
/*In - ESI = address
|
||||||
|
Out - ECX = data, ESI = abrt*/
|
||||||
|
/*MOV ECX, ESI
|
||||||
|
SHR ESI, 12
|
||||||
|
MOV RSI, [readlookup2+ESI*4]
|
||||||
|
CMP ESI, -1
|
||||||
|
JNZ +
|
||||||
|
MOVZX ECX, B[RSI+RCX]
|
||||||
|
XOR ESI,ESI
|
||||||
|
RET
|
||||||
|
* PUSH EAX
|
||||||
|
PUSH EDX
|
||||||
|
PUSH ECX
|
||||||
|
CALL readmembl
|
||||||
|
POP ECX
|
||||||
|
POP EDX
|
||||||
|
POP EAX
|
||||||
|
MOVZX ECX, AL
|
||||||
|
RET
|
||||||
|
*/
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
|
||||||
|
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||||
|
host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2);
|
||||||
|
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
|
||||||
|
misaligned_offset = host_x86_JNZ_short(block);
|
||||||
|
}
|
||||||
|
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
|
||||||
|
branch_offset = host_x86_JZ_short(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
|
||||||
|
else
|
||||||
|
fatal("build_load_routine: size=%i\n", size);
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
|
||||||
|
host_x86_RET(block);
|
||||||
|
|
||||||
|
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||||
|
if (size != 1)
|
||||||
|
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||||
|
host_x86_PUSH(block, REG_RAX);
|
||||||
|
host_x86_PUSH(block, REG_RDX);
|
||||||
|
#if WIN64
|
||||||
|
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
|
||||||
|
//host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data);
|
||||||
|
#else
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX);
|
||||||
|
#endif
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, (void *)readmembl);
|
||||||
|
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
|
||||||
|
}
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, (void *)readmemwl);
|
||||||
|
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
|
||||||
|
}
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, (void *)readmemll);
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
|
||||||
|
}
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, (void *)readmemll);
|
||||||
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
||||||
|
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
|
||||||
|
}
|
||||||
|
else if (size == 8)
|
||||||
|
{
|
||||||
|
host_x86_CALL(block, (void *)readmemql);
|
||||||
|
host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX);
|
||||||
|
}
|
||||||
|
#if WIN64
|
||||||
|
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
|
||||||
|
#endif
|
||||||
|
host_x86_POP(block, REG_RDX);
|
||||||
|
host_x86_POP(block, REG_RAX);
|
||||||
|
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||||
|
host_x86_RET(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
uint8_t *misaligned_offset;
|
||||||
|
|
||||||
|
/*In - ECX = data, ESI = address
|
||||||
|
Out - ESI = abrt
|
||||||
|
Corrupts EDI*/
|
||||||
|
/*MOV EDI, ESI
|
||||||
|
SHR ESI, 12
|
||||||
|
MOV ESI, [writelookup2+ESI*4]
|
||||||
|
CMP ESI, -1
|
||||||
|
JNZ +
|
||||||
|
MOV [RSI+RDI], ECX
|
||||||
|
XOR ESI,ESI
|
||||||
|
RET
|
||||||
|
* PUSH EAX
|
||||||
|
PUSH EDX
|
||||||
|
PUSH ECX
|
||||||
|
CALL writemembl
|
||||||
|
POP ECX
|
||||||
|
POP EDX
|
||||||
|
POP EAX
|
||||||
|
MOVZX ECX, AL
|
||||||
|
RET
|
||||||
|
*/
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
|
||||||
|
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||||
|
host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2);
|
||||||
|
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
|
||||||
|
misaligned_offset = host_x86_JNZ_short(block);
|
||||||
|
}
|
||||||
|
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
|
||||||
|
branch_offset = host_x86_JZ_short(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
|
||||||
|
else
|
||||||
|
fatal("build_store_routine: size=%i\n", size);
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
|
||||||
|
host_x86_RET(block);
|
||||||
|
|
||||||
|
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||||
|
if (size != 1)
|
||||||
|
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||||
|
host_x86_PUSH(block, REG_RAX);
|
||||||
|
host_x86_PUSH(block, REG_RDX);
|
||||||
|
#if WIN64
|
||||||
|
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28);
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data
|
||||||
|
else
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address
|
||||||
|
#else
|
||||||
|
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8);
|
||||||
|
//host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); //data
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); //data
|
||||||
|
else
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data
|
||||||
|
#endif
|
||||||
|
if (size == 1)
|
||||||
|
host_x86_CALL(block, (void *)writemembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_x86_CALL(block, (void *)writememwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_x86_CALL(block, (void *)writememll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_CALL(block, (void *)writememql);
|
||||||
|
#if WIN64
|
||||||
|
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28);
|
||||||
|
#else
|
||||||
|
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8);
|
||||||
|
#endif
|
||||||
|
host_x86_POP(block, REG_RDX);
|
||||||
|
host_x86_POP(block, REG_RAX);
|
||||||
|
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||||
|
host_x86_RET(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_loadstore_routines(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 1, 0);
|
||||||
|
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 2, 0);
|
||||||
|
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 4, 0);
|
||||||
|
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 8, 0);
|
||||||
|
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 4, 1);
|
||||||
|
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 8, 1);
|
||||||
|
|
||||||
|
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 1, 0);
|
||||||
|
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 2, 0);
|
||||||
|
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
|
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 4, 1);
|
||||||
|
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
codeblock_t *block;
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
|
||||||
|
block_current = 0;
|
||||||
|
block_pos = 0;
|
||||||
|
block = &codeblock[block_current];
|
||||||
|
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||||
|
codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block);
|
||||||
|
block_write_data = codeblock[block_current].data;
|
||||||
|
build_loadstore_routines(&codeblock[block_current]);
|
||||||
|
|
||||||
|
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
|
||||||
|
#if WIN64
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX);
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX);
|
||||||
|
#else
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI);
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
|
||||||
|
#endif
|
||||||
|
host_x86_CALL(block, (uintptr_t)x86gpf);
|
||||||
|
codegen_exit_rout = &codeblock[block_current].data[block_pos];
|
||||||
|
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
|
||||||
|
host_x86_POP(block, REG_R15);
|
||||||
|
host_x86_POP(block, REG_R14);
|
||||||
|
host_x86_POP(block, REG_R13);
|
||||||
|
host_x86_POP(block, REG_R12);
|
||||||
|
host_x86_POP(block, REG_RDI);
|
||||||
|
host_x86_POP(block, REG_RSI);
|
||||||
|
host_x86_POP(block, REG_RBP);
|
||||||
|
host_x86_POP(block, REG_RDX);
|
||||||
|
host_x86_RET(block);
|
||||||
|
|
||||||
|
block_write_data = NULL;
|
||||||
|
|
||||||
|
asm(
|
||||||
|
"stmxcsr %0\n"
|
||||||
|
: "=m" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
block_pos = BLOCK_START; /*Entry code*/
|
||||||
|
host_x86_PUSH(block, REG_RBX);
|
||||||
|
host_x86_PUSH(block, REG_RBP);
|
||||||
|
host_x86_PUSH(block, REG_RSI);
|
||||||
|
host_x86_PUSH(block, REG_RDI);
|
||||||
|
host_x86_PUSH(block, REG_R12);
|
||||||
|
host_x86_PUSH(block, REG_R13);
|
||||||
|
host_x86_PUSH(block, REG_R14);
|
||||||
|
host_x86_PUSH(block, REG_R15);
|
||||||
|
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38);
|
||||||
|
host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128);
|
||||||
|
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
|
||||||
|
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
|
||||||
|
host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
|
||||||
|
host_x86_POP(block, REG_R15);
|
||||||
|
host_x86_POP(block, REG_R14);
|
||||||
|
host_x86_POP(block, REG_R13);
|
||||||
|
host_x86_POP(block, REG_R12);
|
||||||
|
host_x86_POP(block, REG_RDI);
|
||||||
|
host_x86_POP(block, REG_RSI);
|
||||||
|
host_x86_POP(block, REG_RBP);
|
||||||
|
host_x86_POP(block, REG_RDX);
|
||||||
|
host_x86_RET(block);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
12
src/codegen_backend_x86-64.h
Normal file
12
src/codegen_backend_x86-64.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "codegen_backend_x86-64_defs.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 0x4000
|
||||||
|
#define BLOCK_MASK 0x3fff
|
||||||
|
#define BLOCK_START 0
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
#define BLOCK_MAX 0x3c0
|
||||||
65
src/codegen_backend_x86-64_defs.h
Normal file
65
src/codegen_backend_x86-64_defs.h
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#define REG_AX 0
|
||||||
|
#define REG_CX 1
|
||||||
|
#define REG_DX 2
|
||||||
|
#define REG_BX 3
|
||||||
|
#define REG_SP 4
|
||||||
|
#define REG_BP 5
|
||||||
|
#define REG_SI 6
|
||||||
|
#define REG_DI 7
|
||||||
|
|
||||||
|
#define REG_EAX 0
|
||||||
|
#define REG_ECX 1
|
||||||
|
#define REG_EDX 2
|
||||||
|
#define REG_EBX 3
|
||||||
|
#define REG_ESP 4
|
||||||
|
#define REG_EBP 5
|
||||||
|
#define REG_ESI 6
|
||||||
|
#define REG_EDI 7
|
||||||
|
|
||||||
|
#define REG_RAX 0
|
||||||
|
#define REG_RCX 1
|
||||||
|
#define REG_RDX 2
|
||||||
|
#define REG_RBX 3
|
||||||
|
#define REG_RSP 4
|
||||||
|
#define REG_RBP 5
|
||||||
|
#define REG_RSI 6
|
||||||
|
#define REG_RDI 7
|
||||||
|
#define REG_R8 8
|
||||||
|
#define REG_R9 9
|
||||||
|
#define REG_R10 10
|
||||||
|
#define REG_R11 11
|
||||||
|
#define REG_R12 12
|
||||||
|
#define REG_R13 13
|
||||||
|
#define REG_R14 14
|
||||||
|
#define REG_R15 15
|
||||||
|
|
||||||
|
#define REG_XMM0 0
|
||||||
|
#define REG_XMM1 1
|
||||||
|
#define REG_XMM2 2
|
||||||
|
#define REG_XMM3 3
|
||||||
|
#define REG_XMM4 4
|
||||||
|
#define REG_XMM5 5
|
||||||
|
#define REG_XMM6 6
|
||||||
|
#define REG_XMM7 7
|
||||||
|
|
||||||
|
#define REG_XMM_TEMP REG_XMM7
|
||||||
|
|
||||||
|
#define CODEGEN_HOST_REGS 3
|
||||||
|
#define CODEGEN_HOST_FP_REGS 7
|
||||||
|
|
||||||
|
extern void *codegen_mem_load_byte;
|
||||||
|
extern void *codegen_mem_load_word;
|
||||||
|
extern void *codegen_mem_load_long;
|
||||||
|
extern void *codegen_mem_load_quad;
|
||||||
|
extern void *codegen_mem_load_single;
|
||||||
|
extern void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
extern void *codegen_mem_store_byte;
|
||||||
|
extern void *codegen_mem_store_word;
|
||||||
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
|
extern void *codegen_mem_store_single;
|
||||||
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
extern void *codegen_gpf_rout;
|
||||||
|
extern void *codegen_exit_rout;
|
||||||
1729
src/codegen_backend_x86-64_ops.c
Normal file
1729
src/codegen_backend_x86-64_ops.c
Normal file
File diff suppressed because it is too large
Load diff
193
src/codegen_backend_x86-64_ops.h
Normal file
193
src/codegen_backend_x86-64_ops.h
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_CALL(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_x86_JMP(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
void host_x86_JNZ(codeblock_t *block, void *p);
|
||||||
|
void host_x86_JZ(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
||||||
|
uint8_t *host_x86_JS_short(codeblock_t *block);
|
||||||
|
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
||||||
|
|
||||||
|
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNBE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNL_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNLE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNO_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNS_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNZ_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JB_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JBE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JL_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JLE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JO_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JS_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_LAHF(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset);
|
||||||
|
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
|
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||||
|
|
||||||
|
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||||
|
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||||
|
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||||
|
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
|
||||||
|
void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale);
|
||||||
|
|
||||||
|
void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
|
||||||
|
void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
|
||||||
|
void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||||
|
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
|
||||||
|
void host_x86_NOP(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_POP(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PUSH(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_RET(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_ROL8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROL16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROL32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_ROR8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROR16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROR32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||||
|
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||||
|
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);
|
||||||
|
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
102
src/codegen_backend_x86-64_ops_helpers.h
Normal file
102
src/codegen_backend_x86-64_ops_helpers.h
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#define JMP_LEN_BYTES 5
|
||||||
|
|
||||||
|
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||||
|
{
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||||
|
// CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
block_write_data[block_pos++] = val;
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-2))
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
block_write_data[block_pos++] = vala;
|
||||||
|
block_write_data[block_pos++] = valb;
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-3))
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
block_write_data[block_pos++] = vala;
|
||||||
|
block_write_data[block_pos++] = valb;
|
||||||
|
block_write_data[block_pos++] = valc;
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-4))
|
||||||
|
{
|
||||||
|
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
block_write_data[block_pos++] = vala;
|
||||||
|
block_write_data[block_pos++] = valb;
|
||||||
|
block_write_data[block_pos++] = valc;
|
||||||
|
block_write_data[block_pos++] = vald;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-2))
|
||||||
|
{
|
||||||
|
fatal("codegen_addword over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
*(uint16_t *)&block_write_data[block_pos] = val;
|
||||||
|
block_pos += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-4))
|
||||||
|
{
|
||||||
|
fatal("codegen_addlong over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
*(uint32_t *)&block_write_data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-8))
|
||||||
|
{
|
||||||
|
fatal("codegen_addquad over! %i\n", block_pos);
|
||||||
|
CPU_BLOCK_END();
|
||||||
|
}
|
||||||
|
*(uint64_t *)&block_write_data[block_pos] = val;
|
||||||
|
block_pos += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_alloc_bytes(codeblock_t *block, int size)
|
||||||
|
{
|
||||||
|
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
|
||||||
|
{
|
||||||
|
/*Current block is full. Allocate a new block*/
|
||||||
|
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
|
||||||
|
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
|
||||||
|
|
||||||
|
/*Add a jump instruction to the new block*/
|
||||||
|
codegen_addbyte(block, 0xe9); /*JMP*/
|
||||||
|
codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]);
|
||||||
|
|
||||||
|
/*Set write address to start of new block*/
|
||||||
|
block_pos = 0;
|
||||||
|
block_write_data = new_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_imm8(uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
614
src/codegen_backend_x86-64_ops_sse.c
Normal file
614
src/codegen_backend_x86-64_ops_sse.c
Normal file
|
|
@ -0,0 +1,614 @@
|
||||||
|
#ifdef __amd64__
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86-64_defs.h"
|
||||||
|
#include "codegen_backend_x86-64_ops_sse.h"
|
||||||
|
#include "codegen_backend_x86-64_ops_helpers.h"
|
||||||
|
|
||||||
|
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/
|
||||||
|
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/
|
||||||
|
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
|
||||||
|
}
|
||||||
|
else if (offset < (1ull << 32))
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 7);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/
|
||||||
|
codegen_addlong(block, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fatal("host_x86_LDMXCSR - out of range %p\n", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (src_reg & 8)
|
||||||
|
fatal("host_x86_MOVQ_ABS_REG reg & 8\n");
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((uintptr_t)p >> 32)
|
||||||
|
fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p);
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/
|
||||||
|
codegen_addbyte(block, 0x25);
|
||||||
|
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
|
||||||
|
{
|
||||||
|
if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
|
||||||
|
fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n");
|
||||||
|
|
||||||
|
if (addr < 0x80 || addr >= 0xffffff80)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
|
||||||
|
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
|
||||||
|
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
|
||||||
|
codegen_addlong(block, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg)
|
||||||
|
{
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_RSP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/
|
||||||
|
codegen_addbyte2(block, 0x24, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (dst_reg & 8)
|
||||||
|
fatal("host_x86_MOVQ_REG_ABS reg & 8\n");
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((uintptr_t)p >> 32)
|
||||||
|
fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p);
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
|
||||||
|
codegen_addbyte(block, 0x25);
|
||||||
|
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
|
||||||
|
{
|
||||||
|
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
|
||||||
|
fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n");
|
||||||
|
|
||||||
|
if (addr < 0x80 || addr >= 0xffffff80)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
|
||||||
|
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
|
||||||
|
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
|
||||||
|
codegen_addlong(block, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/
|
||||||
|
codegen_addbyte2(block, 0x24, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/
|
||||||
|
codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/
|
||||||
|
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
|
||||||
|
codegen_addbyte(block, 0x88);
|
||||||
|
}
|
||||||
|
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
|
||||||
|
codegen_addbyte(block, 0x88);
|
||||||
|
}
|
||||||
|
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
|
||||||
|
codegen_addbyte(block, 0x88);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
|
||||||
|
codegen_addbyte(block, 0xee);
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
|
||||||
|
codegen_addbyte(block, 0xee);
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
|
||||||
|
codegen_addbyte(block, 0xee);
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
114
src/codegen_backend_x86-64_ops_sse.h
Normal file
114
src/codegen_backend_x86-64_ops_sse.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
#define CMPPS_EQ 0
|
||||||
|
#define CMPPS_NLT 5
|
||||||
|
#define CMPPS_NLE 6
|
||||||
|
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
|
||||||
|
|
||||||
|
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
|
||||||
|
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
|
||||||
|
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
|
||||||
|
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
|
||||||
|
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
3144
src/codegen_backend_x86-64_uops.c
Normal file
3144
src/codegen_backend_x86-64_uops.c
Normal file
File diff suppressed because it is too large
Load diff
366
src/codegen_backend_x86.c
Normal file
366
src/codegen_backend_x86.c
Normal file
|
|
@ -0,0 +1,366 @@
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86_defs.h"
|
||||||
|
#include "codegen_backend_x86_ops.h"
|
||||||
|
#include "codegen_backend_x86_ops_sse.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *codegen_mem_load_byte;
|
||||||
|
void *codegen_mem_load_word;
|
||||||
|
void *codegen_mem_load_long;
|
||||||
|
void *codegen_mem_load_quad;
|
||||||
|
void *codegen_mem_load_single;
|
||||||
|
void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
void *codegen_mem_store_byte;
|
||||||
|
void *codegen_mem_store_word;
|
||||||
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
|
void *codegen_mem_store_single;
|
||||||
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
void *codegen_gpf_rout;
|
||||||
|
void *codegen_exit_rout;
|
||||||
|
|
||||||
|
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||||
|
{
|
||||||
|
REG_EAX,
|
||||||
|
REG_EBX,
|
||||||
|
REG_EDX
|
||||||
|
};
|
||||||
|
|
||||||
|
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
|
||||||
|
{
|
||||||
|
REG_XMM0,
|
||||||
|
REG_XMM1,
|
||||||
|
REG_XMM2,
|
||||||
|
REG_XMM3,
|
||||||
|
REG_XMM4,
|
||||||
|
REG_XMM5
|
||||||
|
};
|
||||||
|
|
||||||
|
static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
uint8_t *misaligned_offset = NULL;
|
||||||
|
|
||||||
|
/*In - ESI = address
|
||||||
|
Out - ECX = data, ESI = abrt*/
|
||||||
|
/*MOV ECX, ESI
|
||||||
|
SHR ESI, 12
|
||||||
|
MOV ESI, [readlookup2+ESI*4]
|
||||||
|
CMP ESI, -1
|
||||||
|
JNZ +
|
||||||
|
MOVZX ECX, B[ESI+ECX]
|
||||||
|
XOR ESI,ESI
|
||||||
|
RET
|
||||||
|
* PUSH EAX
|
||||||
|
PUSH EDX
|
||||||
|
PUSH ECX
|
||||||
|
CALL readmembl
|
||||||
|
POP ECX
|
||||||
|
POP EDX
|
||||||
|
POP EAX
|
||||||
|
MOVZX ECX, AL
|
||||||
|
RET
|
||||||
|
*/
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
|
||||||
|
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||||
|
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
|
||||||
|
misaligned_offset = host_x86_JNZ_short(block);
|
||||||
|
}
|
||||||
|
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
|
||||||
|
branch_offset = host_x86_JZ_short(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
|
||||||
|
else
|
||||||
|
fatal("build_load_routine: size=%i\n", size);
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
|
||||||
|
host_x86_RET(block);
|
||||||
|
|
||||||
|
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||||
|
if (size != 1)
|
||||||
|
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||||
|
host_x86_PUSH(block, REG_EAX);
|
||||||
|
host_x86_PUSH(block, REG_EDX);
|
||||||
|
host_x86_PUSH(block, REG_ECX);
|
||||||
|
if (size == 1)
|
||||||
|
host_x86_CALL(block, (void *)readmembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_x86_CALL(block, (void *)readmemwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_x86_CALL(block, (void *)readmemll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_CALL(block, (void *)readmemql);
|
||||||
|
host_x86_POP(block, REG_ECX);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
{
|
||||||
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
||||||
|
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
|
||||||
|
}
|
||||||
|
else if (size == 8)
|
||||||
|
{
|
||||||
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
||||||
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX);
|
||||||
|
host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2);
|
||||||
|
}
|
||||||
|
host_x86_POP(block, REG_EDX);
|
||||||
|
host_x86_POP(block, REG_EAX);
|
||||||
|
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||||
|
host_x86_RET(block);
|
||||||
|
block_pos = (block_pos + 63) & ~63;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
uint8_t *misaligned_offset = NULL;
|
||||||
|
|
||||||
|
/*In - ECX = data, ESI = address
|
||||||
|
Out - ESI = abrt
|
||||||
|
Corrupts EDI*/
|
||||||
|
/*MOV EDI, ESI
|
||||||
|
SHR ESI, 12
|
||||||
|
MOV ESI, [writelookup2+ESI*4]
|
||||||
|
CMP ESI, -1
|
||||||
|
JNZ +
|
||||||
|
MOV [ESI+EDI], ECX
|
||||||
|
XOR ESI,ESI
|
||||||
|
RET
|
||||||
|
* PUSH EAX
|
||||||
|
PUSH EDX
|
||||||
|
PUSH ECX
|
||||||
|
CALL writemembl
|
||||||
|
POP ECX
|
||||||
|
POP EDX
|
||||||
|
POP EAX
|
||||||
|
MOVZX ECX, AL
|
||||||
|
RET
|
||||||
|
*/
|
||||||
|
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
|
||||||
|
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||||
|
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2);
|
||||||
|
if (size != 1)
|
||||||
|
{
|
||||||
|
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
|
||||||
|
misaligned_offset = host_x86_JNZ_short(block);
|
||||||
|
}
|
||||||
|
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
|
||||||
|
branch_offset = host_x86_JZ_short(block);
|
||||||
|
if (size == 1 && !is_float)
|
||||||
|
host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||||
|
else if (size == 2 && !is_float)
|
||||||
|
host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||||
|
else if (size == 4 && !is_float)
|
||||||
|
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||||
|
else if (size == 4 && is_float)
|
||||||
|
host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
|
||||||
|
else
|
||||||
|
fatal("build_store_routine: size=%i is_float=%i\n", size, is_float);
|
||||||
|
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
|
||||||
|
host_x86_RET(block);
|
||||||
|
|
||||||
|
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||||
|
if (size != 1)
|
||||||
|
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||||
|
if (size == 4 && is_float)
|
||||||
|
host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP);
|
||||||
|
host_x86_PUSH(block, REG_EAX);
|
||||||
|
host_x86_PUSH(block, REG_EDX);
|
||||||
|
host_x86_PUSH(block, REG_ECX);
|
||||||
|
if (size == 8)
|
||||||
|
{
|
||||||
|
host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP);
|
||||||
|
host_x86_SUB32_REG_IMM(block, REG_ESP, 8);
|
||||||
|
}
|
||||||
|
host_x86_PUSH(block, REG_EDI);
|
||||||
|
if (size == 1)
|
||||||
|
host_x86_CALL(block, (void *)writemembl);
|
||||||
|
else if (size == 2)
|
||||||
|
host_x86_CALL(block, (void *)writememwl);
|
||||||
|
else if (size == 4)
|
||||||
|
host_x86_CALL(block, (void *)writememll);
|
||||||
|
else if (size == 8)
|
||||||
|
host_x86_CALL(block, (void *)writememql);
|
||||||
|
host_x86_POP(block, REG_EDI);
|
||||||
|
if (size == 8)
|
||||||
|
host_x86_ADD32_REG_IMM(block, REG_ESP, 8);
|
||||||
|
host_x86_POP(block, REG_ECX);
|
||||||
|
host_x86_POP(block, REG_EDX);
|
||||||
|
host_x86_POP(block, REG_EAX);
|
||||||
|
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||||
|
host_x86_RET(block);
|
||||||
|
block_pos = (block_pos + 63) & ~63;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_loadstore_routines(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 1, 0);
|
||||||
|
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 2, 0);
|
||||||
|
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 4, 0);
|
||||||
|
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 8, 0);
|
||||||
|
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 4, 1);
|
||||||
|
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
|
||||||
|
build_load_routine(block, 8, 1);
|
||||||
|
|
||||||
|
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 1, 0);
|
||||||
|
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 2, 0);
|
||||||
|
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
|
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 4, 1);
|
||||||
|
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_init()
|
||||||
|
{
|
||||||
|
codeblock_t *block;
|
||||||
|
int c;
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void *start;
|
||||||
|
size_t len;
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
long pagemask = ~(pagesize - 1);
|
||||||
|
#endif
|
||||||
|
pclog("sizeof(codeblock_t)=%i\n", sizeof(codeblock_t));
|
||||||
|
pclog(" offsetof(codeblock_t, pc)=%i\n", offsetof(codeblock_t, pc));
|
||||||
|
pclog(" offsetof(codeblock_t, _cs)=%i\n", offsetof(codeblock_t, _cs));
|
||||||
|
pclog(" offsetof(codeblock_t, phys)=%i\n", offsetof(codeblock_t, phys));
|
||||||
|
pclog(" offsetof(codeblock_t, phys_2)=%i\n", offsetof(codeblock_t, phys_2));
|
||||||
|
pclog(" offsetof(codeblock_t, status)=%i\n", offsetof(codeblock_t, status));
|
||||||
|
pclog(" offsetof(codeblock_t, flags)=%i\n", offsetof(codeblock_t, flags));
|
||||||
|
pclog(" offsetof(codeblock_t, ins)=%i\n", offsetof(codeblock_t, ins));
|
||||||
|
pclog(" offsetof(codeblock_t, TOP)=%i\n", offsetof(codeblock_t, TOP));
|
||||||
|
pclog(" offsetof(codeblock_t, parent)=%i\n", offsetof(codeblock_t, parent));
|
||||||
|
pclog(" offsetof(codeblock_t, left)=%i\n", offsetof(codeblock_t, left));
|
||||||
|
pclog(" offsetof(codeblock_t, right)=%i\n", offsetof(codeblock_t, right));
|
||||||
|
pclog(" offsetof(codeblock_t, data)=%i\n", offsetof(codeblock_t, data));
|
||||||
|
pclog(" offsetof(codeblock_t, page_mask)=%i\n", offsetof(codeblock_t, page_mask));
|
||||||
|
pclog(" offsetof(codeblock_t, page_mask2)=%i\n", offsetof(codeblock_t, page_mask2));
|
||||||
|
pclog(" offsetof(codeblock_t, dirty_mask)=%i\n", offsetof(codeblock_t, dirty_mask));
|
||||||
|
pclog(" offsetof(codeblock_t, dirty_mask2)=%i\n", offsetof(codeblock_t, dirty_mask2));
|
||||||
|
pclog(" offsetof(codeblock_t, prev)=%i\n", offsetof(codeblock_t, prev));
|
||||||
|
pclog(" offsetof(codeblock_t, next)=%i\n", offsetof(codeblock_t, next));
|
||||||
|
pclog(" offsetof(codeblock_t, prev_2)=%i\n", offsetof(codeblock_t, prev_2));
|
||||||
|
pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2));
|
||||||
|
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||||
|
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||||
|
|
||||||
|
for (c = 0; c < BLOCK_SIZE; c++)
|
||||||
|
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||||
|
|
||||||
|
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||||
|
|
||||||
|
block_current = 0;
|
||||||
|
block_pos = 0;
|
||||||
|
block = &codeblock[block_current];
|
||||||
|
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||||
|
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||||
|
block_write_data = block->data;
|
||||||
|
build_loadstore_routines(block);
|
||||||
|
|
||||||
|
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
|
||||||
|
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0);
|
||||||
|
host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0);
|
||||||
|
host_x86_CALL(block, (void *)x86gpf);
|
||||||
|
codegen_exit_rout = &codeblock[block_current].data[block_pos];
|
||||||
|
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
|
||||||
|
host_x86_POP(block, REG_EDI);
|
||||||
|
host_x86_POP(block, REG_ESI);
|
||||||
|
host_x86_POP(block, REG_EBP);
|
||||||
|
host_x86_POP(block, REG_EDX);
|
||||||
|
host_x86_RET(block);
|
||||||
|
block_write_data = NULL;
|
||||||
|
|
||||||
|
cpu_state.old_fp_control = 0;
|
||||||
|
asm(
|
||||||
|
"fstcw %0\n"
|
||||||
|
"stmxcsr %1\n"
|
||||||
|
: "=m" (cpu_state.old_fp_control2),
|
||||||
|
"=m" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
/*SSE*/
|
||||||
|
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
|
||||||
|
/*x87 - used for double -> i64 conversions*/
|
||||||
|
cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
block_pos = BLOCK_START; /*Entry code*/
|
||||||
|
host_x86_PUSH(block, REG_EBX);
|
||||||
|
host_x86_PUSH(block, REG_EBP);
|
||||||
|
host_x86_PUSH(block, REG_ESI);
|
||||||
|
host_x86_PUSH(block, REG_EDI);
|
||||||
|
host_x86_SUB32_REG_IMM(block, REG_ESP, 64);
|
||||||
|
host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128);
|
||||||
|
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||||
|
{
|
||||||
|
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
|
||||||
|
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
|
||||||
|
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_backend_epilogue(codeblock_t *block)
|
||||||
|
{
|
||||||
|
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
|
||||||
|
host_x86_POP(block, REG_EDI);
|
||||||
|
host_x86_POP(block, REG_ESI);
|
||||||
|
host_x86_POP(block, REG_EBP);
|
||||||
|
host_x86_POP(block, REG_EDX);
|
||||||
|
host_x86_RET(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
12
src/codegen_backend_x86.h
Normal file
12
src/codegen_backend_x86.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "codegen_backend_x86_defs.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 0x10000
|
||||||
|
#define BLOCK_MASK 0xffff
|
||||||
|
#define BLOCK_START 0
|
||||||
|
|
||||||
|
#define HASH_SIZE 0x20000
|
||||||
|
#define HASH_MASK 0x1ffff
|
||||||
|
|
||||||
|
#define HASH(l) ((l) & 0x1ffff)
|
||||||
|
|
||||||
|
#define BLOCK_MAX 0x3c0
|
||||||
50
src/codegen_backend_x86_defs.h
Normal file
50
src/codegen_backend_x86_defs.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef _CODEGEN_BACKEND_X86_DEFS_H_
|
||||||
|
#define _CODEGEN_BACKEND_X86_DEFS_H_
|
||||||
|
|
||||||
|
#define REG_EAX 0
|
||||||
|
#define REG_ECX 1
|
||||||
|
#define REG_EDX 2
|
||||||
|
#define REG_EBX 3
|
||||||
|
#define REG_ESP 4
|
||||||
|
#define REG_EBP 5
|
||||||
|
#define REG_ESI 6
|
||||||
|
#define REG_EDI 7
|
||||||
|
|
||||||
|
#define REG_XMM0 0
|
||||||
|
#define REG_XMM1 1
|
||||||
|
#define REG_XMM2 2
|
||||||
|
#define REG_XMM3 3
|
||||||
|
#define REG_XMM4 4
|
||||||
|
#define REG_XMM5 5
|
||||||
|
#define REG_XMM6 6
|
||||||
|
#define REG_XMM7 7
|
||||||
|
|
||||||
|
#define REG_XMM_TEMP REG_XMM7
|
||||||
|
#define REG_XMM_TEMP2 REG_XMM6
|
||||||
|
|
||||||
|
#define CODEGEN_HOST_REGS 3
|
||||||
|
#define CODEGEN_HOST_FP_REGS 6
|
||||||
|
|
||||||
|
extern void *codegen_mem_load_byte;
|
||||||
|
extern void *codegen_mem_load_word;
|
||||||
|
extern void *codegen_mem_load_long;
|
||||||
|
extern void *codegen_mem_load_quad;
|
||||||
|
extern void *codegen_mem_load_single;
|
||||||
|
extern void *codegen_mem_load_double;
|
||||||
|
|
||||||
|
extern void *codegen_mem_store_byte;
|
||||||
|
extern void *codegen_mem_store_word;
|
||||||
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
|
extern void *codegen_mem_store_single;
|
||||||
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
extern void *codegen_gpf_rout;
|
||||||
|
extern void *codegen_exit_rout;
|
||||||
|
|
||||||
|
#define STACK_ARG0 (0)
|
||||||
|
#define STACK_ARG1 (4)
|
||||||
|
#define STACK_ARG2 (8)
|
||||||
|
#define STACK_ARG3 (12)
|
||||||
|
|
||||||
|
#endif
|
||||||
1291
src/codegen_backend_x86_ops.c
Normal file
1291
src/codegen_backend_x86_ops.c
Normal file
File diff suppressed because it is too large
Load diff
192
src/codegen_backend_x86_ops.h
Normal file
192
src/codegen_backend_x86_ops.h
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
|
||||||
|
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_CALL(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_x86_INC32_ABS(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
void host_x86_JMP(codeblock_t *block, void *p);
|
||||||
|
uint32_t *host_x86_JMP_short(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JMP_long(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_JNZ(codeblock_t *block, void *p);
|
||||||
|
void host_x86_JZ(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
||||||
|
uint8_t *host_x86_JS_short(codeblock_t *block);
|
||||||
|
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
||||||
|
|
||||||
|
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNBE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNL_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNLE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNO_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNS_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JNZ_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JB_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JBE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JL_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JLE_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JO_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JS_long(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_LAHF(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset);
|
||||||
|
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
|
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||||
|
|
||||||
|
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||||
|
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
|
||||||
|
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
|
||||||
|
void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_addr, uint32_t addr, int base_reg, int idx_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
|
||||||
|
void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
#define host_x86_MOV16_STACK_REG(block, offset, src_reg) host_x86_MOV16_BASE_OFFSET_REG(block, REG_ESP, offset, src_reg)
|
||||||
|
|
||||||
|
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
|
||||||
|
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
|
||||||
|
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_POP(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PUSH(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_RET(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_ROL8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROL16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROL32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_ROR8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROR16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_ROR32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
|
||||||
|
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
|
||||||
|
|
||||||
|
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||||
|
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||||
|
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||||
|
|
||||||
|
void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||||
|
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||||
|
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||||
80
src/codegen_backend_x86_ops_fpu.c
Normal file
80
src/codegen_backend_x86_ops_fpu.c
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86_defs.h"
|
||||||
|
#include "codegen_backend_x86_ops_fpu.h"
|
||||||
|
#include "codegen_backend_x86_ops_helpers.h"
|
||||||
|
|
||||||
|
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 2);
|
||||||
|
codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 2);
|
||||||
|
codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x87_FLDCW(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 2);
|
||||||
|
codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 2);
|
||||||
|
codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
5
src/codegen_backend_x86_ops_fpu.h
Normal file
5
src/codegen_backend_x86_ops_fpu.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg);
|
||||||
|
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg);
|
||||||
|
void host_x87_FLDCW(codeblock_t *block, void *p);
|
||||||
|
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg);
|
||||||
|
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg);
|
||||||
84
src/codegen_backend_x86_ops_helpers.h
Normal file
84
src/codegen_backend_x86_ops_helpers.h
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#define JMP_LEN_BYTES 5
|
||||||
|
|
||||||
|
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||||
|
{
|
||||||
|
if (block_pos >= BLOCK_MAX)
|
||||||
|
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||||
|
block_write_data[block_pos++] = val;
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-2))
|
||||||
|
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||||
|
block_write_data[block_pos++] = vala;
|
||||||
|
block_write_data[block_pos++] = valb;
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-3))
|
||||||
|
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||||
|
block_write_data[block_pos++] = vala;
|
||||||
|
block_write_data[block_pos++] = valb;
|
||||||
|
block_write_data[block_pos++] = valc;
|
||||||
|
}
|
||||||
|
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-4))
|
||||||
|
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||||
|
block_write_data[block_pos++] = vala;
|
||||||
|
block_write_data[block_pos++] = valb;
|
||||||
|
block_write_data[block_pos++] = valc;
|
||||||
|
block_write_data[block_pos++] = vald;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-2))
|
||||||
|
fatal("codegen_addword over! %i\n", block_pos);
|
||||||
|
*(uint16_t *)&block_write_data[block_pos] = val;
|
||||||
|
block_pos += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-4))
|
||||||
|
fatal("codegen_addlong over! %i\n", block_pos);
|
||||||
|
*(uint32_t *)&block_write_data[block_pos] = val;
|
||||||
|
block_pos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||||
|
{
|
||||||
|
if (block_pos > (BLOCK_MAX-8))
|
||||||
|
fatal("codegen_addquad over! %i\n", block_pos);
|
||||||
|
*(uint64_t *)&block_write_data[block_pos] = val;
|
||||||
|
block_pos += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void codegen_allocate_new_block(codeblock_t *block)
|
||||||
|
{
|
||||||
|
/*Current block is full. Allocate a new block*/
|
||||||
|
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
|
||||||
|
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
|
||||||
|
|
||||||
|
/*Add a jump instruction to the new block*/
|
||||||
|
codegen_addbyte(block, 0xe9); /*JMP*/
|
||||||
|
codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]);
|
||||||
|
|
||||||
|
/*Set write address to start of new block*/
|
||||||
|
block_pos = 0;
|
||||||
|
block_write_data = new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codegen_alloc_bytes(codeblock_t *block, int size)
|
||||||
|
{
|
||||||
|
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
|
||||||
|
codegen_allocate_new_block(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_imm8(uint32_t imm_data)
|
||||||
|
{
|
||||||
|
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
588
src/codegen_backend_x86_ops_sse.c
Normal file
588
src/codegen_backend_x86_ops_sse.c
Normal file
|
|
@ -0,0 +1,588 @@
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_backend_x86_defs.h"
|
||||||
|
#include "codegen_backend_x86_ops_sse.h"
|
||||||
|
#include "codegen_backend_x86_ops_helpers.h"
|
||||||
|
|
||||||
|
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 7);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 8);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
|
||||||
|
{
|
||||||
|
if (addr < 0x80 || addr >= 0xffffff80)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
|
||||||
|
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
|
||||||
|
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
|
||||||
|
codegen_addlong(block, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg)
|
||||||
|
{
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/
|
||||||
|
codegen_addbyte2(block, 0x24, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset);
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg)
|
||||||
|
{
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/
|
||||||
|
codegen_addbyte(block, 0x24);
|
||||||
|
}
|
||||||
|
else if (offset >= -80 || offset < 0x80)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
|
||||||
|
codegen_addbyte2(block, 0x24, offset & 0xff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
|
||||||
|
codegen_addbyte(block, 0x24);
|
||||||
|
codegen_addlong(block, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 8);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
|
||||||
|
{
|
||||||
|
if (addr < 0x80 || addr >= 0xffffff80)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
|
||||||
|
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
|
||||||
|
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
|
||||||
|
codegen_addlong(block, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
|
||||||
|
codegen_addbyte(block, base_reg | (idx_reg << 3));
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 6);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/
|
||||||
|
codegen_addbyte2(block, 0x24, offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/
|
||||||
|
codegen_addbyte(block, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset);
|
||||||
|
}
|
||||||
|
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
|
||||||
|
codegen_addbyte(block, 0x88);
|
||||||
|
}
|
||||||
|
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
|
||||||
|
codegen_addbyte(block, 0x88);
|
||||||
|
}
|
||||||
|
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
|
||||||
|
codegen_addbyte(block, 0x88);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 5);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
|
||||||
|
codegen_addbyte(block, shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
|
||||||
|
codegen_addbyte(block, 0xee);
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
|
||||||
|
codegen_addbyte(block, 0xee);
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 9);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
|
||||||
|
codegen_addbyte(block, 0xee);
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 4);
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_alloc_bytes(block, 3);
|
||||||
|
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
112
src/codegen_backend_x86_ops_sse.h
Normal file
112
src/codegen_backend_x86_ops_sse.h
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
#define CMPPS_EQ 0
|
||||||
|
#define CMPPS_NLT 5
|
||||||
|
#define CMPPS_NLE 6
|
||||||
|
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
|
||||||
|
|
||||||
|
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
|
||||||
|
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
|
||||||
|
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
|
||||||
|
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
|
||||||
|
void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
|
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
|
||||||
|
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
|
||||||
|
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||||
|
|
||||||
|
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
3139
src/codegen_backend_x86_uops.c
Normal file
3139
src/codegen_backend_x86_uops.c
Normal file
File diff suppressed because it is too large
Load diff
190
src/codegen_ir.c
Normal file
190
src/codegen_ir.c
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_allocator.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
|
||||||
|
extern int has_ea;
|
||||||
|
static ir_data_t ir_block;
|
||||||
|
|
||||||
|
static int codegen_unroll_start, codegen_unroll_count;
|
||||||
|
static int codegen_unroll_first_instruction;
|
||||||
|
|
||||||
|
ir_data_t *codegen_ir_init()
|
||||||
|
{
|
||||||
|
ir_block.wr_pos = 0;
|
||||||
|
// pclog("codegen_ir_init %04x:%04x\n", CS,cpu_state.pc);
|
||||||
|
|
||||||
|
codegen_unroll_count = 0;
|
||||||
|
|
||||||
|
return &ir_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_ir_set_unroll(int count, int start, int first_instruction)
|
||||||
|
{
|
||||||
|
codegen_unroll_count = count;
|
||||||
|
codegen_unroll_start = start;
|
||||||
|
codegen_unroll_first_instruction = first_instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset)
|
||||||
|
{
|
||||||
|
uop_t *new_uop = uop_alloc(ir, uop->type);
|
||||||
|
|
||||||
|
// pclog(" uop type %08x\n", uop->type);
|
||||||
|
if (!ir_reg_is_invalid(uop->src_reg_a))
|
||||||
|
new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg);
|
||||||
|
if (!ir_reg_is_invalid(uop->src_reg_b))
|
||||||
|
new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg);
|
||||||
|
if (!ir_reg_is_invalid(uop->src_reg_c))
|
||||||
|
new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg);
|
||||||
|
if (!ir_reg_is_invalid(uop->dest_reg_a))
|
||||||
|
new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos-1);
|
||||||
|
|
||||||
|
new_uop->type = uop->type;
|
||||||
|
new_uop->imm_data = uop->imm_data;
|
||||||
|
new_uop->p = uop->p;
|
||||||
|
new_uop->pc = uop->pc;
|
||||||
|
|
||||||
|
if (uop->jump_dest_uop != -1)
|
||||||
|
{
|
||||||
|
new_uop->jump_dest_uop = uop->jump_dest_uop + offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int jump_target_at_end = -1;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (codegen_unroll_count)
|
||||||
|
{
|
||||||
|
int unroll_count;
|
||||||
|
int unroll_end;
|
||||||
|
|
||||||
|
codegen_set_loop_start(ir, codegen_unroll_first_instruction);
|
||||||
|
unroll_end = ir->wr_pos;
|
||||||
|
|
||||||
|
for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++)
|
||||||
|
{
|
||||||
|
int offset = ir->wr_pos - codegen_unroll_start;
|
||||||
|
// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count);
|
||||||
|
for (c = codegen_unroll_start; c < unroll_end; c++)
|
||||||
|
{
|
||||||
|
// pclog(" Duplicate uop %i\n", c);
|
||||||
|
duplicate_uop(ir, &ir->uops[c], offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_reg_mark_as_required();
|
||||||
|
codegen_reg_process_dead_list(ir);
|
||||||
|
block_write_data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||||
|
block_pos = 0;
|
||||||
|
codegen_backend_prologue(block);
|
||||||
|
|
||||||
|
for (c = 0; c < ir->wr_pos; c++)
|
||||||
|
{
|
||||||
|
uop_t *uop = &ir->uops[c];
|
||||||
|
|
||||||
|
// pclog("uOP %i : %08x\n", c, uop->type);
|
||||||
|
|
||||||
|
if (uop->type & UOP_TYPE_BARRIER)
|
||||||
|
codegen_reg_flush_invalidate(ir, block);
|
||||||
|
|
||||||
|
if (uop->type & UOP_TYPE_JUMP_DEST)
|
||||||
|
{
|
||||||
|
uop_t *uop_dest = uop;
|
||||||
|
|
||||||
|
while (uop_dest->jump_list_next != -1)
|
||||||
|
{
|
||||||
|
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||||
|
codegen_set_jump_dest(block, uop_dest->p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uop->type & UOP_MASK) == UOP_INVALID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (uop->type & UOP_TYPE_PARAMS_REGS)
|
||||||
|
{
|
||||||
|
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
|
||||||
|
if (uop->src_reg_a.reg != IREG_INVALID)
|
||||||
|
{
|
||||||
|
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
|
||||||
|
}
|
||||||
|
if (uop->src_reg_b.reg != IREG_INVALID)
|
||||||
|
{
|
||||||
|
uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
|
||||||
|
}
|
||||||
|
if (uop->src_reg_c.reg != IREG_INVALID)
|
||||||
|
{
|
||||||
|
uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uop->type & UOP_TYPE_ORDER_BARRIER)
|
||||||
|
codegen_reg_flush(ir, block);
|
||||||
|
|
||||||
|
if (uop->type & UOP_TYPE_PARAMS_REGS)
|
||||||
|
{
|
||||||
|
if (uop->dest_reg_a.reg != IREG_INVALID)
|
||||||
|
{
|
||||||
|
uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uop_handlers[uop->type & UOP_MASK])
|
||||||
|
fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
|
||||||
|
uop_handlers[uop->type & UOP_MASK](block, uop);
|
||||||
|
|
||||||
|
if (uop->type & UOP_TYPE_JUMP)
|
||||||
|
{
|
||||||
|
if (uop->jump_dest_uop == ir->wr_pos)
|
||||||
|
{
|
||||||
|
if (jump_target_at_end == -1)
|
||||||
|
jump_target_at_end = c;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_t *uop_dest = &ir->uops[jump_target_at_end];
|
||||||
|
|
||||||
|
while (uop_dest->jump_list_next != -1)
|
||||||
|
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||||
|
|
||||||
|
uop_dest->jump_list_next = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_t *uop_dest = &ir->uops[uop->jump_dest_uop];
|
||||||
|
|
||||||
|
while (uop_dest->jump_list_next != -1)
|
||||||
|
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||||
|
|
||||||
|
uop_dest->jump_list_next = c;
|
||||||
|
ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_reg_flush_invalidate(ir, block);
|
||||||
|
|
||||||
|
if (jump_target_at_end != -1)
|
||||||
|
{
|
||||||
|
uop_t *uop_dest = &ir->uops[jump_target_at_end];
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
codegen_set_jump_dest(block, uop_dest->p);
|
||||||
|
if (uop_dest->jump_list_next == -1)
|
||||||
|
break;
|
||||||
|
uop_dest = &ir->uops[uop_dest->jump_list_next];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_backend_epilogue(block);
|
||||||
|
block_write_data = NULL;
|
||||||
|
// if (has_ea)
|
||||||
|
// fatal("IR compilation complete\n");
|
||||||
|
}
|
||||||
6
src/codegen_ir.h
Normal file
6
src/codegen_ir.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
|
||||||
|
ir_data_t *codegen_ir_init();
|
||||||
|
|
||||||
|
void codegen_ir_set_unroll(int count, int start, int first_instruction);
|
||||||
|
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block);
|
||||||
810
src/codegen_ir_defs.h
Normal file
810
src/codegen_ir_defs.h
Normal file
|
|
@ -0,0 +1,810 @@
|
||||||
|
#ifndef _CODEGEN_IR_DEFS_
|
||||||
|
#define _CODEGEN_IR_DEFS_
|
||||||
|
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
|
||||||
|
#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8))
|
||||||
|
|
||||||
|
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
|
||||||
|
All registers must have been written back or discarded.
|
||||||
|
This should be used when calling external functions that may change any emulated
|
||||||
|
registers.*/
|
||||||
|
#define UOP_TYPE_BARRIER (1 << 31)
|
||||||
|
|
||||||
|
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
|
||||||
|
All registers must have been written back, but do not have to be discarded.
|
||||||
|
This should be used when calling functions that preserve registers, but can cause
|
||||||
|
the code block to exit (eg memory load/store functions).*/
|
||||||
|
#define UOP_TYPE_ORDER_BARRIER (1 << 27)
|
||||||
|
|
||||||
|
/*uOP uses source and dest registers*/
|
||||||
|
#define UOP_TYPE_PARAMS_REGS (1 << 28)
|
||||||
|
/*uOP uses pointer*/
|
||||||
|
#define UOP_TYPE_PARAMS_POINTER (1 << 29)
|
||||||
|
/*uOP uses immediate data*/
|
||||||
|
#define UOP_TYPE_PARAMS_IMM (1 << 30)
|
||||||
|
|
||||||
|
/*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must
|
||||||
|
set jump_dest in the destination uOP to the address of the branch offset to be
|
||||||
|
written when known.*/
|
||||||
|
#define UOP_TYPE_JUMP (1 << 26)
|
||||||
|
/*uOP is the destination of a jump, and must set the destination offset of the jump
|
||||||
|
at compile time.*/
|
||||||
|
#define UOP_TYPE_JUMP_DEST (1 << 25)
|
||||||
|
|
||||||
|
|
||||||
|
#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER)
|
||||||
|
/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/
|
||||||
|
#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER)
|
||||||
|
#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12)
|
||||||
|
#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13)
|
||||||
|
/*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/
|
||||||
|
#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER)
|
||||||
|
/*UOP_JMP - jump to ptr*/
|
||||||
|
#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/
|
||||||
|
#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER)
|
||||||
|
/*UOP_JMP_DEST - jump to ptr*/
|
||||||
|
#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18)
|
||||||
|
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
/*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/
|
||||||
|
#define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*UOP_MOV_PTR - dest_reg = p*/
|
||||||
|
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
|
||||||
|
/*UOP_MOV_IMM - dest_reg = imm_data*/
|
||||||
|
#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21)
|
||||||
|
/*UOP_MOV - dest_reg = src_reg_a*/
|
||||||
|
#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22)
|
||||||
|
/*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/
|
||||||
|
#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23)
|
||||||
|
/*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/
|
||||||
|
#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24)
|
||||||
|
/*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/
|
||||||
|
#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25)
|
||||||
|
/*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
|
||||||
|
#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26)
|
||||||
|
/*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
|
||||||
|
#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27)
|
||||||
|
/*UOP_MOV_REG_PTR - dest_reg = *p*/
|
||||||
|
#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28)
|
||||||
|
/*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/
|
||||||
|
#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29)
|
||||||
|
/*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/
|
||||||
|
#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a)
|
||||||
|
/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
|
||||||
|
/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/
|
||||||
|
#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31)
|
||||||
|
/*UOP_AND - dest_reg = src_reg_a & src_reg_b*/
|
||||||
|
#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32)
|
||||||
|
/*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/
|
||||||
|
#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33)
|
||||||
|
/*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data)
|
||||||
|
Intended for EA calcluations, imm_data must be between 0 and 3*/
|
||||||
|
#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34)
|
||||||
|
/*UOP_OR - dest_reg = src_reg_a | src_reg_b*/
|
||||||
|
#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35)
|
||||||
|
/*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/
|
||||||
|
#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36)
|
||||||
|
/*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37)
|
||||||
|
/*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/
|
||||||
|
#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38)
|
||||||
|
/*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/
|
||||||
|
#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39)
|
||||||
|
/*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/
|
||||||
|
#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a)
|
||||||
|
/*UOP_ANDN - dest_reg = ~src_reg_a & src_reg_b*/
|
||||||
|
#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b)
|
||||||
|
/*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/
|
||||||
|
#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/
|
||||||
|
#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/
|
||||||
|
#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/
|
||||||
|
#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/
|
||||||
|
#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/
|
||||||
|
#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/
|
||||||
|
#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_LOAD_SINGLE - dest_reg = (float)src_reg_a:[src_reg_b]*/
|
||||||
|
#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/
|
||||||
|
#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_LOAD_DOUBLE - dest_reg = (double)src_reg_a:[src_reg_b]*/
|
||||||
|
#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_SINGLE - src_reg_a:[src_reg_b] = src_reg_c*/
|
||||||
|
#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/
|
||||||
|
#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_CMP_JB - if (src_reg_a < src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
/*UOP_CMP_JNBE - if (src_reg_a > src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER)
|
||||||
|
|
||||||
|
/*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/
|
||||||
|
#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50)
|
||||||
|
/*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51)
|
||||||
|
/*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/
|
||||||
|
#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52)
|
||||||
|
/*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/
|
||||||
|
#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53)
|
||||||
|
/*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/
|
||||||
|
#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54)
|
||||||
|
/*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55)
|
||||||
|
/*UOP_ROL - dest_reg = src_reg_a rotate<< src_reg_b*/
|
||||||
|
#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56)
|
||||||
|
/*UOP_ROL_IMM - dest_reg = src_reg_a rotate<< immediate*/
|
||||||
|
#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57)
|
||||||
|
/*UOP_ROR - dest_reg = src_reg_a rotate>> src_reg_b*/
|
||||||
|
#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58)
|
||||||
|
/*UOP_ROR_IMM - dest_reg = src_reg_a rotate>> immediate*/
|
||||||
|
#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59)
|
||||||
|
|
||||||
|
/*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/
|
||||||
|
#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/
|
||||||
|
#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
|
||||||
|
/*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/
|
||||||
|
#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
|
||||||
|
|
||||||
|
/*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/
|
||||||
|
#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
/*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/
|
||||||
|
#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
|
|
||||||
|
/*UOP_FP_ENTER - must be called before any FPU register accessed*/
|
||||||
|
#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER)
|
||||||
|
/*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81)
|
||||||
|
/*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82)
|
||||||
|
/*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/
|
||||||
|
#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83)
|
||||||
|
/*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/
|
||||||
|
#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84)
|
||||||
|
/*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/
|
||||||
|
#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85)
|
||||||
|
/*UOP_FABS - dest_reg = fabs(src_reg_a)*/
|
||||||
|
#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86)
|
||||||
|
/*UOP_FCHS - dest_reg = fabs(src_reg_a)*/
|
||||||
|
#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87)
|
||||||
|
/*UOP_FTST - dest_reg = flags from compare(src_reg_a, 0)*/
|
||||||
|
#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88)
|
||||||
|
/*UOP_FSQRT - dest_reg = fsqrt(src_reg_a)*/
|
||||||
|
#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89)
|
||||||
|
|
||||||
|
/*UOP_MMX_ENTER - must be called before any MMX registers accessed*/
|
||||||
|
#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER)
|
||||||
|
/*UOP_PADDB - (packed byte) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91)
|
||||||
|
/*UOP_PADDW - (packed word) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92)
|
||||||
|
/*UOP_PADDD - (packed long) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93)
|
||||||
|
/*UOP_PADDSB - (packed byte with signed saturation) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94)
|
||||||
|
/*UOP_PADDSW - (packed word with signed saturation) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95)
|
||||||
|
/*UOP_PADDUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96)
|
||||||
|
/*UOP_PADDUSW - (packed word with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97)
|
||||||
|
/*UOP_PSUBB - (packed byte) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98)
|
||||||
|
/*UOP_PSUBW - (packed word) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99)
|
||||||
|
/*UOP_PSUBD - (packed long) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a)
|
||||||
|
/*UOP_PSUBSB - (packed byte with signed saturation) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b)
|
||||||
|
/*UOP_PSUBSW - (packed word with signed saturation) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c)
|
||||||
|
/*UOP_PSUBUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d)
|
||||||
|
/*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e)
|
||||||
|
/*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/
|
||||||
|
#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f)
|
||||||
|
/*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/
|
||||||
|
#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0)
|
||||||
|
/*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/
|
||||||
|
#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1)
|
||||||
|
/*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2)
|
||||||
|
/*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3)
|
||||||
|
/*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4)
|
||||||
|
/*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5)
|
||||||
|
/*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6)
|
||||||
|
/*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/
|
||||||
|
#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7)
|
||||||
|
/*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8)
|
||||||
|
/*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9)
|
||||||
|
/*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa)
|
||||||
|
/*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab)
|
||||||
|
/*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac)
|
||||||
|
/*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad)
|
||||||
|
/*UOP_PUNPCKLBW - (packed byte) dest_reg = interleave low src_reg_a/src_reg_b*/
|
||||||
|
#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae)
|
||||||
|
/*UOP_PUNPCKLWD - (packed word) dest_reg = interleave low src_reg_a/src_reg_b*/
|
||||||
|
#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf)
|
||||||
|
/*UOP_PUNPCKLDQ - (packed long) dest_reg = interleave low src_reg_a/src_reg_b*/
|
||||||
|
#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0)
|
||||||
|
/*UOP_PUNPCKHBW - (packed byte) dest_reg = interleave high src_reg_a/src_reg_b*/
|
||||||
|
#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1)
|
||||||
|
/*UOP_PUNPCKHWD - (packed word) dest_reg = interleave high src_reg_a/src_reg_b*/
|
||||||
|
#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2)
|
||||||
|
/*UOP_PUNPCKHDQ - (packed long) dest_reg = interleave high src_reg_a/src_reg_b*/
|
||||||
|
#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3)
|
||||||
|
/*UOP_PACKSSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with signed saturation*/
|
||||||
|
#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4)
|
||||||
|
/*UOP_PACKSSDW - dest_reg = interleave src_reg_a/src_reg_b, converting longs to words with signed saturation*/
|
||||||
|
#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5)
|
||||||
|
/*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/
|
||||||
|
#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6)
|
||||||
|
/*UOP_PMULLW - (packed word) dest_reg = (src_reg_a * src_reg_b) & 0xffff*/
|
||||||
|
#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7)
|
||||||
|
/*UOP_PMULHW - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
|
||||||
|
#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8)
|
||||||
|
/*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
|
||||||
|
#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9)
|
||||||
|
|
||||||
|
/*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/
|
||||||
|
#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba)
|
||||||
|
/*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/
|
||||||
|
#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb)
|
||||||
|
/*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/
|
||||||
|
#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc)
|
||||||
|
/*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/
|
||||||
|
#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd)
|
||||||
|
/*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/
|
||||||
|
#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe)
|
||||||
|
/*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf)
|
||||||
|
/*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0)
|
||||||
|
/*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
|
||||||
|
#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1)
|
||||||
|
/*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/
|
||||||
|
#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2)
|
||||||
|
/*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/
|
||||||
|
#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3)
|
||||||
|
/*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/
|
||||||
|
#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4)
|
||||||
|
/*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/
|
||||||
|
#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5)
|
||||||
|
|
||||||
|
#define UOP_MAX 0xc6
|
||||||
|
|
||||||
|
#define UOP_INVALID 0xff
|
||||||
|
|
||||||
|
#define UOP_MASK 0xffff
|
||||||
|
|
||||||
|
typedef struct uop_t
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
ir_reg_t dest_reg_a;
|
||||||
|
ir_reg_t src_reg_a;
|
||||||
|
ir_reg_t src_reg_b;
|
||||||
|
ir_reg_t src_reg_c;
|
||||||
|
uint32_t imm_data;
|
||||||
|
void *p;
|
||||||
|
ir_host_reg_t dest_reg_a_real;
|
||||||
|
ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real;
|
||||||
|
int jump_dest_uop;
|
||||||
|
int jump_list_next;
|
||||||
|
void *jump_dest;
|
||||||
|
uint32_t pc;
|
||||||
|
} uop_t;
|
||||||
|
|
||||||
|
#define UOP_NR_MAX 4096
|
||||||
|
|
||||||
|
typedef struct ir_data_t
|
||||||
|
{
|
||||||
|
uop_t uops[UOP_NR_MAX];
|
||||||
|
int wr_pos;
|
||||||
|
struct codeblock_t *block;
|
||||||
|
} ir_data_t;
|
||||||
|
|
||||||
|
static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type)
|
||||||
|
{
|
||||||
|
uop_t *uop;
|
||||||
|
|
||||||
|
if (ir->wr_pos >= UOP_NR_MAX)
|
||||||
|
fatal("Exceeded uOP max\n");
|
||||||
|
|
||||||
|
uop = &ir->uops[ir->wr_pos++];
|
||||||
|
|
||||||
|
uop->dest_reg_a = invalid_ir_reg;
|
||||||
|
uop->src_reg_a = invalid_ir_reg;
|
||||||
|
uop->src_reg_b = invalid_ir_reg;
|
||||||
|
uop->src_reg_c = invalid_ir_reg;
|
||||||
|
|
||||||
|
uop->pc = cpu_state.oldpc;
|
||||||
|
|
||||||
|
uop->jump_dest_uop = -1;
|
||||||
|
uop->jump_list_next = -1;
|
||||||
|
|
||||||
|
if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))
|
||||||
|
codegen_reg_mark_as_required();
|
||||||
|
|
||||||
|
return uop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop)
|
||||||
|
{
|
||||||
|
uop_t *uop = &ir->uops[jump_uop];
|
||||||
|
|
||||||
|
uop->jump_dest_uop = ir->wr_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uop_gen(uint32_t uop_type, ir_data_t *ir)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
|
||||||
|
return ir->wr_pos-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
|
||||||
|
return ir->wr_pos-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
|
||||||
|
return ir->wr_pos-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
uop->p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->src_reg_c = codegen_reg_read(src_reg_c);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
|
||||||
|
return ir->wr_pos-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->src_reg_c = codegen_reg_read(src_reg_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->src_reg_c = codegen_reg_read(src_reg_c);
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->p = p;
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->p = p;
|
||||||
|
uop->imm_data = imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir, uop_type);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
|
||||||
|
|
||||||
|
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
|
||||||
|
|
||||||
|
#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift)
|
||||||
|
#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
|
||||||
|
#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg)
|
||||||
|
#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg)
|
||||||
|
#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg)
|
||||||
|
#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg)
|
||||||
|
#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg)
|
||||||
|
#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
|
||||||
|
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
|
||||||
|
#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p)
|
||||||
|
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
|
||||||
|
|
||||||
|
#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm)
|
||||||
|
|
||||||
|
#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm)
|
||||||
|
#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm)
|
||||||
|
|
||||||
|
#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p)
|
||||||
|
#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p)
|
||||||
|
|
||||||
|
#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg)
|
||||||
|
#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg)
|
||||||
|
#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg)
|
||||||
|
#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg)
|
||||||
|
|
||||||
|
#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0)
|
||||||
|
#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0)
|
||||||
|
|
||||||
|
#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p)
|
||||||
|
#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir)
|
||||||
|
|
||||||
|
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
|
||||||
|
|
||||||
|
#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm)
|
||||||
|
#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0)
|
||||||
|
#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset)
|
||||||
|
#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0)
|
||||||
|
#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0)
|
||||||
|
#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm)
|
||||||
|
#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0)
|
||||||
|
#define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset)
|
||||||
|
#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm)
|
||||||
|
#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm)
|
||||||
|
#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm)
|
||||||
|
#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0)
|
||||||
|
#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0)
|
||||||
|
|
||||||
|
#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg)
|
||||||
|
#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm)
|
||||||
|
#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p)
|
||||||
|
#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p)
|
||||||
|
#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p)
|
||||||
|
#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p)
|
||||||
|
#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg)
|
||||||
|
#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg)
|
||||||
|
#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg)
|
||||||
|
#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/)
|
||||||
|
#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag)
|
||||||
|
|
||||||
|
#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir)
|
||||||
|
|
||||||
|
#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg)
|
||||||
|
#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg)
|
||||||
|
#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg)
|
||||||
|
#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg)
|
||||||
|
|
||||||
|
#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm)
|
||||||
|
|
||||||
|
#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b)
|
||||||
|
|
||||||
|
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
|
||||||
|
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
|
||||||
|
|
||||||
|
#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg)
|
||||||
|
#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg)
|
||||||
|
|
||||||
|
#ifdef DEBUG_EXTRA
|
||||||
|
#define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
|
||||||
|
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p);
|
||||||
|
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p);
|
||||||
|
void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p);
|
||||||
|
void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p);
|
||||||
|
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p);
|
||||||
|
void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx);
|
||||||
|
void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx);
|
||||||
|
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx);
|
||||||
|
|
||||||
|
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg);
|
||||||
|
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg);
|
||||||
|
void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg);
|
||||||
|
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg);
|
||||||
|
|
||||||
|
void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset);
|
||||||
|
void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset);
|
||||||
|
void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset);
|
||||||
|
void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset);
|
||||||
|
void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset);
|
||||||
|
|
||||||
|
void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg);
|
||||||
|
void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg);
|
||||||
|
void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg);
|
||||||
|
void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg);
|
||||||
|
|
||||||
|
void codegen_set_jump_dest(codeblock_t *block, void *p);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,77 +1,75 @@
|
||||||
#include "ibm.h"
|
#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.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
#include "codegen_ops.h"
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_3dnow.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_arith.h"
|
||||||
#include "codegen_ops_fpu.h"
|
#include "codegen_ops_branch.h"
|
||||||
|
#include "codegen_ops_fpu_arith.h"
|
||||||
|
#include "codegen_ops_fpu_constant.h"
|
||||||
|
#include "codegen_ops_fpu_loadstore.h"
|
||||||
|
#include "codegen_ops_fpu_misc.h"
|
||||||
#include "codegen_ops_jump.h"
|
#include "codegen_ops_jump.h"
|
||||||
#include "codegen_ops_logic.h"
|
#include "codegen_ops_logic.h"
|
||||||
#include "codegen_ops_misc.h"
|
#include "codegen_ops_misc.h"
|
||||||
#include "codegen_ops_mmx.h"
|
#include "codegen_ops_mmx_arith.h"
|
||||||
|
#include "codegen_ops_mmx_cmp.h"
|
||||||
|
#include "codegen_ops_mmx_loadstore.h"
|
||||||
|
#include "codegen_ops_mmx_logic.h"
|
||||||
|
#include "codegen_ops_mmx_pack.h"
|
||||||
|
#include "codegen_ops_mmx_shift.h"
|
||||||
#include "codegen_ops_mov.h"
|
#include "codegen_ops_mov.h"
|
||||||
#include "codegen_ops_shift.h"
|
#include "codegen_ops_shift.h"
|
||||||
#include "codegen_ops_stack.h"
|
#include "codegen_ops_stack.h"
|
||||||
#include "codegen_ops_xchg.h"
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes[512] =
|
RecompOpFn recomp_opcodes[512] =
|
||||||
{
|
{
|
||||||
/*16-bit data*/
|
/*16-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
|
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16,
|
/*10*/ ropADC_b_rmw, ropADC_w_rmw, ropADC_b_rm, ropADC_w_rm, ropADC_AL_imm, ropADC_AX_imm, ropPUSH_SS_16, NULL, ropSBB_b_rmw, ropSBB_w_rmw, ropSBB_b_rm, ropSBB_w_rm, ropSBB_AL_imm, ropSBB_AX_imm, ropPUSH_DS_16, ropPOP_DS_16,
|
||||||
/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL,
|
/*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,
|
/*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,
|
/*40*/ ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16,
|
||||||
/*50*/ ropPUSH_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,
|
/*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL,
|
/*60*/ ropPUSHA_16, ropPOPA_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
|
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
|
||||||
|
|
||||||
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_w, ropMOV_seg_w, NULL,
|
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W,
|
||||||
/*90*/ ropNOP, ropXCHG_AX_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,
|
/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropCBW, ropCWD, NULL, NULL, ropPUSHF, NULL, NULL, NULL,
|
||||||
/*a0*/ ropMOV_AL_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,
|
/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
|
/*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,
|
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES_16, ropLDS_16, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, ropRETF_imm_16, ropRETF_16, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, ropXLAT, 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,
|
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, ropJMP_far_16, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_16, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_16,
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL,
|
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL,
|
||||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32,
|
/*10*/ ropADC_b_rmw, ropADC_l_rmw, ropADC_b_rm, ropADC_l_rm, ropADC_AL_imm, ropADC_EAX_imm, ropPUSH_SS_32, NULL, ropSBB_b_rmw, ropSBB_l_rmw, ropSBB_b_rm, ropSBB_l_rm, ropSBB_AL_imm, ropSBB_EAX_imm, ropPUSH_DS_32, ropPOP_DS_32,
|
||||||
/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL,
|
/*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,
|
/*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,
|
/*40*/ ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32,
|
||||||
/*50*/ ropPUSH_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,
|
/*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL,
|
/*60*/ ropPUSHA_32, ropPOPA_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
|
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
|
||||||
|
|
||||||
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_w_seg, ropLEA_l, ropMOV_seg_w, NULL,
|
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L,
|
||||||
/*90*/ ropNOP, ropXCHG_EAX_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,
|
/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropCWDE, ropCDQ, NULL, NULL, ropPUSHFD, NULL, NULL, NULL,
|
||||||
/*a0*/ ropMOV_AL_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,
|
/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
|
/*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,
|
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES_32, ropLDS_32, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, ropRETF_imm_32, ropRETF_32, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, ropXLAT, 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,
|
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, ropJMP_far_32, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_32, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_32
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_0f[512] =
|
RecompOpFn recomp_opcodes_0f[512] =
|
||||||
{
|
{
|
||||||
/*16-bit data*/
|
/*16-bit data*/
|
||||||
|
|
@ -83,18 +81,18 @@ RecompOpFn recomp_opcodes_0f[512] =
|
||||||
|
|
||||||
/*40*/ 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,
|
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q,
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r,
|
||||||
|
|
||||||
/*80*/ ropJO_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,
|
/*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16,
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL,
|
||||||
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL,
|
/*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
|
|
@ -105,20 +103,43 @@ RecompOpFn recomp_opcodes_0f[512] =
|
||||||
|
|
||||||
/*40*/ 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,
|
/*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,
|
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q,
|
||||||
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm,
|
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r,
|
||||||
|
|
||||||
/*80*/ ropJO_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,
|
/*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32,
|
||||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL,
|
||||||
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w,
|
/*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, 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,
|
/*e0*/ NULL, NULL, NULL, 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,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RecompOpFn recomp_opcodes_3DNOW[256] =
|
||||||
|
{
|
||||||
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
|
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPI2FD, NULL, NULL,
|
||||||
|
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPF2ID, NULL, NULL,
|
||||||
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
|
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
|
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*90*/ ropPFCMPGE, NULL, NULL, NULL, ropPFMIN, NULL, ropPFRCP, ropPFRSQRT, NULL, NULL, ropPFSUB, NULL, NULL, NULL, ropPFADD, NULL,
|
||||||
|
/*a0*/ ropPFCMPGT, NULL, NULL, NULL, ropPFMAX, NULL, ropPFRCPIT, ropPFRSQIT1, NULL, NULL, ropPFSUBR, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*b0*/ ropPFCMPEQ, NULL, NULL, NULL, ropPFMUL, NULL, ropPFRCPIT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
|
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
};
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_d8[512] =
|
RecompOpFn recomp_opcodes_d8[512] =
|
||||||
{
|
{
|
||||||
|
|
@ -173,90 +194,90 @@ RecompOpFn recomp_opcodes_d9[512] =
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
/*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,
|
/*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,
|
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
/*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,
|
/*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,
|
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
/*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,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
||||||
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
|
/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
/*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,
|
/*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,
|
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
/*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,
|
/*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,
|
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
|
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
|
/*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,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
||||||
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
|
/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes_da[512] =
|
RecompOpFn recomp_opcodes_da[512] =
|
||||||
{
|
{
|
||||||
/*16-bit data*/
|
/*16-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
|
||||||
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
|
||||||
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
|
||||||
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
|
||||||
|
|
||||||
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
|
||||||
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
|
||||||
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
|
||||||
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
|
||||||
|
|
||||||
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
|
||||||
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
|
||||||
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
|
||||||
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
|
||||||
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
|
||||||
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
|
||||||
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
|
||||||
|
|
||||||
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
|
||||||
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
|
||||||
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
|
||||||
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
|
||||||
|
|
||||||
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
|
||||||
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
|
/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
|
||||||
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
|
/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
|
||||||
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
|
/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
@ -287,7 +308,7 @@ RecompOpFn recomp_opcodes_db[512] =
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
@ -362,21 +383,21 @@ RecompOpFn recomp_opcodes_dd[512] =
|
||||||
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
|
||||||
|
|
||||||
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
|
||||||
|
|
||||||
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
|
|
@ -384,21 +405,21 @@ RecompOpFn recomp_opcodes_dd[512] =
|
||||||
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
|
||||||
|
|
||||||
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
|
||||||
|
|
||||||
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP,
|
||||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -406,20 +427,20 @@ RecompOpFn recomp_opcodes_de[512] =
|
||||||
{
|
{
|
||||||
/*16-bit data*/
|
/*16-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
|
||||||
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
|
||||||
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
|
||||||
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
|
||||||
|
|
||||||
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
|
||||||
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
|
||||||
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
|
||||||
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
|
||||||
|
|
||||||
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
|
||||||
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
|
||||||
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
|
||||||
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
|
||||||
|
|
||||||
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
@ -428,20 +449,20 @@ RecompOpFn recomp_opcodes_de[512] =
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
|
||||||
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
|
||||||
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
|
||||||
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
|
||||||
|
|
||||||
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
|
||||||
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
|
||||||
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
|
||||||
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
|
||||||
|
|
||||||
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
|
||||||
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
|
/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
|
||||||
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
|
/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
|
||||||
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
|
/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
|
||||||
|
|
||||||
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
@ -495,97 +516,3 @@ RecompOpFn recomp_opcodes_df[512] =
|
||||||
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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,
|
/*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,
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@
|
||||||
|
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
|
||||||
typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block);
|
struct ir_data_t;
|
||||||
|
|
||||||
|
typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
extern RecompOpFn recomp_opcodes[512];
|
extern RecompOpFn recomp_opcodes[512];
|
||||||
extern RecompOpFn recomp_opcodes_0f[512];
|
extern RecompOpFn recomp_opcodes_0f[512];
|
||||||
|
extern RecompOpFn recomp_opcodes_3DNOW[256];
|
||||||
extern RecompOpFn recomp_opcodes_d8[512];
|
extern RecompOpFn recomp_opcodes_d8[512];
|
||||||
extern RecompOpFn recomp_opcodes_d9[512];
|
extern RecompOpFn recomp_opcodes_d9[512];
|
||||||
extern RecompOpFn recomp_opcodes_da[512];
|
extern RecompOpFn recomp_opcodes_da[512];
|
||||||
|
|
@ -15,8 +18,8 @@ extern RecompOpFn recomp_opcodes_dc[512];
|
||||||
extern RecompOpFn recomp_opcodes_dd[512];
|
extern RecompOpFn recomp_opcodes_dd[512];
|
||||||
extern RecompOpFn recomp_opcodes_de[512];
|
extern RecompOpFn recomp_opcodes_de[512];
|
||||||
extern RecompOpFn recomp_opcodes_df[512];
|
extern RecompOpFn recomp_opcodes_df[512];
|
||||||
RecompOpFn recomp_opcodes_REPE[512];
|
/*extern RecompOpFn recomp_opcodes_REPE[512];
|
||||||
RecompOpFn recomp_opcodes_REPNE[512];
|
extern RecompOpFn recomp_opcodes_REPNE[512];*/
|
||||||
|
|
||||||
#define REG_EAX 0
|
#define REG_EAX 0
|
||||||
#define REG_ECX 1
|
#define REG_ECX 1
|
||||||
|
|
|
||||||
208
src/codegen_ops_3dnow.c
Normal file
208
src/codegen_ops_3dnow.c
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_3dnow.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
#define ropParith(func) \
|
||||||
|
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7; \
|
||||||
|
\
|
||||||
|
uop_MMX_ENTER(ir); \
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0) \
|
||||||
|
{ \
|
||||||
|
int src_reg = fetchdat & 7; \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1); \
|
||||||
|
return op_pc + 2; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropParith(PFADD)
|
||||||
|
ropParith(PFCMPEQ)
|
||||||
|
ropParith(PFCMPGE)
|
||||||
|
ropParith(PFCMPGT)
|
||||||
|
ropParith(PFMAX)
|
||||||
|
ropParith(PFMIN)
|
||||||
|
ropParith(PFMUL)
|
||||||
|
ropParith(PFSUB)
|
||||||
|
|
||||||
|
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
15
src/codegen_ops_3dnow.h
Normal file
15
src/codegen_ops_3dnow.h
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFCMPEQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFCMPGE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFCMPGT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFMAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFMIN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
2517
src/codegen_ops_arith.c
Normal file
2517
src/codegen_ops_arith.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1011
src/codegen_ops_branch.c
Normal file
1011
src/codegen_ops_branch.c
Normal file
File diff suppressed because it is too large
Load diff
69
src/codegen_ops_branch.h
Normal file
69
src/codegen_ops_branch.h
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
uint32_t ropJB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJNS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropJNS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
570
src/codegen_ops_fpu_arith.c
Normal file
570
src/codegen_ops_fpu_arith.c
Normal file
|
|
@ -0,0 +1,570 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "x87.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_fpu_arith.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
fpu_POP2(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
fpu_POP2(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ropF_arith_mem(name, load_uop) \
|
||||||
|
uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFCOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
|
||||||
|
fpu_POP(block, ir); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFSUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFSUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropF_arith_mem(s, uop_MEM_LOAD_SINGLE)
|
||||||
|
ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE)
|
||||||
|
|
||||||
|
#define ropFI_arith_mem(name, temp_reg) \
|
||||||
|
uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFICOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
|
||||||
|
fpu_POP(block, ir); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFIDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFIMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFISUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
} \
|
||||||
|
uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_FP_ENTER(ir); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
op_pc--; \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
|
||||||
|
uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
|
||||||
|
\
|
||||||
|
return op_pc+1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropFI_arith_mem(l, IREG_temp0)
|
||||||
|
ropFI_arith_mem(w, IREG_temp0_W)
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FABS(ir, IREG_ST(0), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FCHS(ir, IREG_ST(0), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FSQRT(ir, IREG_ST(0), IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_FTST(ir, IREG_temp0_W, IREG_ST(0));
|
||||||
|
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
|
||||||
|
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
63
src/codegen_ops_fpu_arith.h
Normal file
63
src/codegen_ops_fpu_arith.h
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFADDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFADDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOMs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOMd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOMPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCOMPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFDIVRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFMULs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFMULd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSUBRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFIADDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIADDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFICOMl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFICOMw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFICOMPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFICOMPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIDIVl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIDIVw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIDIVRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIDIVRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIMULl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFIMULw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISUBl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISUBw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISUBRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISUBRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
33
src/codegen_ops_fpu_constant.c
Normal file
33
src/codegen_ops_fpu_constant.c
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "x87.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_fpu_constant.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_temp0, 1);
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_temp0, 0);
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
2
src/codegen_ops_fpu_constant.h
Normal file
2
src/codegen_ops_fpu_constant.h
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
231
src/codegen_ops_fpu_loadstore.c
Normal file
231
src/codegen_ops_fpu_loadstore.c
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "x87.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_fpu_arith.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
|
||||||
|
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
|
||||||
|
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1));
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64);
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
17
src/codegen_ops_fpu_loadstore.h
Normal file
17
src/codegen_ops_fpu_loadstore.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
111
src/codegen_ops_fpu_misc.c
Normal file
111
src/codegen_ops_fpu_misc.c
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "x87.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_fpu_misc.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg));
|
||||||
|
uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg));
|
||||||
|
uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg));
|
||||||
|
fpu_PUSH(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
|
||||||
|
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
|
||||||
|
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
|
||||||
|
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
|
||||||
|
fpu_POP(block, ir);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV(ir, IREG_AX, IREG_NPXS);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV(ir, IREG_temp0_D, IREG_ST(0));
|
||||||
|
uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0));
|
||||||
|
uop_MOV(ir, IREG_temp2, IREG_tag(0));
|
||||||
|
uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg));
|
||||||
|
uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg));
|
||||||
|
uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg));
|
||||||
|
uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D);
|
||||||
|
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q);
|
||||||
|
uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
12
src/codegen_ops_fpu_misc.h
Normal file
12
src/codegen_ops_fpu_misc.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
65
src/codegen_ops_helpers.c
Normal file
65
src/codegen_ops_helpers.c
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ir_defs.h"
|
||||||
|
#include "codegen_reg.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||||
|
{
|
||||||
|
/*Word access that crosses two pages. Perform reads from both pages, shift and combine*/
|
||||||
|
uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr));
|
||||||
|
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1));
|
||||||
|
uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8);
|
||||||
|
uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||||
|
{
|
||||||
|
/*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/
|
||||||
|
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3));
|
||||||
|
uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3));
|
||||||
|
uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8);
|
||||||
|
uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8);
|
||||||
|
uop_OR(ir, dest_reg, dest_reg, IREG_temp3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNROLL_MAX_REG_REFERENCES 200
|
||||||
|
#define UNROLL_MAX_UOPS 1000
|
||||||
|
#define UNROLL_MAX_COUNT 10
|
||||||
|
int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
int max_unroll;
|
||||||
|
int first_instruction;
|
||||||
|
|
||||||
|
/*Check that dest instruction was actually compiled into block*/
|
||||||
|
start = codegen_get_instruction_uop(block, dest_addr, &first_instruction);
|
||||||
|
|
||||||
|
/*Couldn't find any uOPs corresponding to the destination instruction*/
|
||||||
|
if (start == -1)
|
||||||
|
{
|
||||||
|
/*Is instruction jumping to itself?*/
|
||||||
|
if (dest_addr != cpu_state.oldpc)
|
||||||
|
{
|
||||||
|
// pclog("Couldn't find start. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
start = ir->wr_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6);
|
||||||
|
if (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))
|
||||||
|
max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount);
|
||||||
|
if (max_unroll > UNROLL_MAX_COUNT)
|
||||||
|
max_unroll = UNROLL_MAX_COUNT;
|
||||||
|
if (max_unroll <= 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_ir_set_unroll(max_unroll, start, first_instruction);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
126
src/codegen_ops_helpers.h
Normal file
126
src/codegen_ops_helpers.h
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen_backend.h"
|
||||||
|
|
||||||
|
static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset)
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
if (offset)
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset);
|
||||||
|
return IREG_eaaddr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return IREG_ESP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (offset)
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset);
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W);
|
||||||
|
return IREG_eaaddr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
return IREG_eaaddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int LOAD_SP(ir_data_t *ir)
|
||||||
|
{
|
||||||
|
return LOAD_SP_WITH_OFFSET(ir, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ADD_SP(ir_data_t *ir, int offset)
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset);
|
||||||
|
else
|
||||||
|
uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset);
|
||||||
|
}
|
||||||
|
static inline void SUB_SP(ir_data_t *ir, int offset)
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset);
|
||||||
|
else
|
||||||
|
uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void fpu_POP(codeblock_t *block, ir_data_t *ir)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_STATIC_TOP)
|
||||||
|
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1);
|
||||||
|
else
|
||||||
|
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
|
||||||
|
}
|
||||||
|
static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_STATIC_TOP)
|
||||||
|
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2);
|
||||||
|
else
|
||||||
|
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2);
|
||||||
|
}
|
||||||
|
static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_STATIC_TOP)
|
||||||
|
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1);
|
||||||
|
else
|
||||||
|
uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset)
|
||||||
|
{
|
||||||
|
if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) ||
|
||||||
|
(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout);
|
||||||
|
if (end_offset)
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset);
|
||||||
|
uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||||
|
{
|
||||||
|
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
|
||||||
|
static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||||
|
{
|
||||||
|
if ((addr & 0xfff) == 0xfff)
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr);
|
||||||
|
else
|
||||||
|
uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
|
||||||
|
static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
|
||||||
|
{
|
||||||
|
if ((addr & 0xfff) >= 0xffd)
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr);
|
||||||
|
else
|
||||||
|
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr);
|
||||||
|
static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*Is dest within block?*/
|
||||||
|
if (dest_addr > next_pc)
|
||||||
|
return 0;
|
||||||
|
if ((cs+dest_addr) < block->pc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return codegen_can_unroll_full(block, ir, next_pc, dest_addr);
|
||||||
|
}
|
||||||
289
src/codegen_ops_jump.c
Normal file
289
src/codegen_ops_jump.c
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
#include "codegen_ops_mov.h"
|
||||||
|
|
||||||
|
uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
|
||||||
|
uint32_t dest_addr = op_pc+1+offset;
|
||||||
|
|
||||||
|
if (!(op_32 & 0x100))
|
||||||
|
dest_addr &= 0xffff;
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
return dest_addr;
|
||||||
|
}
|
||||||
|
uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
|
||||||
|
uint32_t dest_addr = op_pc+2+offset;
|
||||||
|
|
||||||
|
dest_addr &= 0xffff;
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return dest_addr;
|
||||||
|
}
|
||||||
|
uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t offset = fastreadl(cs + op_pc);
|
||||||
|
uint32_t dest_addr = op_pc+4+offset;
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
return dest_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t new_pc = fastreadw(cs + op_pc);
|
||||||
|
uint16_t new_cs = fastreadw(cs + op_pc + 2);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, new_pc);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
|
||||||
|
uop_CALL_FUNC(ir, loadcsjmp);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t new_pc = fastreadl(cs + op_pc);
|
||||||
|
uint16_t new_cs = fastreadw(cs + op_pc + 4);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, new_pc);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
|
||||||
|
uop_CALL_FUNC(ir, loadcsjmp);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 6);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
|
||||||
|
uint16_t ret_addr = op_pc + 2;
|
||||||
|
uint16_t dest_addr = ret_addr + offset;
|
||||||
|
int sp_reg;
|
||||||
|
|
||||||
|
dest_addr &= 0xffff;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
|
||||||
|
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr);
|
||||||
|
SUB_SP(ir, 2);
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t offset = fastreadl(cs + op_pc);
|
||||||
|
uint32_t ret_addr = op_pc + 4;
|
||||||
|
uint32_t dest_addr = ret_addr + offset;
|
||||||
|
int sp_reg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
|
||||||
|
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr);
|
||||||
|
SUB_SP(ir, 4);
|
||||||
|
uop_MOV_IMM(ir, IREG_pc, dest_addr);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
|
||||||
|
}
|
||||||
|
ADD_SP(ir, 2);
|
||||||
|
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
|
||||||
|
}
|
||||||
|
ADD_SP(ir, 4);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t offset = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
|
||||||
|
}
|
||||||
|
ADD_SP(ir, 2+offset);
|
||||||
|
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t offset = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
|
||||||
|
}
|
||||||
|
ADD_SP(ir, 4+offset);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
|
||||||
|
}
|
||||||
|
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
|
||||||
|
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
|
||||||
|
uop_CALL_FUNC(ir, loadcs);
|
||||||
|
ADD_SP(ir, 4);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
|
||||||
|
}
|
||||||
|
uop_MOV(ir, IREG_pc, IREG_temp0);
|
||||||
|
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
|
||||||
|
uop_CALL_FUNC(ir, loadcs);
|
||||||
|
ADD_SP(ir, 8);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t offset;
|
||||||
|
|
||||||
|
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
offset = fastreadw(cs + op_pc);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
|
||||||
|
}
|
||||||
|
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
|
||||||
|
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
|
||||||
|
uop_CALL_FUNC(ir, loadcs);
|
||||||
|
ADD_SP(ir, 4+offset);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t offset;
|
||||||
|
|
||||||
|
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
offset = fastreadw(cs + op_pc);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
|
||||||
|
}
|
||||||
|
uop_MOV(ir, IREG_pc, IREG_temp0);
|
||||||
|
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
|
||||||
|
uop_CALL_FUNC(ir, loadcs);
|
||||||
|
ADD_SP(ir, 8+offset);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
@ -1,270 +1,21 @@
|
||||||
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
uint32_t offset = fetchdat & 0xff;
|
uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
if (offset & 0x80)
|
uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
offset |= 0xffffff00;
|
uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
|
uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
return -1;
|
uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
}
|
uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
uint16_t offset = fetchdat & 0xffff;
|
|
||||||
|
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
|
uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
return -1;
|
uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
}
|
uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
|
||||||
804
src/codegen_ops_logic.c
Normal file
804
src/codegen_ops_logic.c
Normal file
|
|
@ -0,0 +1,804 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
#include "codegen_ops_logic.h"
|
||||||
|
|
||||||
|
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint8_t imm_data = fastreadb(cs + op_pc);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t imm_data = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||||
|
uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fetchdat = fastreadl(cs + op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_EAX);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 4;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint8_t imm_data = fastreadb(cs + op_pc);
|
||||||
|
|
||||||
|
uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t imm_data = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||||
|
uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fetchdat = fastreadl(cs + op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_EAX);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
return op_pc + 4;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
uop_MOV(ir, IREG_flags_res, dest_reg);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint8_t imm_data = fastreadb(cs + op_pc);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t imm_data = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||||
|
uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fetchdat = fastreadl(cs + op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
return op_pc + 4;
|
||||||
|
}
|
||||||
|
uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint8_t imm_data = fastreadb(cs + op_pc);
|
||||||
|
|
||||||
|
uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t imm_data = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
|
||||||
|
uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fetchdat = fastreadl(cs + op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_EAX);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
return op_pc + 4;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
uop_MOV(ir, IREG_flags_res, dest_reg);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
@ -1,564 +1,36 @@
|
||||||
#define ROP_LOGIC(name, op, writeback) \
|
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{ \
|
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
int src_reg, dst_reg; \
|
uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
x86seg *target_seg; \
|
uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
\
|
uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
if ((fetchdat & 0xc0) == 0xc0) \
|
uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{ \
|
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
dst_reg = LOAD_REG_B(fetchdat & 7); \
|
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
} \
|
|
||||||
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)
|
uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
ROP_LOGIC(OR, OR, 1)
|
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
ROP_LOGIC(XOR, XOR, 1)
|
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
int src_reg, dst_reg;
|
uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
src_reg = LOAD_REG_B(fetchdat & 7);
|
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
}
|
uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
else
|
uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
611
src/codegen_ops_misc.c
Normal file
611
src/codegen_ops_misc.c
Normal file
|
|
@ -0,0 +1,611 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
#include "codegen_ops_misc.h"
|
||||||
|
|
||||||
|
uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W);
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr);
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg = NULL;
|
||||||
|
uint8_t imm_data;
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
if (fetchdat & 0x20)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
reg = IREG_8(fetchdat & 7);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
else
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
reg = IREG_temp0_B;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: case 0x08: /*TEST*/
|
||||||
|
imm_data = fastreadb(cs + op_pc + 1);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc+2;
|
||||||
|
|
||||||
|
case 0x10: /*NOT*/
|
||||||
|
uop_XOR_IMM(ir, reg, reg, 0xff);
|
||||||
|
if ((fetchdat & 0xc0) != 0xc0)
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x18: /*NEG*/
|
||||||
|
uop_MOV_IMM(ir, IREG_temp1_B, 0);
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_flags_op2, reg);
|
||||||
|
uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
|
||||||
|
uop_MOV(ir, reg, IREG_temp1_B);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
|
||||||
|
uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
|
||||||
|
}
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op1, 0);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg = NULL;
|
||||||
|
uint16_t imm_data;
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
if (fetchdat & 0x20)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
reg = IREG_16(fetchdat & 7);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
else
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
reg = IREG_temp0_W;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: case 0x08: /*TEST*/
|
||||||
|
imm_data = fastreadw(cs + op_pc + 1);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 2);
|
||||||
|
return op_pc+3;
|
||||||
|
|
||||||
|
case 0x10: /*NOT*/
|
||||||
|
uop_XOR_IMM(ir, reg, reg, 0xffff);
|
||||||
|
if ((fetchdat & 0xc0) != 0xc0)
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x18: /*NEG*/
|
||||||
|
uop_MOV_IMM(ir, IREG_temp1_W, 0);
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_flags_op2, reg);
|
||||||
|
uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
|
||||||
|
uop_MOV(ir, reg, IREG_temp1_W);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
|
||||||
|
}
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op1, 0);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg = NULL;
|
||||||
|
uint32_t imm_data;
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
if (fetchdat & 0x20)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
reg = IREG_32(fetchdat & 7);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
else
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
reg = IREG_temp0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: case 0x08: /*TEST*/
|
||||||
|
imm_data = fastreadl(cs + op_pc + 1);
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_flags_res, reg, imm_data);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 4);
|
||||||
|
return op_pc+5;
|
||||||
|
|
||||||
|
case 0x10: /*NOT*/
|
||||||
|
uop_XOR_IMM(ir, reg, reg, 0xffffffff);
|
||||||
|
if ((fetchdat & 0xc0) != 0xc0)
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x18: /*NEG*/
|
||||||
|
uop_MOV_IMM(ir, IREG_temp1, 0);
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOV(ir, IREG_flags_op2, reg);
|
||||||
|
uop_SUB(ir, IREG_temp1, IREG_temp1, reg);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||||
|
uop_MOV(ir, reg, IREG_temp1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_SUB(ir, IREG_temp1, IREG_temp1, reg);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
|
||||||
|
uop_MOV(ir, IREG_flags_op2, IREG_temp0);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||||
|
}
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op1, 0);
|
||||||
|
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rebuild_c(ir_data_t *ir)
|
||||||
|
{
|
||||||
|
int needs_rebuild = 1;
|
||||||
|
|
||||||
|
if (codegen_flags_changed)
|
||||||
|
{
|
||||||
|
switch (cpu_state.flags_op)
|
||||||
|
{
|
||||||
|
case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32:
|
||||||
|
case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32:
|
||||||
|
needs_rebuild = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_rebuild)
|
||||||
|
{
|
||||||
|
uop_CALL_FUNC(ir, flags_rebuild_c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg = NULL;
|
||||||
|
int src_reg, sp_reg;
|
||||||
|
|
||||||
|
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
if ((fetchdat & 0x38) == 0x28)
|
||||||
|
return 0;
|
||||||
|
src_reg = IREG_16(fetchdat & 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
if (!(fetchdat & 0x30)) /*INC/DEC*/
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
else
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
src_reg = IREG_temp0_W;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: /*INC*/
|
||||||
|
rebuild_c(ir);
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_ADD_IMM(ir, src_reg, src_reg, 1);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, src_reg);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16);
|
||||||
|
}
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x08: /*DEC*/
|
||||||
|
rebuild_c(ir);
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOVZX(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_SUB_IMM(ir, src_reg, src_reg, 1);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, src_reg);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
|
||||||
|
uop_MOVZX(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16);
|
||||||
|
}
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x10: /*CALL*/
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
|
||||||
|
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1);
|
||||||
|
SUB_SP(ir, 2);
|
||||||
|
uop_MOVZX(ir, IREG_pc, src_reg);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0x20: /*JMP*/
|
||||||
|
uop_MOVZX(ir, IREG_pc, src_reg);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0x28: /*JMP far*/
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2);
|
||||||
|
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc);
|
||||||
|
uop_CALL_FUNC(ir, loadcsjmp);
|
||||||
|
uop_MOVZX(ir, IREG_pc, src_reg);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0x30: /*PUSH*/
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
|
||||||
|
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg);
|
||||||
|
SUB_SP(ir, 2);
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg = NULL;
|
||||||
|
int src_reg, sp_reg;
|
||||||
|
|
||||||
|
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
if ((fetchdat & 0x38) == 0x28)
|
||||||
|
return 0;
|
||||||
|
src_reg = IREG_32(fetchdat & 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
if (!(fetchdat & 0x30)) /*INC/DEC*/
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
else
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
src_reg = IREG_temp0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: /*INC*/
|
||||||
|
rebuild_c(ir);
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOV(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_ADD_IMM(ir, src_reg, src_reg, 1);
|
||||||
|
uop_MOV(ir, IREG_flags_res, src_reg);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_ADD_IMM(ir, IREG_temp1, src_reg, 1);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
|
||||||
|
uop_MOV(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32);
|
||||||
|
}
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x08: /*DEC*/
|
||||||
|
rebuild_c(ir);
|
||||||
|
codegen_flags_changed = 1;
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOV(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_SUB_IMM(ir, src_reg, src_reg, 1);
|
||||||
|
uop_MOV(ir, IREG_flags_res, src_reg);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_SUB_IMM(ir, IREG_temp1, src_reg, 1);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
|
||||||
|
uop_MOV(ir, IREG_flags_op1, src_reg);
|
||||||
|
uop_MOV(ir, IREG_flags_res, IREG_temp1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op2, 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32);
|
||||||
|
}
|
||||||
|
return op_pc+1;
|
||||||
|
|
||||||
|
case 0x10: /*CALL*/
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
|
||||||
|
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1);
|
||||||
|
SUB_SP(ir, 4);
|
||||||
|
uop_MOV(ir, IREG_pc, src_reg);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0x20: /*JMP*/
|
||||||
|
uop_MOV(ir, IREG_pc, src_reg);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0x28: /*JMP far*/
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4);
|
||||||
|
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
|
||||||
|
uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc);
|
||||||
|
uop_CALL_FUNC(ir, loadcsjmp);
|
||||||
|
uop_MOV(ir, IREG_pc, src_reg);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case 0x30: /*PUSH*/
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
|
||||||
|
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg);
|
||||||
|
SUB_SP(ir, 4);
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_MOVSX(ir, IREG_AX, IREG_AL);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_MOVSX(ir, IREG_EAX, IREG_AX);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ropLxS(name, seg) \
|
||||||
|
uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg = NULL; \
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7; \
|
||||||
|
\
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0) \
|
||||||
|
return 0; \
|
||||||
|
\
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \
|
||||||
|
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
|
||||||
|
uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \
|
||||||
|
\
|
||||||
|
if (seg == &cpu_state.seg_ss) \
|
||||||
|
CPU_BLOCK_END(); \
|
||||||
|
\
|
||||||
|
return op_pc + 1; \
|
||||||
|
} \
|
||||||
|
uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg = NULL; \
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7; \
|
||||||
|
\
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0) \
|
||||||
|
return 0; \
|
||||||
|
\
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \
|
||||||
|
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
|
||||||
|
uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \
|
||||||
|
\
|
||||||
|
if (seg == &cpu_state.seg_ss) \
|
||||||
|
CPU_BLOCK_END(); \
|
||||||
|
\
|
||||||
|
return op_pc + 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropLxS(LDS, &cpu_state.seg_ds)
|
||||||
|
ropLxS(LES, &cpu_state.seg_es)
|
||||||
|
ropLxS(LFS, &cpu_state.seg_fs)
|
||||||
|
ropLxS(LGS, &cpu_state.seg_gs)
|
||||||
|
ropLxS(LSS, &cpu_state.seg_ss)
|
||||||
|
|
||||||
|
uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_CALL_FUNC(ir, flags_rebuild);
|
||||||
|
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_CALL_FUNC(ir, flags_rebuild);
|
||||||
|
uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_CALL_FUNC(ir, flags_rebuild);
|
||||||
|
uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG);
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
@ -1,269 +1,37 @@
|
||||||
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
return op_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
CLEAR_BITS((uintptr_t)&flags, D_FLAG);
|
uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
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)
|
uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
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)
|
uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
|
||||||
x86seg *target_seg = NULL;
|
|
||||||
int host_reg;
|
|
||||||
|
|
||||||
if ((fetchdat & 0x30) != 0x00)
|
uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
return 0;
|
uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
uint32_t ropLDS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLDS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLFS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLFS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLGS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLGS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLSS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropLSS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
if ((fetchdat & 0xc0) == 0xc0)
|
uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
else
|
uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t 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);
|
|
||||||
|
|
||||||
SAVE_EA();
|
uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
MEM_CHECK_WRITE(target_seg);
|
uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fetchdat & 0x38)
|
uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
{
|
uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
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;
|
|
||||||
}
|
|
||||||
57
src/codegen_ops_mmx_arith.c
Normal file
57
src/codegen_ops_mmx_arith.c
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_mmx_arith.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
#define ropParith(func) \
|
||||||
|
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7; \
|
||||||
|
\
|
||||||
|
uop_MMX_ENTER(ir); \
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0) \
|
||||||
|
{ \
|
||||||
|
int src_reg = fetchdat & 7; \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return op_pc + 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropParith(PADDB)
|
||||||
|
ropParith(PADDW)
|
||||||
|
ropParith(PADDD)
|
||||||
|
ropParith(PADDSB)
|
||||||
|
ropParith(PADDSW)
|
||||||
|
ropParith(PADDUSB)
|
||||||
|
ropParith(PADDUSW)
|
||||||
|
|
||||||
|
ropParith(PSUBB)
|
||||||
|
ropParith(PSUBW)
|
||||||
|
ropParith(PSUBD)
|
||||||
|
ropParith(PSUBSB)
|
||||||
|
ropParith(PSUBSW)
|
||||||
|
ropParith(PSUBUSB)
|
||||||
|
ropParith(PSUBUSW)
|
||||||
|
|
||||||
|
ropParith(PMADDWD)
|
||||||
|
ropParith(PMULHW)
|
||||||
|
ropParith(PMULLW)
|
||||||
19
src/codegen_ops_mmx_arith.h
Normal file
19
src/codegen_ops_mmx_arith.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
uint32_t ropPADDB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPADDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPADDD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPADDSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPADDSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPADDUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPADDUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropPSUBB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSUBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSUBD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSUBSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSUBSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSUBUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSUBUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropPMADDWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPMULHW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPMULLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
44
src/codegen_ops_mmx_cmp.c
Normal file
44
src/codegen_ops_mmx_cmp.c
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_mmx_cmp.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
#define ropPcmp(func) \
|
||||||
|
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7; \
|
||||||
|
\
|
||||||
|
uop_MMX_ENTER(ir); \
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0) \
|
||||||
|
{ \
|
||||||
|
int src_reg = fetchdat & 7; \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return op_pc + 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropPcmp(PCMPEQB)
|
||||||
|
ropPcmp(PCMPEQW)
|
||||||
|
ropPcmp(PCMPEQD)
|
||||||
|
ropPcmp(PCMPGTB)
|
||||||
|
ropPcmp(PCMPGTW)
|
||||||
|
ropPcmp(PCMPGTD)
|
||||||
6
src/codegen_ops_mmx_cmp.h
Normal file
6
src/codegen_ops_mmx_cmp.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
uint32_t ropPCMPEQB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPCMPEQW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPCMPEQD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPCMPGTB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPCMPGTW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPCMPGTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
110
src/codegen_ops_mmx_loadstore.c
Normal file
110
src/codegen_ops_mmx_loadstore.c
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_mmx_loadstore.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
|
||||||
|
uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
5
src/codegen_ops_mmx_loadstore.h
Normal file
5
src/codegen_ops_mmx_loadstore.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
108
src/codegen_ops_mmx_logic.c
Normal file
108
src/codegen_ops_mmx_logic.c
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_mmx_logic.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
4
src/codegen_ops_mmx_logic.h
Normal file
4
src/codegen_ops_mmx_logic.h
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
47
src/codegen_ops_mmx_pack.c
Normal file
47
src/codegen_ops_mmx_pack.c
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_mmx_pack.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
#define ropPpack(func) \
|
||||||
|
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||||
|
{ \
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7; \
|
||||||
|
\
|
||||||
|
uop_MMX_ENTER(ir); \
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1); \
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0) \
|
||||||
|
{ \
|
||||||
|
int src_reg = fetchdat & 7; \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
x86seg *target_seg; \
|
||||||
|
\
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||||
|
codegen_check_seg_read(block, ir, target_seg); \
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||||
|
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return op_pc + 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ropPpack(PACKSSWB)
|
||||||
|
ropPpack(PACKSSDW)
|
||||||
|
ropPpack(PACKUSWB)
|
||||||
|
ropPpack(PUNPCKLBW)
|
||||||
|
ropPpack(PUNPCKLWD)
|
||||||
|
ropPpack(PUNPCKLDQ)
|
||||||
|
ropPpack(PUNPCKHBW)
|
||||||
|
ropPpack(PUNPCKHWD)
|
||||||
|
ropPpack(PUNPCKHDQ)
|
||||||
9
src/codegen_ops_mmx_pack.h
Normal file
9
src/codegen_ops_mmx_pack.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
uint32_t ropPACKSSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPACKSSDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPACKUSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPUNPCKLBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPUNPCKLWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPUNPCKLDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPUNPCKHBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPUNPCKHWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPUNPCKHDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
93
src/codegen_ops_mmx_shift.c
Normal file
93
src/codegen_ops_mmx_shift.c
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "x86_flags.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_accumulate.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_mmx_shift.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
|
||||||
|
uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg = fetchdat & 7;
|
||||||
|
int op = fetchdat & 0x38;
|
||||||
|
int shift = fastreadb(cs + op_pc + 1);
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x10: /*PSRLW*/
|
||||||
|
uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
case 0x20: /*PSRAW*/
|
||||||
|
uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
case 0x30: /*PSLLW*/
|
||||||
|
uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg = fetchdat & 7;
|
||||||
|
int op = fetchdat & 0x38;
|
||||||
|
int shift = fastreadb(cs + op_pc + 1);
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x10: /*PSRLD*/
|
||||||
|
uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
case 0x20: /*PSRAD*/
|
||||||
|
uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
case 0x30: /*PSLLD*/
|
||||||
|
uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg = fetchdat & 7;
|
||||||
|
int op = fetchdat & 0x38;
|
||||||
|
int shift = fastreadb(cs + op_pc + 1);
|
||||||
|
|
||||||
|
uop_MMX_ENTER(ir);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x10: /*PSRLQ*/
|
||||||
|
uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
case 0x20: /*PSRAQ*/
|
||||||
|
uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
case 0x30: /*PSLLQ*/
|
||||||
|
uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
7
src/codegen_ops_mmx_shift.h
Normal file
7
src/codegen_ops_mmx_shift.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropPSLLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSLLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropPSLLQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
772
src/codegen_ops_mov.c
Normal file
772
src/codegen_ops_mov.c
Normal file
|
|
@ -0,0 +1,772 @@
|
||||||
|
#include "ibm.h"
|
||||||
|
|
||||||
|
#include "x86.h"
|
||||||
|
#include "386_common.h"
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "codegen_ir.h"
|
||||||
|
#include "codegen_ops.h"
|
||||||
|
#include "codegen_ops_helpers.h"
|
||||||
|
#include "codegen_ops_mov.h"
|
||||||
|
|
||||||
|
uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint8_t imm = fastreadb(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_8(opcode & 7), imm);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint16_t imm = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_16(opcode & 7), imm);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fetchdat = fastreadl(cs + op_pc);
|
||||||
|
uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
}
|
||||||
|
return op_pc + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
// if (block->phys == 0x49a400)
|
||||||
|
// pclog("ropMOVb_rmarkcode %08x 1\n", cs+op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
addr = fastreadl(cs + op_pc);
|
||||||
|
else
|
||||||
|
addr = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
codegen_check_seg_read(block, ir, op_ea_seg);
|
||||||
|
uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
|
||||||
|
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
addr = fastreadl(cs + op_pc);
|
||||||
|
else
|
||||||
|
addr = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
codegen_check_seg_read(block, ir, op_ea_seg);
|
||||||
|
uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
|
||||||
|
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t addr = 0;
|
||||||
|
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
{
|
||||||
|
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
|
||||||
|
{
|
||||||
|
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = fastreadl(cs + op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr = fastreadw(cs + op_pc);
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
codegen_check_seg_read(block, ir, op_ea_seg);
|
||||||
|
if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200))
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr);
|
||||||
|
else
|
||||||
|
uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr);
|
||||||
|
|
||||||
|
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
addr = fastreadl(cs + op_pc);
|
||||||
|
else
|
||||||
|
addr = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
codegen_check_seg_write(block, ir, op_ea_seg);
|
||||||
|
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
|
||||||
|
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
addr = fastreadl(cs + op_pc);
|
||||||
|
else
|
||||||
|
addr = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
codegen_check_seg_write(block, ir, op_ea_seg);
|
||||||
|
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
|
||||||
|
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
|
||||||
|
if (op_32 & 0x200)
|
||||||
|
addr = fastreadl(cs + op_pc);
|
||||||
|
else
|
||||||
|
addr = fastreadw(cs + op_pc);
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
codegen_check_seg_write(block, ir, op_ea_seg);
|
||||||
|
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
|
||||||
|
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
uint8_t imm;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
imm = fastreadb(cs + op_pc + 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_8(dest_reg), imm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
imm = fastreadb(cs + op_pc + 1);
|
||||||
|
uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 1);
|
||||||
|
return op_pc + 2;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
uint16_t imm;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
imm = fastreadw(cs + op_pc + 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_16(dest_reg), imm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
imm = fastreadw(cs + op_pc + 1);
|
||||||
|
uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 2);
|
||||||
|
return op_pc + 3;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
uint32_t imm;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
|
||||||
|
imm = fastreadl(cs + op_pc + 1);
|
||||||
|
uop_MOV_IMM(ir, IREG_32(dest_reg), imm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
imm = fastreadl(cs + op_pc + 1);
|
||||||
|
uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc+1, 4);
|
||||||
|
return op_pc + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: /*ES*/
|
||||||
|
src_reg = IREG_ES_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x08: /*CS*/
|
||||||
|
src_reg = IREG_CS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x18: /*DS*/
|
||||||
|
src_reg = IREG_DS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x10: /*SS*/
|
||||||
|
src_reg = IREG_SS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x20: /*FS*/
|
||||||
|
src_reg = IREG_FS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x28: /*GS*/
|
||||||
|
src_reg = IREG_GS_seg_W;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOV(ir, IREG_16(dest_reg), src_reg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: /*ES*/
|
||||||
|
src_reg = IREG_ES_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x08: /*CS*/
|
||||||
|
src_reg = IREG_CS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x18: /*DS*/
|
||||||
|
src_reg = IREG_DS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x10: /*SS*/
|
||||||
|
src_reg = IREG_SS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x20: /*FS*/
|
||||||
|
src_reg = IREG_FS_seg_W;
|
||||||
|
break;
|
||||||
|
case 0x28: /*GS*/
|
||||||
|
src_reg = IREG_GS_seg_W;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int dest_reg = fetchdat & 7;
|
||||||
|
uop_MOVZX(ir, IREG_32(dest_reg), src_reg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int src_reg;
|
||||||
|
x86seg *rseg;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
switch (fetchdat & 0x38)
|
||||||
|
{
|
||||||
|
case 0x00: /*ES*/
|
||||||
|
rseg = &cpu_state.seg_es;
|
||||||
|
break;
|
||||||
|
case 0x18: /*DS*/
|
||||||
|
rseg = &cpu_state.seg_ds;
|
||||||
|
break;
|
||||||
|
case 0x20: /*FS*/
|
||||||
|
rseg = &cpu_state.seg_fs;
|
||||||
|
break;
|
||||||
|
case 0x28: /*GS*/
|
||||||
|
rseg = &cpu_state.seg_gs;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7));
|
||||||
|
src_reg = IREG_temp0_W;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
src_reg = IREG_temp0_W;
|
||||||
|
}
|
||||||
|
|
||||||
|
uop_LOAD_SEG(ir, rseg, src_reg);
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int dest_reg = (fetchdat >> 3) & 7;
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int src_reg = fetchdat & 7;
|
||||||
|
uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_read(block, ir, target_seg);
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg2 = IREG_16(opcode & 7);
|
||||||
|
|
||||||
|
uop_MOV(ir, IREG_temp0_W, IREG_AX);
|
||||||
|
uop_MOV(ir, IREG_AX, reg2);
|
||||||
|
uop_MOV(ir, reg2, IREG_temp0_W);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg2 = IREG_32(opcode & 7);
|
||||||
|
|
||||||
|
uop_MOV(ir, IREG_temp0, IREG_EAX);
|
||||||
|
uop_MOV(ir, IREG_EAX, reg2);
|
||||||
|
uop_MOV(ir, reg2, IREG_temp0);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg1 = IREG_8((fetchdat >> 3) & 7);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int reg2 = IREG_8(fetchdat & 7);
|
||||||
|
|
||||||
|
uop_MOV(ir, IREG_temp0_B, reg1);
|
||||||
|
uop_MOV(ir, reg1, reg2);
|
||||||
|
uop_MOV(ir, reg2, IREG_temp0_B);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
|
||||||
|
uop_MOV(ir, reg1, IREG_temp0_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg1 = IREG_16((fetchdat >> 3) & 7);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int reg2 = IREG_16(fetchdat & 7);
|
||||||
|
|
||||||
|
uop_MOV(ir, IREG_temp0_W, reg1);
|
||||||
|
uop_MOV(ir, reg1, reg2);
|
||||||
|
uop_MOV(ir, reg2, IREG_temp0_W);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
|
||||||
|
uop_MOV(ir, reg1, IREG_temp0_W);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
int reg1 = IREG_32((fetchdat >> 3) & 7);
|
||||||
|
|
||||||
|
codegen_mark_code_present(block, cs+op_pc, 1);
|
||||||
|
if ((fetchdat & 0xc0) == 0xc0)
|
||||||
|
{
|
||||||
|
int reg2 = IREG_32(fetchdat & 7);
|
||||||
|
|
||||||
|
uop_MOV(ir, IREG_temp0, reg1);
|
||||||
|
uop_MOV(ir, reg1, reg2);
|
||||||
|
uop_MOV(ir, reg2, IREG_temp0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
|
||||||
|
uop_MOV(ir, reg1, IREG_temp0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op_pc + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
|
||||||
|
uop_MOVZX(ir, IREG_eaaddr, IREG_AL);
|
||||||
|
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX);
|
||||||
|
if (!(op_32 & 0x200))
|
||||||
|
uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff);
|
||||||
|
|
||||||
|
uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue