Mercurial > hg > release > icedtea6-1.11
changeset 1909:30881dc8076c
Merge
author | Andrew John Hughes <ahughes@redhat.com> |
---|---|
date | Thu, 28 Jan 2010 16:34:49 +0000 |
parents | ac7b942245f2 (current diff) bb0e039df90a (diff) |
children | 2e9cc3b3a882 |
files | ChangeLog Makefile.am acinclude.m4 configure.ac |
diffstat | 15 files changed, 10696 insertions(+), 5816 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Jan 21 02:04:50 2010 +0000 +++ b/ChangeLog Thu Jan 28 16:34:49 2010 +0000 @@ -1,3 +1,167 @@ +2010-01-27 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: Reference plugin + directory by absolute path in EXTRA_DIST + to avoid confusion with build rule. + +2010-01-27 Andrew John Hughes <ahughes@redhat.com> + + * NEWS: Updated for 1.7 release. + +2010-01-27 Andrew John Hughes <ahughes@redhat.com> + + * HACKING: Document new patch. + * Makefile.am: Add new patch. + * patches/libpng.patch: + Patch splashscreen code so that + it will build against libpng 1.4 + (png_check_sig --> png_sig_cmp) + +2010-01-27 Andrew John Hughes <ahughes@redhat.com> + + * NEWS: + Add missing items for 1.5.1, 1.5.2, + 1.5.3, 1.6.1 and 1.6.2. + +2010-01-27 Edward Nevill <ed@camswl.com> + + * ports/hotspot/src/cpu/zero/vm/thumb2.cpp + Forgot to do hg add on this file in my last commit + +2010-01-26 Deepak Bhole <dbhole@redhat.com> + + * NEWS: Added message about alpha release for the new NPR based plugin. + +2010-01-27 Matthias Klose <doko@ubuntu.com> + + * Makefile.am: Remove quoting from ICEDTEA_NAME ICEDTEA_REV + ICEDTEA_PKG. + +2010-01-26 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + (stamps/plugin-tests.stamp): Add + a target for building the plugin tests. + (plugin-tests): Alias for the above. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * acinclude.m4: + (IT_CHECK_OLD_PLUGIN): New macro for + --enable/disable-plugin. + (IT_CHECK_NEW_PLUGIN): Likewise for + --enable/disable-npplugin. + (IT_CHECK_PLUGIN_DEPENDENCIES): New macro + to run pkg-config checks. Enables the new + plugin if xulrunner 1.9.2 or above is + detected. + (IT_CHECK_XULRUNNER_VERSION): Obtain the + XULrunner vgersion for MOZILLA_VERSION_COLLAPSED. + * configure.ac: + Replace old plugin stuff with a single call + to IT_CHECK_XULRUNNER_VERSION (which depends + on the other macros). + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Build NPPlugin source files separately. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Fix ICEDTEAPLUGIN_TARGET to use new + stamp targets and remove redundant + ICEDTEANPPPLUGIN_TARGET. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Use NPPLUGIN_SRCDIR for Java plugin sources. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Provide stamp targets for both npplugin + and the old plugin so 'make plugin' builds + the one configured. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Remove trailing space after IcedTea version + in plugin version information when package + version is not set. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Build NPPlugin in the build directory, + not the source tree. + +2010-01-22 Deepak Bhole <dbhole@redhat.com> + + * Makefile.am: + Use MOZILLA_CFLAGS/LIBS rather than + XULRUNNER. + * configure.ac: + Check for Mozilla not XULrunner. + Bring in libxul-unstable as well. + * plugin/icedteanp/IcedTeaNPPlugin.cc: + Use PRInt32 rather than PRInt32_t for port. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * IcedTeaPlugin.cc: + Standardise plugin versioning. + * Makefile.am: + Set ICEDTEA_NAME and use in place of literal + "IcedTea6". Use HAS_PKGVERSION to set ICEDTEA_PKG + and output DISTRO_PACKAGE_VERSION rather than + running test. Set PLUGIN_VERSION and use for + both plugins. + * acinclude.m4: + (IT_GET_PKGVERSION): Moved from configure.ac and + changed to a macro with output. + (IT_GET_LSB_DATA): Depend on IT_GET_PKGVERSION. + * configure.ac: + Invoke new IT_GET_PKGVERSION macro. + * plugin/icedteanp/IcedTeaNPPlugin.cc: + Standardise plugin versioning. + +2010-01-25 Andrew John Hughes <ahughes@redhat.com> + + * patches/icedtea-libraries.patch: + Make all dlopen choices at build-time, + not just one. Support libjpeg8 as well. + +2010-01-21 Andrew John Hughes <ahughes@redhat.com> + + PR icedtea/433 + * Makefile.am: + Add set -e to tarball extractions so + that they fail immediately. + +2010-01-21 Edward Nevill <ed@camswl.com> + + * zeroshark.make, asm_helper.cpp, bytecodes_arm.def, + cppInterpreter_arm.S, thumb2.cpp (new file) + Added Thumb2 JIT (not build as default - yet) + Removal of, more, hard coded constants + Move 'complex' bytecodes from cppInterpreter_arm.S to asm_helper.cpp + General tidying up of cppInterpreter_arm.S + +2010-01-21 Matthias Klose <doko@ubuntu.com> + + * Makefile.am: Don't hide errors in statement sequences building + the NPPlugin. Use ICEDTEA_REV to defined PLUGIN_VERSION. + +2010-01-21 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Fix paths to patches and IcedTeaNPPlugin.cc + for make dist. + 2010-01-20 Andrew John Hughes <ahughes@redhat.com> * Makefile.am: @@ -23,6 +187,23 @@ Create a link from client to server after CACAO install to make openjdk find the expected client dir on 32bit systems. +2010-01-08 Andrew John Hughes <ahughes@redhat.com> + + * Makefile.am: + Calculate JDK and HotSpot Mercurial revisions + if available and pass to build. Also pass + DIST_NAME to build. + * acinclude.m4: + (IT_GET_LSB_DATA): Moved from configure.ac + and extended to also obtain the name of + the distribution from either lsb_release -is + or $build_os. + * configure.ac: + Invoke IT_GET_LSB_DATA macro. + * patches/icedtea-version.patch: + Updated to use distribution name and JDK and + HotSpot Mercurial revision IDs. + 2010-01-19 Man Lung Wong <mwong@redhat.com> * rt/net/sourceforge/jnlp/JNLPFile.java
--- a/HACKING Thu Jan 21 02:04:50 2010 +0000 +++ b/HACKING Thu Jan 28 16:34:49 2010 +0000 @@ -115,6 +115,7 @@ * openjdk/6648816.patch: Backport of regression (NPE) fix in AccessControlContext (PR364/S6648816) * icedtea-nss-config.patch: Add the NSS PKCS11 security provider. (PR356) * icedtea-nss-6763530.patch: Fix PKCS11 provider when used with newer version of NSS (>=3.12.3) (PR356, S6763530). +* libpng.patch: Use png_sig_cmp instead of png_check_sig so we can build against libpng 1.4. The following patches are only applied to OpenJDK in IcedTea:
--- a/IcedTeaPlugin.cc Thu Jan 21 02:04:50 2010 +0000 +++ b/IcedTeaPlugin.cc Thu Jan 28 16:34:49 2010 +0000 @@ -275,8 +275,8 @@ #define PLUGIN_CHECK(message, result) #endif -#define PLUGIN_NAME "IcedTea Java Web Browser Plugin" -#define PLUGIN_DESCRIPTION "The " PLUGIN_NAME PLUGIN_VERSION " executes Java applets." +#define PLUGIN_NAME "IcedTea Java Web Browser Plugin (using " PLUGIN_VERSION ")" +#define PLUGIN_DESCRIPTION "The " PLUGIN_NAME " executes Java applets." #define PLUGIN_MIME_DESC \ "application/x-java-vm:class,jar:IcedTea;" \ "application/x-java-applet:class,jar:IcedTea;" \
--- a/Makefile.am Thu Jan 21 02:04:50 2010 +0000 +++ b/Makefile.am Thu Jan 28 16:34:49 2010 +0000 @@ -123,15 +123,16 @@ # FIXME (plugin): NPPLUGIN_DIR becomes PLUGIN_DIR if ENABLE_NPPLUGIN ICEDTEAPLUGIN_CLEAN = clean-IcedTeaNPPlugin -ICEDTEAPLUGIN_TARGET = stamps/icedtea-npplugin +ICEDTEAPLUGIN_TARGET = stamps/icedtea-npplugin.stamp PLUGIN_PATCH = patches/icedtea-liveconnect.patch LIVECONNECT_DIR = -C lib/rt netscape -C lib/rt sun/applet -NPPLUGIN_DIR=$(abs_top_srcdir)/plugin/icedteanp -LIVECONNECT_SRCS = $(NPPLUGIN_DIR)/java +NPPLUGIN_DIR=$(abs_top_builddir)/plugin/icedteanp +NPPLUGIN_SRCDIR=$(abs_top_srcdir)/plugin/icedteanp +LIVECONNECT_SRCS = $(NPPLUGIN_SRCDIR)/java else if ENABLE_PLUGIN ICEDTEAPLUGIN_CLEAN = clean-IcedTeaPlugin -ICEDTEAPLUGIN_TARGET = IcedTeaPlugin.so +ICEDTEAPLUGIN_TARGET = stamps/icedtea-plugin.stamp PLUGIN_PATCH = patches/icedtea-liveconnect.patch LIVECONNECT_DIR = -C lib/rt netscape -C lib/rt sun/applet NPPLUGIN_DIR = @@ -202,6 +203,10 @@ ICEDTEA_HOME = $(abs_top_builddir)/bootstrap/icedtea endif +# Sources list + +PLUGIN_TEST_SRCS = $(abs_top_srcdir)/plugin/tests/LiveConnect/*.java + # Patch list ICEDTEA_FSG_PATCHES = @@ -293,7 +298,8 @@ patches/icedtea-6897844-xshm.patch \ patches/icedtea-linux-separate-debuginfo.patch \ patches/icedtea-parisc.patch \ - patches/icedtea-sh4-support.patch + patches/icedtea-sh4-support.patch \ + patches/libpng.patch if WITH_RHINO ICEDTEA_PATCHES += \ @@ -379,9 +385,15 @@ JDK_UPDATE_VERSION = $(shell echo $(OPENJDK_VERSION) | sed -e "s/^b//") COMBINED_VERSION = $(JDK_UPDATE_VERSION)-$(OPENJDK_VERSION) +ICEDTEA_NAME = IcedTea6 if HAS_ICEDTEA_REVISION -ICEDTEA_REV="+${ICEDTEA_REVISION}" +ICEDTEA_REV = +${ICEDTEA_REVISION} endif +if HAS_PKGVERSION +ICEDTEA_PKG = $(EMPTY) (${PKGVERSION}) +endif + +PLUGIN_VERSION = $(ICEDTEA_NAME) $(PACKAGE_VERSION)$(ICEDTEA_REV)$(ICEDTEA_PKG) ICEDTEA_ENV = \ IMPORT_BINARY_PLUGS=true \ @@ -423,7 +435,7 @@ JDK_HOME="" \ RHINO_JAR="$(RHINO_JAR)" \ DISTRIBUTION_ID="$(DIST_ID)" \ - DERIVATIVE_ID="IcedTea6 $(PACKAGE_VERSION)$(ICEDTEA_REV)" \ + DERIVATIVE_ID="$(ICEDTEA_NAME) $(PACKAGE_VERSION)$(ICEDTEA_REV)" \ DEBUG_CLASSFILES="true" \ DEBUG_BINARIES="true" \ ALT_DROPS_DIR="$(abs_top_builddir)/drops" @@ -511,7 +523,7 @@ JAR_KNOWS_J_OPTIONS="$(JAR_KNOWS_J_OPTIONS)" \ JAR_ACCEPTS_STDIN_LIST="$(JAR_ACCEPTS_STDIN_LIST)" \ DISTRIBUTION_ID="$(DIST_ID)" \ - DERIVATIVE_ID="IcedTea6 $(PACKAGE_VERSION)$(ICEDTEA_REV)" \ + DERIVATIVE_ID="$(ICEDTEA_NAME) $(PACKAGE_VERSION)$(ICEDTEA_REV)" \ DEBUG_CLASSFILES="true" \ DEBUG_BINARIES="true" \ DISABLE_NIMBUS="true" \ @@ -551,16 +563,15 @@ # FIXME (distclean): Add pulseaudio sources EXTRA_DIST = rt generated \ - patches/* \ + $(abs_top_srcdir)/patches/* \ tools-copy contrib ports \ extra overlays \ javaws.png javaws.desktop visualvm.desktop \ jconsole.desktop policytool.desktop \ test/jtreg \ IcedTeaPlugin.cc \ - IcedTeaNPPlugin.cc \ HACKING pulseaudio fsg.sh \ - plugin \ + $(abs_top_srcdir)/plugin \ hotspot.map \ autogen.sh \ tapset/hotspot.stp.in \ @@ -863,6 +874,7 @@ if OPENJDK_SRC_DIR_FOUND cp -a $(OPENJDK_SRC_DIR) openjdk else + set -e ; \ if ! test -d openjdk ; \ then \ mkdir openjdk ; \ @@ -874,12 +886,14 @@ if BUILD_CACAO if !USE_SYSTEM_CACAO if USE_ALT_CACAO_SRC_DIR + set -e ; \ if ! test -d cacao ; \ then \ mkdir -p cacao/cacao ; \ cp -r $(ALT_CACAO_SRC_DIR)/* cacao/cacao/ ; \ fi else + set -e ; \ if ! test -d cacao ; \ then \ mkdir cacao ; \ @@ -891,17 +905,20 @@ endif endif if WITH_VISUALVM + set -e ; \ if ! test -d netbeans ; \ then \ mkdir netbeans ; \ $(TAR) xf $(NETBEANS_PROFILER_SRC_ZIP) -C netbeans ; \ fi + set -e ; \ if ! test -d visualvm ; \ then \ $(TAR) xf $(VISUALVM_SRC_ZIP) ; \ fi endif + set -e ; \ if [ ! -e $(abs_top_builddir)/generated ]; then \ cp -a $(abs_top_srcdir)/generated $(abs_top_builddir); \ find $(abs_top_builddir)/generated -type f -exec chmod 640 '{}' ';' \ @@ -1043,10 +1060,10 @@ if ! test "x$(WITH_CACAO)" = "xno"; then \ echo "JDK_DERIVATIVE_NAME=$${icedtea_version}" \ >>openjdk/jdk/make/common/shared/Defs.gmk ; \ - echo "PRODUCT_NAME=IcedTea6" \ + echo "PRODUCT_NAME=$(ICEDTEA_NAME)" \ >>openjdk/jdk/make/common/shared/Defs.gmk ; \ else \ - echo "JDK_DERIVATIVE_NAME=IcedTea6 $${icedtea_version}" \ + echo "JDK_DERIVATIVE_NAME=$(ICEDTEA_NAME) $${icedtea_version}" \ >>openjdk/jdk/make/common/shared/Defs.gmk ; \ fi ; @@ -1054,11 +1071,11 @@ echo "JDK_REVID=$(JDK_REVISION)" >>openjdk/jdk/make/common/shared/Defs.gmk ; endif - echo "DISTRO_NAME=$(DIST_NAME)" >>openjdk/jdk/make/common/shared/Defs.gmk ; \ - if [ -n "$(PKGVERSION)" ]; then \ + echo "DISTRO_NAME=$(DIST_NAME)" >>openjdk/jdk/make/common/shared/Defs.gmk ; +if HAS_PKGVERSION echo "DISTRO_PACKAGE_VERSION=$(PKGVERSION)" \ - >>openjdk/jdk/make/common/shared/Defs.gmk ; \ - fi + >>openjdk/jdk/make/common/shared/Defs.gmk ; +endif #FIXME (plugin): Don't do this copying if ENABLE_NPPLUGIN @@ -1283,7 +1300,7 @@ stamps/icedtea.stamp: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \ - $(ICEDTEAPLUGIN_TARGET) $(ICEDTEANPPLUGIN_TARGET) \ + $(ICEDTEAPLUGIN_TARGET) \ extra-lib/about.jar stamps/cacao.stamp stamps/visualvm.stamp \ stamps/pulse-java.stamp $(ARCH_PREFIX) $(MAKE) \ @@ -1386,7 +1403,7 @@ stamps/icedtea-debug.stamp: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \ - $(ICEDTEAPLUGIN_TARGET) $(ICEDTEANPPLUGIN_TARGET) \ + $(ICEDTEAPLUGIN_TARGET) \ extra-lib/about.jar stamps/cacao.stamp stamps/visualvm.stamp \ stamps/pulse-java.stamp $(ARCH_PREFIX) $(MAKE) \ @@ -1572,35 +1589,29 @@ IcedTeaJavaRequestProcessor.o IcedTeaPluginRequestProcessor.o \ IcedTeaPluginUtils.o -$(addprefix $(NPPLUGIN_DIR)/,$(NPPLUGIN_OBJECTS)): $(addprefix $(NPPLUGIN_DIR)/,$(NPPLUGIN_SRC)) - cd $(NPPLUGIN_DIR); \ - if [ -e $(abs_top_srcdir)/.hg ] && which $(HG) >/dev/null; then \ - revision="-r`(cd $(abs_top_srcdir); $(HG) tip --template '{rev}')`" ; \ - fi ; \ - if [ -n "$(PKGVERSION)" ]; then plugin_version=" ($(PKGVERSION))"; fi; \ - plugin_version=" $(PACKAGE_VERSION)$$revision$$plugin_version"; \ +$(NPPLUGIN_DIR)/%.o: $(NPPLUGIN_SRCDIR)/%.cc + mkdir -p $(NPPLUGIN_DIR) && \ + cd $(NPPLUGIN_DIR) && \ $(CXX) $(CXXFLAGS) \ - -DPACKAGE_VERSION="\"$(PACKAGE_VERSION)\"" \ - -DPLUGIN_VERSION="\"$$plugin_version\"" \ + -DPLUGIN_VERSION="\"$(PLUGIN_VERSION)\"" \ -DMOZILLA_VERSION_COLLAPSED="$(MOZILLA_VERSION_COLLAPSED)" \ $(GLIB_CFLAGS) \ $(GTK_CFLAGS) \ $(MOZILLA_CFLAGS) \ - -fPIC -c $(NPPLUGIN_SRC); \ - cd ../ + -fPIC -o $@ -c $< $(NPPLUGIN_DIR)/IcedTeaNPPlugin.so: $(addprefix $(NPPLUGIN_DIR)/,$(NPPLUGIN_OBJECTS)) - cd $(NPPLUGIN_DIR); \ + cd $(NPPLUGIN_DIR) && \ $(CXX) $(CXXFLAGS) \ $(NPPLUGIN_OBJECTS) \ $(GLIB_LIBS) \ $(GTK_LIBS) \ $(MOZILLA_LIBS)\ - -shared -o $@; \ - cd ../ + -shared -o $@ -stamps/icedtea-npplugin: $(NPPLUGIN_DIR)/IcedTeaNPPlugin.so - touch stamps/icedtea-npplugin +stamps/icedtea-npplugin.stamp: $(NPPLUGIN_DIR)/IcedTeaNPPlugin.so + mkdir -p stamps + touch stamps/icedtea-npplugin.stamp clean-IcedTeaNPPlugin: cd $(NPPLUGIN_DIR);\ @@ -1614,25 +1625,23 @@ # is listed before -l options. See: # http://developer.mozilla.org/en/docs/XPCOM_Glue IcedTeaPlugin.o: IcedTeaPlugin.cc - if [ -e $(abs_top_srcdir)/.hg ] && which $(HG) >/dev/null; then \ - revision="-r`(cd $(abs_top_srcdir); $(HG) tip --template '{rev}')`" ; \ - fi ; \ - if [ -n "$(PKGVERSION)" ]; then plugin_version=" ($(PKGVERSION))"; fi; \ - plugin_version=" $(PACKAGE_VERSION)$$revision$$plugin_version"; \ $(CXX) $(CXXFLAGS) \ - -DPACKAGE_VERSION="\"$(PACKAGE_VERSION)\"" \ - -DPLUGIN_VERSION="\"$$plugin_version\"" \ + -DPLUGIN_VERSION="\"$(PLUGIN_VERSION)\"" \ -DMOZILLA_VERSION_COLLAPSED="$(MOZILLA_VERSION_COLLAPSED)" \ $(GTK_CFLAGS) \ - $(XULRUNNER_CFLAGS) \ + $(MOZILLA_CFLAGS) \ -fPIC -c -o $@ $< IcedTeaPlugin.so: IcedTeaPlugin.o $(CXX) $(CXXFLAGS) \ $< \ $(GTK_LIBS) \ - $(XULRUNNER_LIBS) \ + $(MOZILLA_LIBS) \ -shared -o $@ +stamps/icedtea-plugin.stamp: IcedTeaPlugin.so + mkdir -p stamps + touch stamps/icedtea-plugin.stamp + clean-IcedTeaPlugin: rm -f IcedTeaPlugin.o rm -f IcedTeaPlugin.so @@ -1981,6 +1990,33 @@ # end additional VMs +# plugin tests + +stamps/plugin-tests.stamp: $(PLUGIN_TEST_SRCS) \ + bootstrap/jdk1.7.0/jre/lib/rt-closed.jar + mkdir -p plugin/tests/LiveConnect + if test -d lib/rt/netscape ; then \ + set -e ; \ + if ! test -d $(ICEDTEA_BOOT_DIR) ; then \ + $(JAVAC) $(MEMORY_LIMIT) -g -d plugin/tests/LiveConnect \ + -classpath bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \ + -source 1.5 $(PLUGIN_TEST_SRCS) ; \ + $(JAR) cf plugin/tests/LiveConnect/PluginTest.jar \ + plugin/tests/LiveConnect/*.class ; \ + else \ + $(ICEDTEA_BOOT_DIR)/bin/javac $(MEMORY_LIMIT) -g \ + -d plugin/tests/LiveConnect \ + -classpath bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \ + -source 1.5 $(PLUGIN_TEST_SRCS) ; \ + $(ICEDTEA_BOOT_DIR)/bin/jar cf plugin/tests/LiveConnect/PluginTest.jar \ + plugin/tests/LiveConnect/*.class ; \ + fi ; \ + cp -a $(abs_top_srcdir)/plugin/tests/LiveConnect/*.{js,html} plugin/tests/LiveConnect ; \ + echo "Done. Now launch \"firefox file://`pwd`/index.html\"" ; \ + fi + mkdir -p stamps + touch stamps/plugin-tests.stamp + # jtreg stamps/jtreg.stamp: stamps/icedtea.stamp @@ -2305,3 +2341,7 @@ clean: distclean-local jtreg: stamps/jtreg.stamp + +plugin: $(ICEDTEAPLUGIN_TARGET) + +plugin-tests: stamps/plugin-tests.stamp
--- a/NEWS Thu Jan 21 02:04:50 2010 +0000 +++ b/NEWS Thu Jan 28 16:34:49 2010 +0000 @@ -1,16 +1,25 @@ New in release 1.8 (XXXX-XX-XX): -New in release 1.7 (XXXX-XX-XX): +New in release 1.7 (2010-01-27): - Updated to OpenJDK6 b17. +- Alpha version of the new IcedTea NPRuntime based plugin with support for + Firefox >= 3.5, Chromium, and other browsers that support NPRuntime + (use --enable-npplugin to build it). For xulrunner >= 1.9.2 (used + by Firefox >= 3.6), the new plugin is required and the build will + automatically enable it if the old plugin is requested. - Support added for building with HotSpot 16 using - --with-hotspot-build=hs16. + --with-hotspot-build=hs16. This is the same as was released + in the proprietary JDK6 update 18. - Zero port updated to match the version submitted to OpenJDK as closely as possible. -- libjpeg7 and libXext >= 1.1.0 supported. +- libjpeg7, libjpeg8, libpng 1.4 and libXext >= 1.1.0 supported. - Added JNI call tracing using systemtap version 1.0+ when configuring with --enable-systemtap. See tapset/hotspot_jni.stp. +- Add support for building the Zero assembler port on Hitachi SH. + +New in release 1.6.2 (2009-11-09) - Latest security updates: - (CVE-2009-3728) ICC_Profile file existence detection information leak (6631533) - (CVE-2009-3885) BMP parsing DoS with UNC ICC links (6632445) @@ -27,11 +36,50 @@ - (CVE-2009-3869) JRE AWT setDifflCM stack overflow (6872357) - (CVE-2009-3874) ImageI/O JPEG heap overflow (6874643 - (CVE-2009-3871) JRE AWT setBytePixels heap overflow (6872358) -- Add support for zero build on Hitachi SH. + +New in release 1.5.3 (2009-11-09) +- Latest security updates: + - (CVE-2009-3728) ICC_Profile file existence detection information leak (6631533) + - (CVE-2009-3885) BMP parsing DoS with UNC ICC links (6632445) + - (CVE-2009-3881) resurrected classloaders can still have children (6636650) + - (CVE-2009-3882) Numerous static security flaws in Swing (findbugs) (6657026) + - (CVE-2009-3883) Mutable statics in Windows PL&F (findbugs) (6657138) + - (CVE-2009-3880) UI logging information leakage (6664512) + - (CVE-2009-3879) GraphicsConfiguration information leak (6822057) + - (CVE-2009-3884) zoneinfo file existence information leak (6824265) + - (CVE-2009-2409) deprecate MD2 in SSL cert validation (Kaminsky) (6861062) + - (CVE-2009-3873) JPEG Image Writer quantization problem (6862968) + - (CVE-2009-3875) MessageDigest.isEqual introduces timing attack vulnerabilities (6863503) + - (CVE-2009-3876, CVE-2009-3877) OpenJDK ASN.1/DER input stream parser denial of service (6864911) + - (CVE-2009-3869) JRE AWT setDifflCM stack overflow (6872357) + - (CVE-2009-3874) ImageI/O JPEG heap overflow (6874643 + - (CVE-2009-3871) JRE AWT setBytePixels heap overflow (6872358) + +New in release 1.6.1 (2009-09-14): + +- Fix tarball error in 1.6 +- Improve jar performance, + http://hg.openjdk.java.net/jdk6/jdk6/jdk/rev/b35f1e5075a4 New in release 1.6 (2009-09-10): - Added java method tracing using systemtap version 0.9.9+. +- FAST interpreter for ARM +- Timezone fix: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=377 +- Stackoverflow error fix: +http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=381 +- Backport regression (NPE) fix for AccessControlContext fix +- Bump to hs14b16 +- The plugin has been updated to improve stability and cookie support. + Support for certificates with mismatched CNs has been added as well. + +New in release 1.5.2 (2009-09-04) +- Timezone fix: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=377 +- Stackoverflow error fix: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=381 +- Backport regression (NPE) fix for AccessControlContext fix +- Bump to hs14b16 + +New in release 1.5.1 (2009-08-07) - Security fixes for: CVE-2009-2670 - OpenJDK Untrusted applet System properties access CVE-2009-2671 CVE-2009-2672 - OpenJDK Proxy mechanism information leaks @@ -43,14 +91,7 @@ CVE-2009-2476 - OpenJDK OpenType checks can be bypassed CVE-2009-2689 - OpenJDK JDK13Services grants unnecessary privileges CVE-2009-2690 - OpenJDK private variable information disclosure -- FAST interpreter for ARM -- Timezone fix: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=377 -- Stackoverflow error fix: -http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=381 -- Backport regression (NPE) fix for AccessControlContext fix -- Bump to hs14b16 -- The plugin has been updated to improve stability and cookie support. - Support for certificates with mismatched CNs has been added as well. +- Plugin/Netx security fix. New in release 1.5 (2009-05-20)
--- a/acinclude.m4 Thu Jan 21 02:04:50 2010 +0000 +++ b/acinclude.m4 Thu Jan 28 16:34:49 2010 +0000 @@ -1268,15 +1268,33 @@ AC_SUBST(PARALLEL_JOBS) ]) -AC_DEFUN([IT_GET_LSB_DATA], +AC_DEFUN_ONCE([IT_GET_PKGVERSION], [ +AC_MSG_CHECKING([for distribution package version]) +AC_ARG_WITH([pkgversion], + [AS_HELP_STRING([--with-pkgversion=PKG], + [Use PKG in the version string in addition to "IcedTea"])], + [case "$withval" in + yes) AC_MSG_ERROR([package version not specified]) ;; + no) PKGVERSION=none ;; + *) PKGVERSION="$withval" ;; + esac], + [PKGVERSION=none]) +AC_MSG_RESULT([${PKGVERSION}]) +AM_CONDITIONAL(HAS_PKGVERSION, test "x${PKGVERSION}" != "xnone") +AC_SUBST(PKGVERSION) +]) + +AC_DEFUN_ONCE([IT_GET_LSB_DATA], +[ +AC_REQUIRE([IT_GET_PKGVERSION]) AC_MSG_CHECKING([build identification]) if test -n "$LSB_RELEASE"; then lsb_info="$($LSB_RELEASE -ds | sed 's/^"//;s/"$//')" - if test -n "$PKGVERSION"; then + if test "x$PKGVERSION" = "xnone"; then + DIST_ID="Built on $lsb_info ($(date))" + else DIST_ID="$lsb_info, package $PKGVERSION" - else - DIST_ID="Built on $lsb_info ($(date))" fi DIST_NAME="$($LSB_RELEASE -is | sed 's/^"//;s/"$//')" else @@ -1326,3 +1344,126 @@ AM_CONDITIONAL([HAS_JDK_REVISION], test "x${JDK_REVISION}" != xnone) AM_CONDITIONAL([HAS_HOTSPOT_REVISION], test "x${HOTSPOT_REVISION}" != xnone) ]) + +AC_DEFUN_ONCE([IT_CHECK_OLD_PLUGIN], +[ +AC_MSG_CHECKING([whether to build the browser plugin]) +AC_ARG_ENABLE([plugin], + [AS_HELP_STRING([--disable-plugin], + [Disable compilation of browser plugin])], + [enable_plugin="${enableval}"], [enable_plugin="yes"]) +AC_MSG_RESULT(${enable_plugin}) +]) + +AC_DEFUN_ONCE([IT_CHECK_NEW_PLUGIN], +[ +AC_MSG_CHECKING([whether to build the new experimental browser plugin based on npruntime]) +AC_ARG_ENABLE([npplugin], + [AS_HELP_STRING([--enable-npplugin], + [Enable compilation of browser plugin (automatically disables default plugin)])], + [enable_npplugin="${enableval}"], [enable_npplugin="no"]) +AC_MSG_RESULT(${enable_npplugin}) +]) + +AC_DEFUN_ONCE([IT_CHECK_PLUGIN_DEPENDENCIES], +[ +dnl Check for plugin support headers and libraries. +dnl FIXME: use unstable +AC_REQUIRE([IT_CHECK_OLD_PLUGIN]) +AC_REQUIRE([IT_CHECK_NEW_PLUGIN]) +if test "x${enable_plugin}" = "xyes" -o "x${enable_npplugin}" = "xyes" ; then + PKG_CHECK_MODULES(GTK, gtk+-2.0) + PKG_CHECK_MODULES(GLIB, glib-2.0) + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GTK_CFLAGS) + AC_SUBST(GTK_LIBS) + + + if $PKG_CONFIG --atleast-version 1.9.2 libxul 2>&AS_MESSAGE_LOG_FD ; then + if test "x${enable_npplugin}" != "xyes" ; then + AC_MSG_WARN([The old plugin does not work with xulrunner >= 1.9.2. Enabling new plugin.]) + enable_npplugin=yes; + fi + xullibs=libxul + else + xullibs="libxul libxul-unstable" + fi + + if test "x${enable_npplugin}" = "xyes" ; + then + PKG_CHECK_MODULES(MOZILLA, \ + mozilla-plugin ${xullibs}) + + AC_SUBST(MOZILLA_CFLAGS) + AC_SUBST(MOZILLA_LIBS) + else + if test "x${enable_plugin}" = "xyes" + then + PKG_CHECK_MODULES(MOZILLA, \ + nspr mozilla-js mozilla-plugin libxul-unstable >= 1.9) + + AC_SUBST(MOZILLA_CFLAGS) + AC_SUBST(MOZILLA_LIBS) + fi + fi +fi +AM_CONDITIONAL(ENABLE_PLUGIN, test "x${enable_plugin}" = "xyes") +AM_CONDITIONAL(ENABLE_NPPLUGIN, test "x${enable_npplugin}" = "xyes") +]) + +AC_DEFUN_ONCE([IT_CHECK_XULRUNNER_VERSION], +[ +AC_REQUIRE([IT_CHECK_PLUGIN_DEPENDENCIES]) +if test "x${enable_plugin}" = "xyes" -o "x${enable_npplugin}" = "xyes" +then + AC_LANG_PUSH([C++]) + OLDCPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $MOZILLA_CFLAGS" + + AC_CACHE_CHECK([for xulrunner version], [xulrunner_cv_collapsed_version], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ +#include <mozilla-config.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +]],[[ +int version = 0; +const char* token = NULL; +int power=6; +FILE *datafile; + +datafile = fopen ("conftest.vdata", "w"); +if (!datafile) return 1; + +// 32 chars is more than enough to hold version +char* mozilla_version = (char*) malloc(32*sizeof(char)); +snprintf(mozilla_version, 32, "%s", MOZILLA_VERSION); + +token = strtok(mozilla_version, "."); +while (token) +{ + version += atoi(token)*(pow(10, power)); + power -=2; + token = strtok(NULL, "."); +} + +fprintf (datafile, "%d\n", version); +free(mozilla_version); +if (fclose(datafile)) return 1; + +return EXIT_SUCCESS; +]])], + [xulrunner_cv_collapsed_version="$(cat conftest.vdata)"], + [AC_MSG_FAILURE([cannot determine xulrunner version])])], + [xulrunner_cv_collapsed_version="190000"]) + + CPPFLAGS="$OLDCPPFLAGS" + AC_LANG_POP([C++]) + + AC_SUBST(MOZILLA_VERSION_COLLAPSED, $xulrunner_cv_collapsed_version) +fi +]) +
--- a/configure.ac Thu Jan 21 02:04:50 2010 +0000 +++ b/configure.ac Thu Jan 28 16:34:49 2010 +0000 @@ -94,22 +94,6 @@ AM_CONDITIONAL(WITH_VISUALVM, test "x${enable_visualvm}" = "xyes") AC_MSG_RESULT(${enable_visualvm}) -AC_MSG_CHECKING([whether to build the browser plugin]) -AC_ARG_ENABLE([plugin], - [AS_HELP_STRING([--disable-plugin], - [Disable compilation of browser plugin])], - [enable_plugin="${enableval}"], [enable_plugin="yes"]) -AM_CONDITIONAL(ENABLE_PLUGIN, test "x${enable_plugin}" = "xyes") -AC_MSG_RESULT(${enable_plugin}) - -AC_MSG_CHECKING([whether to build the new experimental browser plugin based on npruntime]) -AC_ARG_ENABLE([npplugin], - [AS_HELP_STRING([--enable-npplugin], - [Enable compilation of browser plugin (automatically disables default plugin)])], - [enable_npplugin="${enableval}"], [enable_npplugin="no"]) -AM_CONDITIONAL(ENABLE_NPPLUGIN, test "x${enable_npplugin}" = "xyes") -AC_MSG_RESULT(${enable_npplugin}) - AC_MSG_CHECKING([whether to include PulseAudio support]) AC_ARG_ENABLE([pulse-java], [AS_HELP_STRING([--enable-pulse-java], @@ -167,17 +151,7 @@ AM_CONDITIONAL([ENABLE_NSS], [test x$ENABLE_NSS = xyes]) AC_MSG_RESULT(${ENABLE_NSS}) -AC_ARG_WITH([pkgversion], - [AS_HELP_STRING([--with-pkgversion=PKG], - [Use PKG in the version string in addition to "IcedTea"])], - [case "$withval" in - yes) AC_MSG_ERROR([package version not specified]) ;; - no) PKGVERSION= ;; - *) PKGVERSION="$withval" ;; - esac], - [PKGVERSION=]) -AC_SUBST(PKGVERSION) - +IT_GET_PKGVERSION IT_GET_LSB_DATA SET_ARCH_DIRS @@ -229,8 +203,8 @@ ENABLE_HG AC_CHECK_WITH_HG_REVISION AC_CHECK_WITH_TZDATA_DIR - IT_CHECK_FOR_CLASS([SUN_AWT_TOOLKIT], [sun.awt.SunToolkit]) +IT_CHECK_XULRUNNER_VERSION if test "x${enable_visualvm}" = "xyes" then @@ -432,89 +406,6 @@ AC_SUBST(LIBPULSE_LIBS) fi -dnl Check for plugin support headers and libraries. -dnl FIXME: use unstable -if test "x${enable_plugin}" = "xyes" - then - PKG_CHECK_MODULES(XULRUNNER, \ - nspr mozilla-js mozilla-plugin libxul-unstable >= 1.9) - PKG_CHECK_MODULES(GTK, gtk+-2.0) - PKG_CHECK_MODULES(GLIB, glib-2.0) - - AC_SUBST(MOZILLA_CFLAGS) - AC_SUBST(MOZILLA_LIBS) - AC_SUBST(GLIB_CFLAGS) - AC_SUBST(GLIB_LIBS) - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) - fi - -if test "x${enable_npplugin}" = "xyes" - then - PKG_CHECK_MODULES(MOZILLA, \ - mozilla-plugin libxul) - PKG_CHECK_MODULES(GTK, gtk+-2.0) - PKG_CHECK_MODULES(GLIB, glib-2.0) - - AC_SUBST(MOZILLA_CFLAGS) - AC_SUBST(MOZILLA_LIBS) - AC_SUBST(GLIB_CFLAGS) - AC_SUBST(GLIB_LIBS) - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) - fi - -if test "x${enable_plugin}" = "xyes" -o "x${enable_npplugin}" = "xyes" -then - AC_LANG_PUSH([C++]) - OLDCPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $XULRUNNER_CFLAGS" - - AC_CACHE_CHECK([for xulrunner version], [xulrunner_cv_collapsed_version], - [AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include <mozilla-config.h> -#include <math.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -]],[[ -int version = 0; -const char* token = NULL; -int power=6; -FILE *datafile; - -datafile = fopen ("conftest.vdata", "w"); -if (!datafile) return 1; - -// 32 chars is more than enough to hold version -char* mozilla_version = (char*) malloc(32*sizeof(char)); -snprintf(mozilla_version, 32, "%s", MOZILLA_VERSION); - -token = strtok(mozilla_version, "."); -while (token) -{ - version += atoi(token)*(pow(10, power)); - power -=2; - token = strtok(NULL, "."); -} - -fprintf (datafile, "%d\n", version); -free(mozilla_version); -if (fclose(datafile)) return 1; - -return EXIT_SUCCESS; -]])], - [xulrunner_cv_collapsed_version="$(cat conftest.vdata)"], - [AC_MSG_FAILURE([cannot determine xulrunner version])])], - [xulrunner_cv_collapsed_version="190000"]) - - CPPFLAGS="$OLDCPPFLAGS" - AC_LANG_POP([C++]) - - AC_SUBST(MOZILLA_VERSION_COLLAPSED, $xulrunner_cv_collapsed_version) -fi - if test "x${ENABLE_NSS}" = "xyes" then PKG_CHECK_MODULES(NSS, nss, [NSS_FOUND=yes], [NSS_FOUND=no])
--- a/patches/icedtea-libraries.patch Thu Jan 21 02:04:50 2010 +0000 +++ b/patches/icedtea-libraries.patch Thu Jan 28 16:34:49 2010 +0000 @@ -25045,18 +25045,22 @@ } -@@ -2317,6 +2377,146 @@ +@@ -2317,6 +2377,150 @@ /********************** end of destination manager ************/ +METHODDEF(void) +initIDs() +{ ++#if JPEG_LIB_VERSION >= 80 ++ void *handle = dlopen("libjpeg.so.8", RTLD_LAZY | RTLD_GLOBAL); ++#else +#if JPEG_LIB_VERSION >= 70 + void *handle = dlopen("libjpeg.so.7", RTLD_LAZY | RTLD_GLOBAL); +#else + void *handle = dlopen("libjpeg.so.62", RTLD_LAZY | RTLD_GLOBAL); +#endif ++#endif + + jpegstderror = (fn_jpegstderror)dlsym(handle, "jpeg_std_error"); + if (jpegstderror == NULL) { @@ -25343,14 +25347,19 @@ /* Initialize the Java VM instance variable when the library is first loaded */ JavaVM *jvm; -@@ -462,6 +493,71 @@ +@@ -462,6 +493,76 @@ Java_sun_awt_image_JPEGImageDecoder_initIDs(JNIEnv *env, jclass cls, jclass InputStreamClass) { ++#if JPEG_LIB_VERSION >= 80 ++ void *handle = dlopen("libjpeg.so.8", RTLD_LAZY | RTLD_GLOBAL); ++#else ++#if JPEG_LIB_VERSION >= 70 + void *handle = dlopen("libjpeg.so.7", RTLD_LAZY | RTLD_GLOBAL); -+ if (handle == NULL) { -+ handle = dlopen("libjpeg.so.62", RTLD_LAZY | RTLD_GLOBAL); -+ } ++#else ++ void *handle = dlopen("libjpeg.so.62", RTLD_LAZY | RTLD_GLOBAL); ++#endif ++#endif + + jpegstderror = (fn_jpegstderror)dlsym(handle, "jpeg_std_error"); + if (jpegstderror == NULL) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/libpng.patch Thu Jan 28 16:34:49 2010 +0000 @@ -0,0 +1,12 @@ +diff -r 93c580ce5e88 jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c +--- openjdk.orig/jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c Fri Jan 15 08:41:51 2010 -0800 ++++ openjdk/jdk/src/share/native/sun/awt/splashscreen/splashscreen_png.c Wed Jan 27 16:52:44 2010 +0000 +@@ -182,7 +182,7 @@ + int success = 0; + + stream->read(stream, sig, SIG_BYTES); +- if (!png_check_sig(sig, SIG_BYTES)) { ++ if (png_sig_cmp(sig, 0, SIG_BYTES)) { + goto done; + } + success = SplashDecodePng(splash, my_png_read_stream, stream);
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc Thu Jan 21 02:04:50 2010 +0000 +++ b/plugin/icedteanp/IcedTeaNPPlugin.cc Thu Jan 28 16:34:49 2010 +0000 @@ -87,8 +87,8 @@ __LINE__, g_thread_self (), first, second, third) // Plugin information passed to about:plugins. -#define PLUGIN_NAME "IcedTea NPR Web Browser Plugin (using IcedTea)" -#define PLUGIN_DESC "The " PLUGIN_NAME PLUGIN_VERSION " executes Java applets." +#define PLUGIN_NAME "IcedTea NPR Web Browser Plugin (using " PLUGIN_VERSION ")" +#define PLUGIN_DESC "The " PLUGIN_NAME " executes Java applets." #define PLUGIN_MIME_DESC \ "application/x-java-vm:class,jar:IcedTea;" \ @@ -1336,7 +1336,7 @@ // if proxy info is available, extract it nsCString phost; - PRint32_t pport; + PRInt32 pport; nsCString ptype; info->GetHost(phost); @@ -2079,7 +2079,7 @@ { case NPPVpluginNameString: PLUGIN_DEBUG_0ARG ("NP_GetValue: returning plugin name.\n"); - *char_value = g_strdup (PLUGIN_NAME " " PACKAGE_VERSION); + *char_value = g_strdup (PLUGIN_NAME); break; case NPPVpluginDescriptionString:
--- a/ports/hotspot/make/linux/makefiles/zeroshark.make Thu Jan 21 02:04:50 2010 +0000 +++ b/ports/hotspot/make/linux/makefiles/zeroshark.make Thu Jan 28 16:34:49 2010 +0000 @@ -29,6 +29,7 @@ Obj_Files += asm_helper.o Obj_Files += cppInterpreter_arm.o +Obj_Files += thumb2.o CFLAGS += -DHOTSPOT_ASM @@ -38,6 +39,7 @@ $(COMPILE.CC) -o $@ $< $(COMPILE_DONE) cppInterpreter_arm.o: offsets_arm.s bytecodes_arm.s +thumb2.o: offsets_arm.s offsets_arm.s: mkoffsets @echo Generating assembler offsets
--- a/ports/hotspot/src/cpu/zero/vm/asm_helper.cpp Thu Jan 21 02:04:50 2010 +0000 +++ b/ports/hotspot/src/cpu/zero/vm/asm_helper.cpp Thu Jan 28 16:34:49 2010 +0000 @@ -16,10 +16,60 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "incls/_precompiled.incl" +#define ARCH_THUMBEE (1<<16) +#define ARCH_VFP (1<<17) +#define ARCH_CLZ (1<<18) #ifndef STATIC_OFFSETS +#include "incls/_bytecodeInterpreter.cpp.incl" + +#include <linux/auxvec.h> +#include <asm/hwcap.h> + +#define VECBUFF_SIZE 64 + +extern "C" unsigned hwcap(void) +{ + int fd; + unsigned vecs[VECBUFF_SIZE]; + unsigned *p; + int i, n; + unsigned rc = 0; + unsigned arch = 4; + + fd = open("/proc/self/auxv", O_RDONLY); + if (fd < 0) return 0; + do { + n = read(fd, vecs, VECBUFF_SIZE * sizeof(unsigned)); + p = vecs; + i = n/8; + while (--i >= 0) { + unsigned tag = *p++; + unsigned value = *p++; + if (tag == 0) goto fini; + if (tag == AT_HWCAP) { + if (value & HWCAP_THUMBEE) rc |= ARCH_THUMBEE; + if (value & HWCAP_VFP) rc |= ARCH_VFP; + } else if (tag == AT_PLATFORM) { + const char *s = (const char *)value; + int c; + + if (*s++ == 'v') { + arch = 0; + while ((isdigit)(c = *s++)) arch = arch * 10 + c - '0'; + } + } + } + } while (n == VECBUFF_SIZE * sizeof(unsigned)); +fini: + close(fd); +// printf("arch = %d, rc = 0x%08x\n", arch, rc); + if (arch >= 5) rc |= ARCH_CLZ; + if (arch >= 7) rc |= ARCH_THUMBEE; + return rc | (1<<arch); +} + /* Thease functions allow the ASM interpreter to call CPP virtual functions. * Otherwise the ASM interpreter has to grup around in the VTABLE which is * not very portable. @@ -44,10 +94,262 @@ return SharedRuntime::generate_class_cast_message(name, klass); } +#define HELPER_THROW(thread, name, msg) Exceptions::_throw_msg(thread, __FILE__, __LINE__, name, msg) + +class VMStructs { +public: + static inline klassOop klass_at_addr(constantPoolOop constants, u2 index) { + return (klassOop) *constants->obj_at_addr(index); + } +}; + +extern "C" oop Helper_new(interpreterState istate, unsigned index) +{ + JavaThread *thread = istate->thread(); + + constantPoolOop constants = istate->method()->constants(); + oop result = NULL; + if (!constants->tag_at(index).is_unresolved_klass()) { + // Make sure klass is initialized and doesn't have a finalizer + oop entry = VMStructs::klass_at_addr(constants, index); + klassOop k_entry = (klassOop) entry; + instanceKlass* ik = (instanceKlass*) k_entry->klass_part(); + if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) { + size_t obj_size = ik->size_helper(); + // If the TLAB isn't pre-zeroed then we'll have to do it + bool need_zero = !ZeroTLAB; + if (UseTLAB) { + result = (oop) thread->tlab().allocate(obj_size); + } + if (result == NULL) { + need_zero = true; + // Try allocate in shared eden + retry: + HeapWord* compare_to = *Universe::heap()->top_addr(); + HeapWord* new_top = compare_to + obj_size; + if (new_top <= *Universe::heap()->end_addr()) { + if (Atomic::cmpxchg_ptr(new_top, Universe::heap()->top_addr(), compare_to) != compare_to) { + goto retry; + } + result = (oop) compare_to; + } + } + if (result != NULL) { + // Initialize object (if nonzero size and need) and then the header + if (need_zero ) { + HeapWord* to_zero = (HeapWord*) result + sizeof(oopDesc) / oopSize; + obj_size -= sizeof(oopDesc) / oopSize; + if (obj_size > 0 ) { + memset(to_zero, 0, obj_size * HeapWordSize); + } + } + if (UseBiasedLocking) { + result->set_mark(ik->prototype_header()); + } else { + result->set_mark(markOopDesc::prototype()); + } + result->set_klass_gap(0); + result->set_klass(k_entry); + return result; + } + } + } + // Slow case allocation + InterpreterRuntime::_new(thread, istate->method()->constants(), index); + result = thread->vm_result(); + thread->set_vm_result(NULL); + return result; +} + +extern "C" int Helper_instanceof(interpreterState istate, unsigned index, oop tos) +{ + if (tos == NULL) return 0; + + // Constant pool may have actual klass or unresolved klass. If it is + // unresolved we must resolve it + if (istate->method()->constants()->tag_at(index).is_unresolved_klass()) { + InterpreterRuntime::quicken_io_cc(istate->thread()); + if (istate->thread()->has_pending_exception()) return 0; + } + klassOop klassOf = VMStructs::klass_at_addr(istate->method()->constants(), index); + klassOop objKlassOop = tos->klass(); + // + // Check for compatibilty. This check must not GC!! + // Seems way more expensive now that we must dispatch + // + return objKlassOop == klassOf || objKlassOop->klass_part()->is_subtype_of(klassOf); +} + +extern "C" oop Helper_checkcast(interpreterState istate, unsigned index, oop tos) +{ + if (tos == NULL) return NULL; + + // Constant pool may have actual klass or unresolved klass. If it is + // unresolved we must resolve it + if (istate->method()->constants()->tag_at(index).is_unresolved_klass()) { + oop except_oop; + InterpreterRuntime::quicken_io_cc(istate->thread()); + if (except_oop = istate->thread()->pending_exception()) return except_oop; + } + klassOop klassOf = VMStructs::klass_at_addr(istate->method()->constants(), index); + klassOop objKlassOop = tos->klass(); //ebx + // + // Check for compatibilty. This check must not GC!! + // Seems way more expensive now that we must dispatch + // + if (objKlassOop != klassOf && !objKlassOop->klass_part()->is_subtype_of(klassOf)) { + ResourceMark rm(istate->thread()); + const char* objName = Klass::cast(objKlassOop)->external_name(); + const char* klassName = Klass::cast(klassOf)->external_name(); + char* message = SharedRuntime::generate_class_cast_message(objName, klassName); + ThreadInVMfromJava trans(istate->thread()); + HELPER_THROW(istate->thread(), vmSymbols::java_lang_ClassCastException(), message); + } + return istate->thread()->pending_exception(); +} + +extern "C" oop Helper_aastore(interpreterState istate, oop value, int index, arrayOop arrayref) +{ + if (arrayref == NULL) { + ThreadInVMfromJava trans(istate->thread()); + HELPER_THROW(istate->thread(), vmSymbols::java_lang_NullPointerException(), ""); + } else if ((uint32_t)index >= (uint32_t)arrayref->length()) { + char message[jintAsStringSize]; + sprintf(message, "%d", index); + HELPER_THROW(istate->thread(), vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message); + } else { + if (value != NULL) { + /* Check assignability of value into arrayref */ + klassOop rhsKlassOop = value->klass(); // EBX (subclass) + klassOop elemKlassOop = ((objArrayKlass*) arrayref->klass()->klass_part())->element_klass(); + // + // Check for compatibilty. This check must not GC!! + // Seems way more expensive now that we must dispatch + // + if (rhsKlassOop != elemKlassOop && !rhsKlassOop->klass_part()->is_subtype_of(elemKlassOop)) { + HELPER_THROW(istate->thread(), vmSymbols::java_lang_ArrayStoreException(), ""); + goto handle_exception; + } + } + oop* elem_loc = (oop*)(((address) arrayref->base(T_OBJECT)) + index * sizeof(oop)); + // *(oop*)(((address) arrayref->base(T_OBJECT)) + index * sizeof(oop)) = value; + *elem_loc = value; + // Mark the card + BarrierSet* bs = Universe::heap()->barrier_set(); + static volatile jbyte* _byte_map_base = (volatile jbyte*)(((CardTableModRefBS*)bs)->byte_map_base); + OrderAccess::release_store(&_byte_map_base[(uintptr_t)elem_loc >> CardTableModRefBS::card_shift], 0); + } +handle_exception: + return istate->thread()->pending_exception(); +} + +extern "C" void Helper_aputfield(oop obj) +{ + BarrierSet* bs = Universe::heap()->barrier_set(); + static volatile jbyte* _byte_map_base = (volatile jbyte*)(((CardTableModRefBS*)bs)->byte_map_base); + OrderAccess::release_store(&_byte_map_base[(uintptr_t)obj >> CardTableModRefBS::card_shift], 0); +} + +extern "C" oop Helper_synchronized_enter(JavaThread *thread, BasicObjectLock *mon) +{ + BasicLock *lock = mon->lock(); + markOop displaced = lock->displaced_header(); + + if (thread->is_lock_owned((address)displaced->clear_lock_bits())) + lock->set_displaced_header(NULL); + else + InterpreterRuntime::monitorenter(thread, mon); + return thread->pending_exception(); +} + +extern "C" oop Helper_synchronized_exit(JavaThread *thread, BasicObjectLock *mon) +{ + { + HandleMark __hm(thread); + if (mon->obj() == NULL) + InterpreterRuntime::throw_illegal_monitor_state_exception(thread); + else + InterpreterRuntime::monitorexit(thread, mon); + } + return thread->pending_exception(); +} + +extern "C" oop Helper_SafePoint(JavaThread *thread) +{ + { + HandleMarkCleaner __hmc(thread); + } + SafepointSynchronize::block(thread); + return thread->pending_exception(); +} + +extern "C" void Helper_RaiseArrayBoundException(JavaThread *thread, int index) +{ + char message[jintAsStringSize]; + sprintf(message, "%d", index); + { + ThreadInVMfromJava trans(thread); + Exceptions::_throw_msg(thread, "[Bytecoce Interpreter]", 99, + vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message); + } +} + +extern "C" void Helper_Raise(JavaThread *thread, symbolOopDesc *name, char const *msg) +{ + ThreadInVMfromJava trans(thread); + Exceptions::_throw_msg(thread, "[Bytecoce Interpreter]", 99, name, msg); +} + +extern "C" void Helper_RaiseIllegalMonitorException(JavaThread *thread) +{ + HandleMark __hm(thread); + InterpreterRuntime::throw_illegal_monitor_state_exception(thread); +} + +extern "C" address Helper_HandleException(interpreterState istate, JavaThread *thread) +{ + HandleMarkCleaner __hmc(thread); + Handle except_oop(thread, thread->pending_exception()); + HandleMark __hm(thread); + intptr_t continuation_bci; + intptr_t *topOfStack; + address pc; + + thread->clear_pending_exception(); + continuation_bci = (intptr_t)InterpreterRuntime::exception_handler_for_exception(thread, except_oop()); + except_oop = (oop) thread->vm_result(); + thread->set_vm_result(NULL); + if (continuation_bci >= 0) { + topOfStack = (intptr_t *)istate->stack(); + *topOfStack-- = (intptr_t)except_oop(); + istate->set_stack(topOfStack); + pc = istate->method()->code_base() + continuation_bci; +#if 0 + tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", Klass::cast(except_oop->klass())->external_name(), except_oop()); + tty->print_cr(" thrown in interpreter method <%s>", istate->method()->name_and_sig_as_C_string()); + tty->print_cr(" at bci %d, continuing at %d for thread " INTPTR_FORMAT, + pc - (intptr_t)istate->method()->code_base(), + continuation_bci, thread); +#endif + return pc; + } +#if 0 + tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", Klass::cast(except_oop->klass())->external_name(), except_oop()); + tty->print_cr(" thrown in interpreter method <%s>", istate->method()->name_and_sig_as_C_string()); + tty->print_cr(" at bci %d, unwinding for thread " INTPTR_FORMAT, + pc - (intptr_t) istate->method()->code_base(), + thread); +#endif + thread->set_pending_exception(except_oop(), NULL, 0); + return 0; +} + #endif // STATIC_OFFSETS #ifdef STATIC_OFFSETS +#include "incls/_precompiled.incl" + class VMStructs { public: static void print_vm_offsets(void); @@ -57,6 +359,7 @@ void print_def(const char *s, int v) { + fprintf(outfile, "#undef %-40s\n", s); fprintf(outfile, "#define %-40s 0x%02x\n", s, v); } @@ -65,80 +368,115 @@ fputc('\n', outfile); } +// ZeroFrame is not friends with VMStructs, but it is with ZeroStackPrinter +class ZeroStackPrinter { +public: + static void print_vm_offsets(void); +}; + +void ZeroStackPrinter::print_vm_offsets(void) +{ + print_def("INTERPRETER_FRAME", ZeroFrame::INTERPRETER_FRAME); +} + void VMStructs::print_vm_offsets(void) { - print_def("THREAD_PENDING_EXC", offset_of(JavaThread, _pending_exception)); - print_def("THREAD_SUSPEND_FLAGS", offset_of(JavaThread, _suspend_flags)); - print_def("THREAD_ACTIVE_HANDLES", offset_of(JavaThread, _active_handles)); - print_def("THREAD_LAST_HANDLE_MARK", offset_of(JavaThread, _last_handle_mark)); - print_def("THREAD_TLAB_TOP", offset_of(JavaThread, _tlab) + offset_of(ThreadLocalAllocBuffer, _top)); - print_def("THREAD_TLAB_END", offset_of(JavaThread, _tlab) + offset_of(ThreadLocalAllocBuffer, _end)); - print_def("THREAD_RESOURCEAREA", offset_of(JavaThread, _resource_area)); - print_def("THREAD_HANDLE_AREA", offset_of(JavaThread, _handle_area)); - print_def("THREAD_STACK_BASE", offset_of(JavaThread, _stack_base)); - print_def("THREAD_STACK_SIZE", offset_of(JavaThread, _stack_size)); - print_def("THREAD_LAST_JAVA_SP", offset_of(JavaThread, _anchor) + offset_of(JavaFrameAnchor, _last_Java_sp)); - print_def("THREAD_JNI_ENVIRONMENT", offset_of(JavaThread, _jni_environment)); - print_def("THREAD_VM_RESULT", offset_of(JavaThread, _vm_result)); - print_def("THREAD_STATE", offset_of(JavaThread, _thread_state)); - print_def("THREAD_DO_NOT_UNLOCK", offset_of(JavaThread, _do_not_unlock_if_synchronized)); + print_def("ISTATE_THREAD", offset_of(BytecodeInterpreter, _thread)); + print_def("ISTATE_BCP", offset_of(BytecodeInterpreter, _bcp)); + print_def("ISTATE_LOCALS", offset_of(BytecodeInterpreter, _locals)); + print_def("ISTATE_CONSTANTS", offset_of(BytecodeInterpreter, _constants)); + print_def("ISTATE_METHOD", offset_of(BytecodeInterpreter, _method)); + print_def("ISTATE_STACK", offset_of(BytecodeInterpreter, _stack)); + print_def("ISTATE_MSG", offset_of(BytecodeInterpreter, _msg)); + print_def("ISTATE_OOP_TEMP", offset_of(BytecodeInterpreter, _oop_temp)); + print_def("ISTATE_STACK_BASE",offset_of(BytecodeInterpreter, _stack_base)); + print_def("ISTATE_STACK_LIMIT",offset_of(BytecodeInterpreter, _stack_limit)); + print_def("ISTATE_MONITOR_BASE",offset_of(BytecodeInterpreter, _monitor_base)); + print_def("ISTATE_SELF_LINK", offset_of(BytecodeInterpreter, _self_link)); + print_def("ISTATE_FRAME_TYPE", sizeof(BytecodeInterpreter) + 0); + print_def("ISTATE_NEXT_FRAME", sizeof(BytecodeInterpreter) + 4); + print_def("FRAME_SIZE", sizeof(BytecodeInterpreter) + 8); + nl(); + ZeroStackPrinter::print_vm_offsets(); + nl(); + print_def("THREAD_PENDING_EXC", offset_of(JavaThread, _pending_exception)); + print_def("THREAD_SUSPEND_FLAGS", offset_of(JavaThread, _suspend_flags)); + print_def("THREAD_ACTIVE_HANDLES", offset_of(JavaThread, _active_handles)); + print_def("THREAD_LAST_HANDLE_MARK", offset_of(JavaThread, _last_handle_mark)); + print_def("THREAD_TLAB_TOP", offset_of(JavaThread, _tlab) + offset_of(ThreadLocalAllocBuffer, _top)); + print_def("THREAD_TLAB_END", offset_of(JavaThread, _tlab) + offset_of(ThreadLocalAllocBuffer, _end)); + print_def("THREAD_RESOURCEAREA", offset_of(JavaThread, _resource_area)); + print_def("THREAD_HANDLE_AREA", offset_of(JavaThread, _handle_area)); + print_def("THREAD_STACK_BASE", offset_of(JavaThread, _stack_base)); + print_def("THREAD_STACK_SIZE", offset_of(JavaThread, _stack_size)); + print_def("THREAD_LAST_JAVA_SP", offset_of(JavaThread, _anchor) + offset_of(JavaFrameAnchor, _last_Java_sp)); + print_def("THREAD_JNI_ENVIRONMENT", offset_of(JavaThread, _jni_environment)); + print_def("THREAD_VM_RESULT", offset_of(JavaThread, _vm_result)); + print_def("THREAD_STATE", offset_of(JavaThread, _thread_state)); + print_def("THREAD_DO_NOT_UNLOCK", offset_of(JavaThread, _do_not_unlock_if_synchronized)); - print_def("THREAD_JAVA_STACK_BASE", offset_of(JavaThread, _zero_stack) + in_bytes(ZeroStack::base_offset())); - print_def("THREAD_JAVA_SP", offset_of(JavaThread, _zero_stack) + in_bytes(ZeroStack::sp_offset())); - print_def("THREAD_TOP_ZERO_FRAME", offset_of(JavaThread, _top_zero_frame)); - print_def("THREAD_SPECIALRUNTIMEEXITCONDITION", offset_of(JavaThread, _special_runtime_exit_condition)); - nl(); - print_def("_thread_external_suspend", Thread::_external_suspend); - print_def("_thread_ext_suspended", Thread::_ext_suspended); - print_def("_thread_deopt_suspend", Thread::_deopt_suspend); - nl(); - print_def("METHOD_CONSTMETHOD", offset_of(methodOopDesc, _constMethod)); - print_def("METHOD_CONSTANTS", offset_of(methodOopDesc, _constants)); - print_def("METHOD_METHODDATA", offset_of(methodOopDesc, _method_data)); - print_def("METHOD_INVOKECOUNT", offset_of(methodOopDesc, _interpreter_invocation_count)); - print_def("METHOD_ACCESSFLAGS", offset_of(methodOopDesc, _access_flags)); - print_def("METHOD_VTABLEINDEX", offset_of(methodOopDesc, _vtable_index)); - print_def("METHOD_RESULTINDEX", offset_of(methodOopDesc, _result_index)); - print_def("METHOD_METHODSIZE", offset_of(methodOopDesc, _method_size)); - print_def("METHOD_MAXSTACK", offset_of(methodOopDesc, _max_stack)); - print_def("METHOD_MAXLOCALS", offset_of(methodOopDesc, _max_locals)); - print_def("METHOD_SIZEOFPARAMETERS", offset_of(methodOopDesc, _size_of_parameters)); - print_def("METHOD_INVOCATIONCOUNTER", offset_of(methodOopDesc, _invocation_counter)); - print_def("METHOD_BACKEDGECOUNTER", offset_of(methodOopDesc, _backedge_counter)); - print_def("METHOD_FROM_INTERPRETED", offset_of(methodOopDesc, _from_interpreted_entry)); - // ECN: These two appear to be just tagged onto the end of the class - print_def("METHOD_NATIVEHANDLER", sizeof(methodOopDesc)); - print_def("METHOD_SIGNATUREHANDLER", sizeof(methodOopDesc)+4); - nl(); - print_def("CONSTMETHOD_CODESIZE", offset_of(constMethodOopDesc, _code_size)); - print_def("CONSTMETHOD_CODEOFFSET", sizeof(constMethodOopDesc)); - nl(); - print_def("JNIHANDLEBLOCK_TOP", offset_of(JNIHandleBlock, _top)); - nl(); - print_def("KLASS_PART", klassOopDesc::klass_part_offset_in_bytes()); - print_def("KLASS_ACCESSFLAGS", offset_of(Klass, _access_flags)); - print_def("INSTANCEKLASS_INITSTATE", offset_of(instanceKlass, _init_state)); - print_def("INSTANCEKLASS_VTABLE_LEN", offset_of(instanceKlass, _vtable_len)); - print_def("INSTANCEKLASS_ITABLE_LEN", offset_of(instanceKlass, _itable_len)); - print_def("INSTANCEKLASS_VTABLE_OFFSET", instanceKlass::vtable_start_offset() * sizeof(int *)); - print_def("OBJARRAYKLASS_ELEMENTKLASS", offset_of(objArrayKlass, _element_klass)); - nl(); - print_def("CONSTANTPOOL_TAGS", offset_of(constantPoolOopDesc, _tags)); - print_def("CONSTANTPOOL_CACHE", offset_of(constantPoolOopDesc, _cache)); - print_def("CONSTANTPOOL_BASE", sizeof(constantPoolOopDesc)); - nl(); - print_def("CP_OFFSET", in_bytes(constantPoolCacheOopDesc::base_offset())); - nl(); - print_def("BASE_OFFSET_BYTE", arrayOopDesc::base_offset_in_bytes(T_BYTE)); - print_def("BASE_OFFSET_SHORT", arrayOopDesc::base_offset_in_bytes(T_SHORT)); - print_def("BASE_OFFSET_WORD", arrayOopDesc::base_offset_in_bytes(T_INT)); - print_def("BASE_OFFSET_LONG", arrayOopDesc::base_offset_in_bytes(T_LONG)); - nl(); - print_def("SIZEOF_HANDLEMARK", sizeof(HandleMark)); + print_def("THREAD_JAVA_STACK_BASE", offset_of(JavaThread, _zero_stack) + in_bytes(ZeroStack::base_offset())); + print_def("THREAD_JAVA_SP", offset_of(JavaThread, _zero_stack) + in_bytes(ZeroStack::sp_offset())); + print_def("THREAD_TOP_ZERO_FRAME", offset_of(JavaThread, _top_zero_frame)); + print_def("THREAD_SPECIALRUNTIMEEXITCONDITION", offset_of(JavaThread, _special_runtime_exit_condition)); + nl(); + print_def("_thread_external_suspend", Thread::_external_suspend); + print_def("_thread_ext_suspended", Thread::_ext_suspended); + print_def("_thread_deopt_suspend", Thread::_deopt_suspend); + nl(); + print_def("METHOD_CONSTMETHOD", offset_of(methodOopDesc, _constMethod)); + print_def("METHOD_CONSTANTS", offset_of(methodOopDesc, _constants)); + print_def("METHOD_METHODDATA", offset_of(methodOopDesc, _method_data)); + print_def("METHOD_INVOKECOUNT", offset_of(methodOopDesc, _interpreter_invocation_count)); + print_def("METHOD_ACCESSFLAGS", offset_of(methodOopDesc, _access_flags)); + print_def("METHOD_VTABLEINDEX", offset_of(methodOopDesc, _vtable_index)); + print_def("METHOD_RESULTINDEX", offset_of(methodOopDesc, _result_index)); + print_def("METHOD_METHODSIZE", offset_of(methodOopDesc, _method_size)); + print_def("METHOD_MAXSTACK", offset_of(methodOopDesc, _max_stack)); + print_def("METHOD_MAXLOCALS", offset_of(methodOopDesc, _max_locals)); + print_def("METHOD_SIZEOFPARAMETERS", offset_of(methodOopDesc, _size_of_parameters)); + print_def("METHOD_INVOCATIONCOUNTER", offset_of(methodOopDesc, _invocation_counter)); + print_def("METHOD_BACKEDGECOUNTER", offset_of(methodOopDesc, _backedge_counter)); + print_def("METHOD_FROM_INTERPRETED", offset_of(methodOopDesc, _from_interpreted_entry)); + // ECN: These two appear to be just tagged onto the end of the class + print_def("METHOD_NATIVEHANDLER", sizeof(methodOopDesc)); + print_def("METHOD_SIGNATUREHANDLER", sizeof(methodOopDesc)+4); + nl(); + print_def("CONSTMETHOD_CODESIZE", offset_of(constMethodOopDesc, _code_size)); + print_def("CONSTMETHOD_CODEOFFSET", sizeof(constMethodOopDesc)); + nl(); + print_def("JNIHANDLEBLOCK_TOP", offset_of(JNIHandleBlock, _top)); + nl(); + print_def("KLASS_PART", klassOopDesc::klass_part_offset_in_bytes()); + print_def("KLASS_ACCESSFLAGS", offset_of(Klass, _access_flags)); + print_def("KLASS_JAVA_MIRROR", offset_of(Klass, _java_mirror)); + print_def("INSTANCEKLASS_INITSTATE", offset_of(instanceKlass, _init_state)); + print_def("INSTANCEKLASS_VTABLE_LEN", offset_of(instanceKlass, _vtable_len)); + print_def("INSTANCEKLASS_ITABLE_LEN", offset_of(instanceKlass, _itable_len)); + print_def("INSTANCEKLASS_VTABLE_OFFSET", instanceKlass::vtable_start_offset() * sizeof(int *)); + print_def("OBJARRAYKLASS_ELEMENTKLASS", offset_of(objArrayKlass, _element_klass)); + nl(); + print_def("CONSTANTPOOL_TAGS", offset_of(constantPoolOopDesc, _tags)); + print_def("CONSTANTPOOL_CACHE", offset_of(constantPoolOopDesc, _cache)); + print_def("CONSTANTPOOL_POOL_HOLDER", offset_of(constantPoolOopDesc, _pool_holder)); + print_def("CONSTANTPOOL_BASE", sizeof(constantPoolOopDesc)); + nl(); + print_def("CP_OFFSET", in_bytes(constantPoolCacheOopDesc::base_offset())); + nl(); + print_def("BASE_OFFSET_BYTE", arrayOopDesc::base_offset_in_bytes(T_BYTE)); + print_def("BASE_OFFSET_SHORT", arrayOopDesc::base_offset_in_bytes(T_SHORT)); + print_def("BASE_OFFSET_WORD", arrayOopDesc::base_offset_in_bytes(T_INT)); + print_def("BASE_OFFSET_LONG", arrayOopDesc::base_offset_in_bytes(T_LONG)); + nl(); + print_def("SIZEOF_HANDLEMARK", sizeof(HandleMark)); } int main(void) { + print_def("ARCH_VFP", ARCH_VFP); + print_def("ARCH_THUMBEE", ARCH_THUMBEE); + print_def("ARCH_CLZ", ARCH_CLZ); + nl(); print_def("JVM_CONSTANT_Utf8", JVM_CONSTANT_Utf8); print_def("JVM_CONSTANT_Unicode", JVM_CONSTANT_Unicode); print_def("JVM_CONSTANT_Integer", JVM_CONSTANT_Integer); @@ -190,6 +528,15 @@ print_def("T_ARRAY", T_ARRAY); print_def("T_VOID", T_VOID); nl(); + print_def("tos_btos", btos); + print_def("tos_ctos", ctos); + print_def("tos_stos", stos); + print_def("tos_itos", itos); + print_def("tos_ltos", ltos); + print_def("tos_ftos", ftos); + print_def("tos_dtos", dtos); + print_def("tos_atos", atos); + nl(); print_def("_thread_uninitialized", _thread_uninitialized); print_def("_thread_new", _thread_new); print_def("_thread_new_trans", _thread_new_trans);
--- a/ports/hotspot/src/cpu/zero/vm/bytecodes_arm.def Thu Jan 21 02:04:50 2010 +0000 +++ b/ports/hotspot/src/cpu/zero/vm/bytecodes_arm.def Thu Jan 28 16:34:49 2010 +0000 @@ -267,8 +267,6 @@ @return_register_finalizer = 0xe5, 1 -dmac = 0xe6, 2 - iload_0_iconst_N = 0xe7, 2 iload_1_iconst_N = 0xe8, 2 iload_2_iconst_N = 0xe9, 2 @@ -967,7 +965,7 @@ } (frem) frem { -@ ECN: It must be possible to do better than this +@ It must be possible to do better than this POP r0 bl __aeabi_f2d PUSH r0, r1 @@ -1336,166 +1334,138 @@ @ r2 = [jpc, #1] @ r1 = [jpc, #2] (ifeq,ifnull) ifeq_unsafe { + POP r3 ldrb r1, [jpc, #2] - POP r3 - mov r2, r2, lsl #24 cmp r3, #0 + beq 1f + DISPATCH 3 +1: + mov r2, r2, lsl #24 orr ip, r1, r2, asr #16 - beq 1f - mov ip, #3 -1: ldrb r0, [jpc, ip]! DISPATCH_BYTECODE } (ifne,ifnonnull) ifne_unsafe { + POP r3 ldrb r1, [jpc, #2] - POP r3 - mov r2, r2, lsl #24 cmp r3, #0 + bne 1f + DISPATCH 3 +1: + mov r2, r2, lsl #24 orr ip, r1, r2, asr #16 - bne 1f - mov ip, #3 -1: ldrb r0, [jpc, ip]! DISPATCH_BYTECODE } (iflt) iflt_unsafe { + POP r3 ldrb r1, [jpc, #2] - POP r3 - mov r2, r2, lsl #24 cmp r3, #0 + blt 1f + DISPATCH 3 +1: + mov r2, r2, lsl #24 orr ip, r1, r2, asr #16 - blt 1f - mov ip, #3 -1: ldrb r0, [jpc, ip]! DISPATCH_BYTECODE } (ifge) ifge_unsafe { + POP r3 ldrb r1, [jpc, #2] - POP r3 - mov r2, r2, lsl #24 cmp r3, #0 + bge 1f + DISPATCH 3 +1: + mov r2, r2, lsl #24 orr ip, r1, r2, asr #16 - bge 1f - mov ip, #3 -1: ldrb r0, [jpc, ip]! DISPATCH_BYTECODE } (ifgt) ifgt_unsafe { + POP r3 ldrb r1, [jpc, #2] - POP r3 - mov r2, r2, lsl #24 cmp r3, #0 + bgt 1f + DISPATCH 3 +1: + mov r2, r2, lsl #24 orr ip, r1, r2, asr #16 - bgt 1f - mov ip, #3 -1: ldrb r0, [jpc, ip]! DISPATCH_BYTECODE } (ifle) ifle_unsafe { + POP r3 ldrb r1, [jpc, #2] - POP r3 - mov r2, r2, lsl #24 cmp r3, #0 + ble 1f + DISPATCH 3 +1: + mov r2, r2, lsl #24 orr ip, r1, r2, asr #16 - ble 1f - mov ip, #3 -1: ldrb r0, [jpc, ip]! DISPATCH_BYTECODE } (if_icmpeq,if_acmpeq) if_icmpeq_unsafe { + POP r3, tmp1 ldrb r1, [jpc, #2] - POP r3, tmp1 - mov r2, r2, lsl #24 cmp tmp1, r3 - orr ip, r1, r2, asr #16 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe + DISPATCH 3 } (if_icmpne,if_acmpne) if_icmpne_unsafe { + POP r3, tmp1 ldrb r1, [jpc, #2] - POP r3, tmp1 - mov r2, r2, lsl #24 cmp tmp1, r3 - orr ip, r1, r2, asr #16 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe + DISPATCH 3 } (if_icmplt) if_icmplt_unsafe { + POP r3, tmp1 ldrb r1, [jpc, #2] - POP r3, tmp1 - mov r2, r2, lsl #24 cmp tmp1, r3 - orr ip, r1, r2, asr #16 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe + DISPATCH 3 } (if_icmpge) if_icmpge_unsafe { + POP r3, tmp1 ldrb r1, [jpc, #2] - POP r3, tmp1 - mov r2, r2, lsl #24 cmp tmp1, r3 - orr ip, r1, r2, asr #16 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe + DISPATCH 3 } (if_icmpgt) if_icmpgt_unsafe { + POP r3, tmp1 ldrb r1, [jpc, #2] - POP r3, tmp1 - mov r2, r2, lsl #24 cmp tmp1, r3 - orr ip, r1, r2, asr #16 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe + DISPATCH 3 } (if_icmple) if_icmple_unsafe { + POP r3, tmp1 ldrb r1, [jpc, #2] - POP r3, tmp1 - mov r2, r2, lsl #24 cmp tmp1, r3 - orr ip, r1, r2, asr #16 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe + DISPATCH 3 } (goto) goto_unsafe { ldrb r1, [jpc, #2] mov r2, r2, lsl #24 - orr ip, r1, r2, asr #16 - DISPATCH_START_REG ip + orr tmp1, r1, r2, asr #16 + DISPATCH_START_REG tmp1 + USEC cmp tmp1, #0 + USEC ble do_backedge DISPATCH_BYTECODE } @@ -1520,7 +1490,7 @@ DISPATCH 48 } -@ ECN: We dont do safe and unsafe versions of tableswitch and lookupswitch +@ We dont do safe and unsafe versions of tableswitch and lookupswitch (tableswitch) tableswitch { POP a2 bic a1, jpc, #3 @@ -1752,28 +1722,17 @@ (aputfield) aputfield { ldrb r1, [jpc, #2] - GET_STACK 1, r0 @ r0 = object - POP oop_value_tmp @ r1 = value - add r3, constpool, r1, lsl #12 - add r3, r3, r2, lsl #4 - ldr r3, [r3, #CP_OFFSET+8] - SW_NPC cmp r0, #0 - add oop_address_tmp, r0, r3 - SW_NPC beq null_ptr_exception + POP r3, tmp1 @ r3 = value, tmp1 = object + add tmp2, constpool, r1, lsl #12 + add tmp2, tmp2, r2, lsl #4 + SW_NPC cmp tmp1, #0 + SW_NPC beq null_ptr_exception_jpc_3 + ldr tmp2, [tmp2, #CP_OFFSET+8] .abortentry113: - HW_NPC ldr ip, [r0] @ Only to provoke an abort - bl oop_store - ldr r3, [dispatch, #Universe_collectedHeap_Address-XXX] - DISPATCH_START 3 - POP r2 - ldr r3, [r3, #0] - DISPATCH_NEXT - ldr r3, [r3, #12] - DISPATCH_NEXT - ldr r3, [r3, #76] - mov tmp2, #0 - strb tmp2, [r3, r2, lsr #9] - DISPATCH_FINISH + str r3, [tmp1, tmp2] + mov r0, tmp1 + bl Helper_aputfield + DISPATCH 3 } (lputfield) lputfield { @@ -1862,29 +1821,11 @@ add r1, r2, #4 str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] add stack, r1, r0, lsl #2 - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT - add r2, r2, #4 - DISPATCH_NEXT - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT - DISPATCH_FINISH + + str stack, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} 1: bl return_check_monitors b 2b @@ -1909,30 +1850,12 @@ ldr r3, [stack, #0] ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH + + str stack, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} 1: bl return_check_monitors b 2b @@ -1956,33 +1879,14 @@ add r1, r2, #4 str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - POP r2, r3 add stack, r1, r0, lsl #2 stmdb stack!, {r2, r3} - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT - add r2, r2, #4 - DISPATCH_NEXT - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT - DISPATCH_FINISH + + str stack, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} 1: bl return_check_monitors b 2b @@ -2032,12 +1936,10 @@ mov r1, #0 bl _ZN18InterpreterRuntime3ldcEP10JavaThreadb ldr r0, [istate, #ISTATE_THREAD] @ thread - ASSERT_STACK_CACHED CACHE_CP ldr r1, [r0, #THREAD_PENDING_EXC] CACHE_JPC cmp r1, #0 - ASSERT_LOCALS_CACHED bne handle_exception ldr r3, [r0, #THREAD_VM_RESULT] mov r2, #0 @@ -2089,8 +1991,6 @@ DECACHE_STACK mov r1, #1 bl _ZN18InterpreterRuntime3ldcEP10JavaThreadb - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] @ thread CACHE_CP ldr r1, [r0, #THREAD_PENDING_EXC] @@ -2455,10 +2355,7 @@ } (dmul) dmul_vfp { - FBC cmp r2, #opc_dadd DISPATCH_START_R2 - FBC beq 1f -2: vldr d7, [stack, #12] vldr d6, [stack, #4] DISPATCH_NEXT @@ -2469,30 +2366,7 @@ vstr d0, [stack, #12] add stack, stack, #8 DISPATCH_FINISH -1: - FBC mov r2, #opc_dmac - FBC strb r2, [jpc, #-1] - FBC b 2b -} - -#ifdef FAST_BYTECODES - -(dmac) dmac_vfp { - DISPATCH_START \seq_len - vldr d2, [stack, #20] - vldr d1, [stack, #12] - vldr d0, [stack, #4] - DISPATCH_NEXT - DISPATCH_NEXT - fmacd d2, d1, d0 - DISPATCH_NEXT - DISPATCH_NEXT - vstr d2, [stack, #20] - add stack, stack, #16 - DISPATCH_FINISH -} - -#endif // FAST_BYTECODES +} (fdiv) fdiv_vfp { DISPATCH_START_R2 @@ -2623,10 +2497,10 @@ #ifdef FAST_BYTECODES @############################################################################## -@ ECN: Optimised bytecode pairs +@ Optimised bytecode pairs @############################################################################## -@ --- ECN: load; iaccess ------------------------------------------------------ +@ --- load; iaccess ------------------------------------------------------ (iload_0,iload_1,iload_2,iload_3) (iaccess_0,iaccess_1,iaccess_2,iaccess_3) @@ -2680,7 +2554,7 @@ DISPATCH_FINISH } -@ --- ECN: load; load --------------------------------------------------------- +@ --- load; load --------------------------------------------------------- (aload_0,aload_1,aload_2,aload_3) (aload_0,aload_1,aload_2,aload_3) @@ -2875,7 +2749,7 @@ DISPATCH_FINISH } -@ --- ECN: load; store -------------------------------------------------------- +@ --- load; store -------------------------------------------------------- (aload_0,aload_1,aload_2,aload_3) (astore_0,astore_1,astore_2,astore_3) @@ -2986,7 +2860,7 @@ DISPATCH_FINISH } -@ --- ECN: load; const ------------------------------------------------------- +@ --- load; const ------------------------------------------------------- (aload_0,aload_1,aload_2,aload_3) (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5) @@ -3109,7 +2983,7 @@ DISPATCH_FINISH } -@ --- ECN: load; Xaload ------------------------------------------------------- +@ --- load; Xaload ------------------------------------------------------- (iload_0,iload_1,iload_2,iload_3) (iaload,aaload,faload) @@ -3271,7 +3145,7 @@ DISPATCH_FINISH } -@ --- ECN: load; Xastore ------------------------------------------------------- +@ --- load; Xastore ------------------------------------------------------- (iload_0,iload_1,iload_2,iload_3) (iastore,fastore) @@ -3384,7 +3258,7 @@ DISPATCH_FINISH } -@ --- ECN: load; dataop ------------------------------------------------------- +@ --- load; dataop ------------------------------------------------------- (iload_0,iload_1,iload_2,iload_3) (iadd) @@ -3472,40 +3346,6 @@ } (iload_0,iload_1,iload_2,iload_3) -(idiv) -{ - rsb tmp2, r0, #opc_iload_0 - DISPATCH_START 2 - ldr tmp2, [locals, tmp2, lsl #2] - POP tmp1 - b int_div -} - -(iload,aload,fload)(idiv) { - DISPATCH_START 3 - POP tmp1 - ldr tmp2, [locals, -r2, lsl #2] - b int_div -} - -(iload_0,iload_1,iload_2,iload_3) -(irem) -{ - rsb tmp2, r0, #opc_iload_0 - DISPATCH_START 2 - ldr tmp2, [locals, tmp2, lsl #2] - POP tmp1 - b int_rem -} - -(iload,aload,fload)(irem) { - DISPATCH_START 3 - POP tmp1 - ldr tmp2, [locals, -r2, lsl #2] - b int_rem -} - -(iload_0,iload_1,iload_2,iload_3) (ineg) { rsb lr, r0, #opc_iload_0 @@ -3717,192 +3557,138 @@ #ifdef NOTICE_SAFEPOINTS -@ --- ECN: load; branch ------------------------------------------------------- +@ --- load; branch ------------------------------------------------------- (iload_0,iload_1,iload_2,iload_3) (ifeq,ifnull) { + rsb r3, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r3, [locals, r3, lsl #2] ldrb ip, [jpc, #3] - rsb r3, r0, #opc_iload_0 - add jpc, jpc, #1 - ldr r3, [locals, r3, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(ifeq,ifnull) { + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r3, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - add jpc, jpc, #2 - ldr r3, [locals, -r2, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) (ifne,ifnonnull) { + rsb r3, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r3, [locals, r3, lsl #2] ldrb ip, [jpc, #3] - rsb r3, r0, #opc_iload_0 - add jpc, jpc, #1 - ldr r3, [locals, r3, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(ifne,ifnonnull) { + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r3, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - add jpc, jpc, #2 - ldr r3, [locals, -r2, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) (iflt) { + rsb r3, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r3, [locals, r3, lsl #2] ldrb ip, [jpc, #3] - rsb r3, r0, #opc_iload_0 - add jpc, jpc, #1 - ldr r3, [locals, r3, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(iflt) { + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r3, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - add jpc, jpc, #2 - ldr r3, [locals, -r2, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) (ifge) { + rsb r3, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r3, [locals, r3, lsl #2] ldrb ip, [jpc, #3] - rsb r3, r0, #opc_iload_0 - add jpc, jpc, #1 - ldr r3, [locals, r3, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(ifge) { + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r3, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - add jpc, jpc, #2 - ldr r3, [locals, -r2, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) (ifgt) { + rsb r3, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r3, [locals, r3, lsl #2] ldrb ip, [jpc, #3] - rsb r3, r0, #opc_iload_0 - add jpc, jpc, #1 - ldr r3, [locals, r3, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(ifgt) { + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r3, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - add jpc, jpc, #2 - ldr r3, [locals, -r2, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) (ifle) { + rsb r3, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r3, [locals, r3, lsl #2] ldrb ip, [jpc, #3] - rsb r3, r0, #opc_iload_0 - add jpc, jpc, #1 - ldr r3, [locals, r3, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(ifle) { + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r3, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - add jpc, jpc, #2 - ldr r3, [locals, -r2, lsl #2] cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) @@ -3911,31 +3697,22 @@ POP r3 rsb r2, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #3] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #1 cmp r3, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(if_icmpeq,if_acmpeq) { POP r3 + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, -r2, lsl #2] - add jpc, jpc, #2 cmp r3, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) @@ -3944,31 +3721,22 @@ POP r3 rsb r2, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #3] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #1 cmp r3, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(if_icmpne,if_acmpne) { POP r3 + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, -r2, lsl #2] - add jpc, jpc, #2 cmp r3, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) @@ -3977,31 +3745,22 @@ POP r3 rsb r2, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #3] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #1 cmp r3, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(if_icmplt) { POP r3 + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, -r2, lsl #2] - add jpc, jpc, #2 cmp r3, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) @@ -4010,31 +3769,22 @@ POP r3 rsb r2, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #3] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #1 cmp r3, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(if_icmpge) { POP r3 + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, -r2, lsl #2] - add jpc, jpc, #2 cmp r3, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) @@ -4043,31 +3793,22 @@ POP r3 rsb r2, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #3] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #1 cmp r3, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(if_icmpgt) { POP r3 + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, -r2, lsl #2] - add jpc, jpc, #2 cmp r3, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_2 + DISPATCH 5 } (iload_0,iload_1,iload_2,iload_3) @@ -4076,34 +3817,25 @@ POP r3 rsb r2, r0, #opc_iload_0 ldrsb r1, [jpc, #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #3] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #1 cmp r3, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_1 + DISPATCH 4 } (iload,aload,fload)(if_icmple) { POP r3 + rsb r2, r2, #0 ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, -r2, lsl #2] - add jpc, jpc, #2 cmp r3, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -@ --- ECN: load; return/invoke ------------------------------------------------- + ble branch_taken_unsafe_2 + DISPATCH 5 +} + +@ --- load; return/invoke ------------------------------------------------- (iload_0,iload_1,iload_2,iload_3) (ireturn,areturn,freturn) @@ -4122,30 +3854,12 @@ ldr r0, [istate, #ISTATE_METHOD] ldr r3, [stack, #0] ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH + + str stack, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} 1: PUSH r1 add jpc, jpc, #1 @@ -4169,30 +3883,12 @@ ldr r0, [istate, #ISTATE_METHOD] ldr r3, [stack, #0] ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH + + str stack, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} 1: PUSH r1 add jpc, jpc, #2 @@ -4399,7 +4095,7 @@ DISPATCH_FINISH } -@ --- ECN: iconst; store ------------------------------------------------- +@ --- iconst; store ------------------------------------------------- (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5) (istore_0,istore_1,istore_2,istore_3) @@ -4419,7 +4115,7 @@ DISPATCH_BYTECODE } -@ --- ECN: iconst; dataop ------------------------------------------------- +@ --- iconst; dataop ------------------------------------------------- (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(iadd) { sub tmp1, r0, #opc_iconst_0 @@ -4505,7 +4201,7 @@ DISPATCH_FINISH } -@ --- ECN: iconst; branch ------------------------------------------------- +@ --- iconst; branch ------------------------------------------------- #ifdef NOTICE_SAFEPOINTS @@ -4513,90 +4209,60 @@ POP r3 sub r2, r0, #opc_iconst_0 ldrsb r1, [jpc, #2] + cmp r3, r2 ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_1 + DISPATCH 4 } (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(if_icmpne) { POP r3 sub r2, r0, #opc_iconst_0 ldrsb r1, [jpc, #2] + cmp r3, r2 ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_1 + DISPATCH 4 } (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(if_icmplt) { POP r3 sub r2, r0, #opc_iconst_0 ldrsb r1, [jpc, #2] + cmp r3, r2 ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_1 + DISPATCH 4 } (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(if_icmpge) { POP r3 sub r2, r0, #opc_iconst_0 ldrsb r1, [jpc, #2] + cmp r3, r2 ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_1 + DISPATCH 4 } (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(if_icmpgt) { POP r3 sub r2, r0, #opc_iconst_0 ldrsb r1, [jpc, #2] + cmp r3, r2 ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_1 + DISPATCH 4 } (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(if_icmple) { POP r3 sub r2, r0, #opc_iconst_0 ldrsb r1, [jpc, #2] + cmp r3, r2 ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_1 + DISPATCH 4 } (iconst_m1,iconst_0,iconst_1,iconst_2,iconst_3,iconst_4,iconst_5)(ireturn) { @@ -4613,30 +4279,12 @@ ldr r0, [istate, #ISTATE_METHOD] ldr r3, [stack, #0] ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH + + str stack, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} 1: PUSH r1 add jpc, jpc, #1 @@ -5001,292 +4649,6 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(iaload,faload,aaload)(ifeq,ifnull) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry61: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r3, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(ifne,ifnonnull) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry62: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r3, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(iflt) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry63: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r3, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(ifge) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry64: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r3, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(ifgt) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry65: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r3, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(ifle) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry66: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r3, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(if_icmpeq,if_acmpeq) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry67: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r2, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - POP r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(if_icmpne,if_acmpne) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry68: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r2, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - POP r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(if_icmplt) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry69: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r2, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - POP r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(if_icmpge) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry70: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r2, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - POP r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(if_icmpgt) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry71: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r2, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - POP r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaload,faload,aaload)(if_icmple) { - POP r2, r3 @ r2 = index, r3 = arrayref - SW_NPC cmp r3, #0 - SW_NPC beq null_ptr_exception_jpc_0 -.abortentry72: - ldr r1, [r3, #8] @ r1 = length - cmp r2, r1 - bcs array_bound_exception_jpc_0 - add r3, r3, r2, lsl #2 - ldr r2, [r3, #BASE_OFFSET_WORD] @ r1 = tos - - POP r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - cmp r3, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -#endif // NOTICE_SAFEPOINTS - @ ---- iadd; xxx ------------------------------------------------------------ (iadd)(iload,fload,aload) { @@ -5395,255 +4757,11 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(iadd)(ifeq,ifnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(ifne,ifnonnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(iflt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(ifge) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(ifgt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(ifle) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(if_icmpeq,if_acmpeq) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(if_icmpne,if_acmpne) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(if_icmplt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(if_icmpge) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(if_icmpgt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(if_icmple) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iadd)(goto) { - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - orr ip, ip, r1, lsl #8 - DISPATCH_START_REG ip - POP r2, r3 - add r2, r3, r2 - DISPATCH_NEXT - PUSH r2 - DISPATCH_FINISH -} - -(iadd)(ireturn) { - POP r2, r3 - ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base - ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end - add r1, r3, r2 - ldr tmp_xxx, [istate, #ISTATE_THREAD] - cmp tmp1, tmp2 - bcc 1f -2: - mov r3, #0 - ldr stack, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - ldr r0, [istate, #ISTATE_METHOD] - ldr r3, [stack, #0] - ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH -1: - PUSH r1 - add jpc, jpc, #1 - bl return_check_monitors - POP r1 - b 2b -} - -#endif // NOTICE_SAFEPOINTS - (iadd)(iinc) { POP tmp1, lr DISPATCH_START \seq_len add tmp1, lr, tmp1 - ldrb r3, [jpc, #-2] @ ECN: jpc now points to next bc + ldrb r3, [jpc, #-2] @ jpc now points to next bc ldrsb r2, [jpc, #-1] DISPATCH_NEXT PUSH tmp1 @@ -5761,255 +4879,11 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(isub)(ifeq,ifnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(ifne,ifnonnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(iflt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(ifge) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(ifgt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(ifle) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(if_icmpeq,if_acmpeq) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(if_icmpne,if_acmpne) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(if_icmplt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(if_icmpge) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(if_icmpgt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(if_icmple) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - sub r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(isub)(goto) { - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - orr ip, ip, r1, lsl #8 - DISPATCH_START_REG ip - POP r2, r3 - sub r2, r3, r2 - DISPATCH_NEXT - PUSH r2 - DISPATCH_FINISH -} - -(isub)(ireturn) { - POP r2, r3 - ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base - ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end - sub r1, r3, r2 - ldr tmp_xxx, [istate, #ISTATE_THREAD] - cmp tmp1, tmp2 - bcc 1f -2: - mov r3, #0 - ldr stack, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - ldr r0, [istate, #ISTATE_METHOD] - ldr r3, [stack, #0] - ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH -1: - PUSH r1 - add jpc, jpc, #1 - bl return_check_monitors - POP r1 - b 2b -} - -#endif // NOTICE_SAFEPOINTS - (isub)(iinc) { POP tmp1, lr DISPATCH_START \seq_len sub tmp1, lr, tmp1 - ldrb r3, [jpc, #-2] @ ECN: jpc now points to next bc + ldrb r3, [jpc, #-2] @ jpc now points to next bc ldrsb r2, [jpc, #-1] DISPATCH_NEXT PUSH tmp1 @@ -6127,255 +5001,11 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(iand)(ifeq,ifnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(ifne,ifnonnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(iflt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(ifge) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(ifgt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(ifle) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(if_icmpeq,if_acmpeq) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(if_icmpne,if_acmpne) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(if_icmplt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(if_icmpge) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(if_icmpgt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(if_icmple) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - and r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iand)(goto) { - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - orr ip, ip, r1, lsl #8 - DISPATCH_START_REG ip - POP r2, r3 - and r2, r3, r2 - DISPATCH_NEXT - PUSH r2 - DISPATCH_FINISH -} - -(iand)(ireturn) { - POP r2, r3 - ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base - ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end - and r1, r3, r2 - ldr tmp_xxx, [istate, #ISTATE_THREAD] - cmp tmp1, tmp2 - bcc 1f -2: - mov r3, #0 - ldr stack, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - ldr r0, [istate, #ISTATE_METHOD] - ldr r3, [stack, #0] - ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH -1: - PUSH r1 - add jpc, jpc, #1 - bl return_check_monitors - POP r1 - b 2b -} - -#endif // NOTICE_SAFEPOINTS - (iand)(iinc) { POP tmp1, lr DISPATCH_START \seq_len and tmp1, lr, tmp1 - ldrb r3, [jpc, #-2] @ ECN: jpc now points to next bc + ldrb r3, [jpc, #-2] @ jpc now points to next bc ldrsb r2, [jpc, #-1] DISPATCH_NEXT PUSH tmp1 @@ -6493,255 +5123,11 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(ior)(ifeq,ifnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(ifne,ifnonnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(iflt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(ifge) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(ifgt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(ifle) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(if_icmpeq,if_acmpeq) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(if_icmpne,if_acmpne) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(if_icmplt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(if_icmpge) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(if_icmpgt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(if_icmple) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - orr r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ior)(goto) { - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - orr ip, ip, r1, lsl #8 - DISPATCH_START_REG ip - POP r2, r3 - orr r2, r3, r2 - DISPATCH_NEXT - PUSH r2 - DISPATCH_FINISH -} - -(ior)(ireturn) { - POP r2, r3 - ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base - ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end - orr r1, r3, r2 - ldr tmp_xxx, [istate, #ISTATE_THREAD] - cmp tmp1, tmp2 - bcc 1f -2: - mov r3, #0 - ldr stack, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - ldr r0, [istate, #ISTATE_METHOD] - ldr r3, [stack, #0] - ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH -1: - PUSH r1 - add jpc, jpc, #1 - bl return_check_monitors - POP r1 - b 2b -} - -#endif // NOTICE_SAFEPOINTS - (ior)(iinc) { POP tmp1, lr DISPATCH_START \seq_len orr tmp1, lr, tmp1 - ldrb r3, [jpc, #-2] @ ECN: jpc now points to next bc + ldrb r3, [jpc, #-2] @ jpc now points to next bc ldrsb r2, [jpc, #-1] DISPATCH_NEXT PUSH tmp1 @@ -6844,7 +5230,7 @@ DISPATCH_NEXT DISPATCH_NEXT PUSH tmp2 - DISPATCH_FINISH + DISPATCH_FINISH } (ixor)(isub) { @@ -6860,255 +5246,11 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(ixor)(ifeq,ifnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(ifne,ifnonnull) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(iflt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(ifge) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(ifgt) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(ifle) { - POP r2, r3 - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r3, r3, r2 - add jpc, jpc, #1 - cmp r3, #0 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(if_icmpeq,if_acmpeq) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(if_icmpne,if_acmpne) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(if_icmplt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(if_icmpge) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(if_icmpgt) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(if_icmple) { - POP r2, r3, lr - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - eor r2, r3, r2 - add jpc, jpc, #1 - cmp lr, r2 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(ixor)(goto) { - ldrsb r1, [jpc, #2] - ldrb ip, [jpc, #3] - add jpc, jpc, #1 - orr ip, ip, r1, lsl #8 - DISPATCH_START_REG ip - POP r2, r3 - eor r2, r3, r2 - DISPATCH_NEXT - PUSH r2 - DISPATCH_FINISH -} - -(ixor)(ireturn) { - POP r2, r3 - ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base - ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end - eor r1, r3, r2 - ldr tmp_xxx, [istate, #ISTATE_THREAD] - cmp tmp1, tmp2 - bcc 1f -2: - mov r3, #0 - ldr stack, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - ldr r0, [istate, #ISTATE_METHOD] - ldr r3, [stack, #0] - ldrh r0, [r0, #40] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - str r1, [stack, r0, lsl #2]! - cmp ip, #0 - beq normal_return - - sub istate, istate, #ISTATE_NEXT_FRAME - - CACHE_JPC - ldr r2, [istate, #ISTATE_STACK_LIMIT] - DISPATCH_START_REG ip - sub stack, stack, #4 - ldr r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - DISPATCH_NEXT @ ldrb r1, [jpc, #2] - add r2, r2, #4 - DISPATCH_NEXT @ ldr ip, [dispatch, r0, lsl #2] - str r2, [tmp_xxx, #THREAD_JAVA_SP] - DISPATCH_NEXT @ ldrb r2, [jpc, #1] - str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] - CACHE_CP - CACHE_LOCALS - DISPATCH_NEXT @ ands lr, ip, lr - DISPATCH_FINISH -1: - PUSH r1 - add jpc, jpc, #1 - bl return_check_monitors - POP r1 - b 2b -} - -#endif // NOTICE_SAFEPOINTS - (ixor)(iinc) { POP tmp1, lr DISPATCH_START \seq_len eor tmp1, lr, tmp1 - ldrb r3, [jpc, #-2] @ ECN: jpc now points to next bc + ldrb r3, [jpc, #-2] @ jpc now points to next bc ldrsb r2, [jpc, #-1] DISPATCH_NEXT PUSH tmp1 @@ -7175,7 +5317,7 @@ } @############################################################################### -@# ECN: Optimised bytecode triples +@# Optimised bytecode triples @############################################################################### (iaccess_0,iaccess_1,iaccess_2,iaccess_3) @@ -7251,316 +5393,6 @@ DISPATCH_FINISH } -#ifdef NOTICE_SAFEPOINTS - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(ifeq,ifnull) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - orr ip, ip, r0, lsl #8 -.abortentry92: - ldr tmp2, [tmp1, tmp2] - cmp tmp2, #0 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(ifne,ifnonnull) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - orr ip, ip, r0, lsl #8 -.abortentry93: - ldr tmp2, [tmp1, tmp2] - cmp tmp2, #0 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(iflt) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - orr ip, ip, r0, lsl #8 -.abortentry94: - ldr tmp2, [tmp1, tmp2] - cmp tmp2, #0 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(ifge) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - orr ip, ip, r0, lsl #8 -.abortentry95: - ldr tmp2, [tmp1, tmp2] - cmp tmp2, #0 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(ifgt) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - orr ip, ip, r0, lsl #8 -.abortentry96: - ldr tmp2, [tmp1, tmp2] - cmp tmp2, #0 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(ifle) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - orr ip, ip, r0, lsl #8 -.abortentry97: - ldr tmp2, [tmp1, tmp2] - cmp tmp2, #0 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(if_icmpeq,if_acmpeq) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - POP r3 - orr ip, ip, r0, lsl #8 -.abortentry98: - ldr tmp2, [tmp1, tmp2] - cmp r3, tmp2 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(if_icmpne,if_acmpne) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - POP r3 - orr ip, ip, r0, lsl #8 -.abortentry99: - ldr tmp2, [tmp1, tmp2] - cmp r3, tmp2 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(if_icmplt) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - POP r3 - orr ip, ip, r0, lsl #8 -.abortentry100: - ldr tmp2, [tmp1, tmp2] - cmp r3, tmp2 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(if_icmpge) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - POP r3 - orr ip, ip, r0, lsl #8 -.abortentry101: - ldr tmp2, [tmp1, tmp2] - cmp r3, tmp2 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(if_icmpgt) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - POP r3 - orr ip, ip, r0, lsl #8 -.abortentry102: - ldr tmp2, [tmp1, tmp2] - cmp r3, tmp2 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -(iaccess_0,iaccess_1,iaccess_2,iaccess_3) -(if_icmple) { - ldrb r2, [jpc, #3] - rsb tmp1, r0, #opc_iaccess_0 - ldrb ip, [jpc, #2] - add jpc, jpc, #4 - ldrsb r0, [jpc, #1] - add tmp2, constpool, r2, lsl #12 - ldr tmp1, [locals, tmp1, lsl #2] - add tmp2, ip, lsl #4 - ldrb ip, [jpc, #2] - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception_jpc_3 - ldr tmp2, [tmp2, #CP_OFFSET+8] - POP r3 - orr ip, ip, r0, lsl #8 -.abortentry103: - ldr tmp2, [tmp1, tmp2] - cmp r3, tmp2 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -#endif // NOTICE_SAFEPOINTS - (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) (iadd) { @@ -8564,23 +6396,20 @@ DISPATCH_FINISH } +#ifdef NOTICE_SAFEPOINTS + (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) (if_icmpeq,if_acmpeq) { ldrb r3, [jpc, #1] rsb r2, r0, #opc_iload_0_iconst_N ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_2 + DISPATCH 5 } (iload_iconst_N) @@ -8589,17 +6418,12 @@ ldrb r3, [jpc, #2] rsb r2, r2, #0 ldrsb r1, [jpc, #4] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #5] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #3 cmp r2, r3 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) @@ -8608,17 +6432,12 @@ ldrb r3, [jpc, #1] rsb r2, r0, #opc_iload_0_iconst_N ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_2 + DISPATCH 5 } (iload_iconst_N) @@ -8627,17 +6446,12 @@ ldrb r3, [jpc, #2] rsb r2, r2, #0 ldrsb r1, [jpc, #4] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #5] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #3 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) @@ -8646,17 +6460,12 @@ ldrb r3, [jpc, #1] rsb r2, r0, #opc_iload_0_iconst_N ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_2 + DISPATCH 5 } (iload_iconst_N) @@ -8665,17 +6474,12 @@ ldrb r3, [jpc, #2] rsb r2, r2, #0 ldrsb r1, [jpc, #4] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #5] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #3 cmp r2, r3 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) @@ -8684,17 +6488,12 @@ ldrb r3, [jpc, #1] rsb r2, r0, #opc_iload_0_iconst_N ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_2 + DISPATCH 5 } (iload_iconst_N) @@ -8703,17 +6502,12 @@ ldrb r3, [jpc, #2] rsb r2, r2, #0 ldrsb r1, [jpc, #4] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #5] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #3 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) @@ -8722,17 +6516,12 @@ ldrb r3, [jpc, #1] rsb r2, r0, #opc_iload_0_iconst_N ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_2 + DISPATCH 5 } (iload_iconst_N) @@ -8741,17 +6530,12 @@ ldrb r3, [jpc, #2] rsb r2, r2, #0 ldrsb r1, [jpc, #4] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #5] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #3 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iconst_N,iload_1_iconst_N,iload_2_iconst_N,iload_3_iconst_N) @@ -8760,17 +6544,12 @@ ldrb r3, [jpc, #1] rsb r2, r0, #opc_iload_0_iconst_N ldrsb r1, [jpc, #3] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_2 + DISPATCH 5 } (iload_iconst_N) @@ -8779,18 +6558,15 @@ ldrb r3, [jpc, #2] rsb r2, r2, #0 ldrsb r1, [jpc, #4] + ldr r2, [locals, r2, lsl #2] sub r3, r3, #opc_iconst_0 ldrb ip, [jpc, #5] - ldr r2, [locals, r2, lsl #2] - add jpc, jpc, #3 cmp r2, r3 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} + ble branch_taken_unsafe_3 + DISPATCH 6 +} + +#endif // NOTICE_SAFEPOINTS (iload_iload) (iadd_istore_N) @@ -9582,23 +7358,20 @@ DISPATCH_FINISH } +#ifdef NOTICE_SAFEPOINTS + (iload_iload) (if_icmpeq,if_acmpeq) { ldrb r3, [jpc, #3] rsb r2, r2, #0 ldrsb r1, [jpc, #5] rsb r3, r3, #0 - ldrb ip, [jpc, #6] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #4 + ldrb ip, [jpc, #6] cmp r2, r3 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_4 + DISPATCH 7 } (iload_iload_N) @@ -9607,17 +7380,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #4] rsb r3, r3, #opc_iload_0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload,iload_1_iload,iload_2_iload,iload_3_iload) @@ -9626,35 +7394,39 @@ rsb r2, r0, #opc_iload_0_iload ldrsb r1, [jpc, #4] rsb r3, r3, #0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + beq branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload_N,iload_1_iload_N,iload_2_iload_N,iload_3_iload_N) (if_icmpeq,if_acmpeq) { rsb r3, r2, #opc_iload_0 + ldrsb r1, [jpc, #3] rsb r2, r0, #opc_iload_0_iload_N - ldrsb r1, [jpc, #3] + ldr r3, [locals, r3, lsl #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] + cmp r2, r3 + beq branch_taken_unsafe_2 + DISPATCH 5 +} + +(iload_iload) +(if_icmpne,if_acmpne) { + ldrb r3, [jpc, #3] + rsb r2, r2, #0 + ldrsb r1, [jpc, #5] + rsb r3, r3, #0 ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #2 + ldrb ip, [jpc, #6] cmp r2, r3 - orr ip, ip, r1, lsl #8 - beq 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_4 + DISPATCH 7 } (iload_iload_N) @@ -9663,17 +7435,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #4] rsb r3, r3, #opc_iload_0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload,iload_1_iload,iload_2_iload,iload_3_iload) @@ -9682,35 +7449,25 @@ rsb r2, r0, #opc_iload_0_iload ldrsb r1, [jpc, #4] rsb r3, r3, #0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload_N,iload_1_iload_N,iload_2_iload_N,iload_3_iload_N) (if_icmpne,if_acmpne) { rsb r3, r2, #opc_iload_0 + ldrsb r1, [jpc, #3] rsb r2, r0, #opc_iload_0_iload_N - ldrsb r1, [jpc, #3] + ldr r3, [locals, r3, lsl #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bne 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bne branch_taken_unsafe_2 + DISPATCH 5 } (iload_iload) @@ -9719,17 +7476,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #5] rsb r3, r3, #0 - ldrb ip, [jpc, #6] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #4 + ldrb ip, [jpc, #6] cmp r2, r3 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_4 + DISPATCH 7 } (iload_iload_N) @@ -9738,17 +7490,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #4] rsb r3, r3, #opc_iload_0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload,iload_1_iload,iload_2_iload,iload_3_iload) @@ -9757,35 +7504,25 @@ rsb r2, r0, #opc_iload_0_iload ldrsb r1, [jpc, #4] rsb r3, r3, #0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload_N,iload_1_iload_N,iload_2_iload_N,iload_3_iload_N) (if_icmplt) { rsb r3, r2, #opc_iload_0 + ldrsb r1, [jpc, #3] rsb r2, r0, #opc_iload_0_iload_N - ldrsb r1, [jpc, #3] + ldr r3, [locals, r3, lsl #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - blt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + blt branch_taken_unsafe_2 + DISPATCH 5 } (iload_iload) @@ -9794,17 +7531,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #5] rsb r3, r3, #0 - ldrb ip, [jpc, #6] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #4 + ldrb ip, [jpc, #6] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_4 + DISPATCH 7 } (iload_iload_N) @@ -9813,17 +7545,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #4] rsb r3, r3, #opc_iload_0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload,iload_1_iload,iload_2_iload,iload_3_iload) @@ -9832,35 +7559,25 @@ rsb r2, r0, #opc_iload_0_iload ldrsb r1, [jpc, #4] rsb r3, r3, #0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload_N,iload_1_iload_N,iload_2_iload_N,iload_3_iload_N) (if_icmpge) { rsb r3, r2, #opc_iload_0 + ldrsb r1, [jpc, #3] rsb r2, r0, #opc_iload_0_iload_N - ldrsb r1, [jpc, #3] + ldr r3, [locals, r3, lsl #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bge 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bge branch_taken_unsafe_2 + DISPATCH 5 } (iload_iload) @@ -9869,17 +7586,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #5] rsb r3, r3, #0 - ldrb ip, [jpc, #6] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #4 + ldrb ip, [jpc, #6] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_4 + DISPATCH 7 } (iload_iload_N) @@ -9888,17 +7600,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #4] rsb r3, r3, #opc_iload_0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload,iload_1_iload,iload_2_iload,iload_3_iload) @@ -9907,35 +7614,25 @@ rsb r2, r0, #opc_iload_0_iload ldrsb r1, [jpc, #4] rsb r3, r3, #0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload_N,iload_1_iload_N,iload_2_iload_N,iload_3_iload_N) (if_icmpgt) { rsb r3, r2, #opc_iload_0 + ldrsb r1, [jpc, #3] rsb r2, r0, #opc_iload_0_iload_N - ldrsb r1, [jpc, #3] + ldr r3, [locals, r3, lsl #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - bgt 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + bgt branch_taken_unsafe_2 + DISPATCH 5 } (iload_iload) @@ -9944,17 +7641,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #5] rsb r3, r3, #0 - ldrb ip, [jpc, #6] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #4 + ldrb ip, [jpc, #6] cmp r2, r3 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_4 + DISPATCH 7 } (iload_iload_N) @@ -9963,17 +7655,12 @@ rsb r2, r2, #0 ldrsb r1, [jpc, #4] rsb r3, r3, #opc_iload_0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload,iload_1_iload,iload_2_iload,iload_3_iload) @@ -9982,63 +7669,27 @@ rsb r2, r0, #opc_iload_0_iload ldrsb r1, [jpc, #4] rsb r3, r3, #0 - ldrb ip, [jpc, #5] ldr r2, [locals, r2, lsl #2] ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #3 + ldrb ip, [jpc, #5] cmp r2, r3 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE + ble branch_taken_unsafe_3 + DISPATCH 6 } (iload_0_iload_N,iload_1_iload_N,iload_2_iload_N,iload_3_iload_N) (if_icmple) { rsb r3, r2, #opc_iload_0 + ldrsb r1, [jpc, #3] rsb r2, r0, #opc_iload_0_iload_N - ldrsb r1, [jpc, #3] + ldr r3, [locals, r3, lsl #2] + ldr r2, [locals, r2, lsl #2] ldrb ip, [jpc, #4] - ldr r2, [locals, r2, lsl #2] - ldr r3, [locals, r3, lsl #2] - add jpc, jpc, #2 cmp r2, r3 - orr ip, ip, r1, lsl #8 - ble 1f - mov ip, #3 -1: - ldrb r0, [jpc, ip]! - DISPATCH_BYTECODE -} - -#ifdef HW_FP - -(dmac)(dastore) { - ldr tmp2, [stack, #28] - ldr tmp1, [stack, #32] - vldr d2, [stack, #20] - vldr d1, [stack, #12] - vldr d0, [stack, #4] - DISPATCH_START \seq_len - SW_NPC cmp tmp1, #0 - SW_NPC beq null_ptr_exception -.abortentry120: - ldr ip, [tmp1, #8] - cmp tmp2, ip - DISPATCH_NEXT - bcs array_bound_exception_jpc_1_tmp2 - DISPATCH_NEXT - add tmp2, tmp1, tmp2, lsl #3 - fmacd d2, d1, d0 - vstr d2, [tmp2, #BASE_OFFSET_LONG] - DISPATCH_NEXT - DISPATCH_NEXT - add stack, stack, #32 - DISPATCH_FINISH -} - -#endif //HW_FP + ble branch_taken_unsafe_2 + DISPATCH 5 +} + +#endif #endif // FAST_BYTECODES
--- a/ports/hotspot/src/cpu/zero/vm/cppInterpreter_arm.S Thu Jan 21 02:04:50 2010 +0000 +++ b/ports/hotspot/src/cpu/zero/vm/cppInterpreter_arm.S Thu Jan 28 16:34:49 2010 +0000 @@ -19,15 +19,21 @@ #define ARMv4 -#ifdef SHARK +#if defined(SHARK) || defined(THUMB2EE) + #define USE_COMPILER -#define DISABLE_NOTICE_SAFEPOINTS + #endif #ifdef USE_COMPILER +#ifdef SHARK #define MP_COMPILE_THRESHOLD 0x10000 // 65536 - must be a single MOV constant #define UP_COMPILE_THRESHOLD 0x30000 // 196608 - must be a single MOV constant +#else +#define MP_COMPILE_THRESHOLD 0x2700 // 10000 - must be a single MOV constant +#define UP_COMPILE_THRESHOLD 0x2700 // 10000 - must be a single MOV constant +#endif #define MAX_FG_METHOD_SIZE 500 @@ -38,6 +44,12 @@ #define DISABLE_BG_COMP_ON_NON_MP #endif +#ifdef THUMB2EE +#define FREQ_COUNT_OVERFLOW Thumb2_Compile +#else +#define FREQ_COUNT_OVERFLOW _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh +#endif + #endif // USE_COMPILER #ifndef DISABLE_NOTICE_SAFEPOINTS @@ -46,12 +58,6 @@ #ifndef DISABLE_HW_NULL_PTR_CHECK #define HW_NULL_PTR_CHECK #endif -#ifndef DISABLE_FASTPATH_ENTRY -#define FASTPATH_ENTRY -#endif -#ifndef DISABLE_NATIVE_ENTRY -#define NATIVE_ENTRY -#endif #ifndef DISABLE_FAST_BYTECODES #define FAST_BYTECODES #endif @@ -74,67 +80,25 @@ #define tmp1 r11 #define tmp2 r10 -#define tmp_invoke_len lr - -#define regset r3-r11 - -// XXX hardwired constants! -#define tos_btos 0 -#define tos_ctos 1 -#define tos_stos 2 -#define tos_itos 3 -#define tos_ltos 4 -#define tos_ftos 5 -#define tos_dtos 6 -#define tos_atos 7 +#define regset r4,r5,r6,r7,r9,r10,r11 +#define fast_regset r8 #include "offsets_arm.s" -// XXX hardwired constants! -#define RESOURCEAREA_AREA 0 -#define RESOURCEAREA_CHUNK 4 -#define RESOURCEAREA_HWM 8 -#define RESOURCEAREA_MAX 12 - -// XXX hardwired constants! -#define ISTATE_THREAD 0 -#define ISTATE_BCP 4 -#define ISTATE_LOCALS 8 -#define ISTATE_CONSTANTS 12 -#define ISTATE_METHOD 16 -#define ISTATE_MDX 20 -#define ISTATE_STACK 24 -#define ISTATE_ADVANCE_PC 28 -#define ISTATE_MSG 28 -#define ISTATE_CALLEE 32 // union frame_manager_message -#define ISTATE_PREV_LINK 44 -#define ISTATE_OOP_TEMP 48 -#define ISTATE_STACK_BASE 52 -#define ISTATE_STACK_LIMIT 56 -#define ISTATE_MONITOR_BASE 60 -#define ISTATE_SELF_LINK 64 -#define ISTATE_FRAME_TYPE 68 -#define ISTATE_NEXT_FRAME 72 -#define FRAME_SIZE 76 - -// XXX hardwired constants! -#define ENTRY_FRAME 1 -#define INTERPRETER_FRAME 2 -#define SHARK_FRAME 3 -#define FAKE_STUB_FRAME 4 - #define last_implemented_bytecode 201 +#define CODE_ALIGN_SIZE 64 + .macro ALIGN_CODE - .align 3 + .align 6 .endm .macro ALIGN_DATA - .align 3 + .align 6 .endm .macro ALIGN_OPCODE - .align 3 + .align 6 .endm .macro ALIGN_WORD @@ -276,6 +240,24 @@ .endif #endif .endm +@------------------------------------------------ +@ THUMB2 specific code macro +@ Usage: +@ T2 <thumb2 specific code> +@------------------------------------------------ + .macro T2 p1, p2, p3, p4 +#ifdef THUMB2EE + .ifnes "\p4", "" + \p1 \p2, \p3, \p4 + .else + .ifnes "\p3", "" + \p1 \p2, \p3 + .else + \p1 \p2 + .endif + .endif +#endif + .endm .macro Opcode label ALIGN_OPCODE @@ -290,6 +272,7 @@ str \reg, [stack, #(\offset+1) * 4] .endm +#define PUSH java_push .macro PUSH reg1, reg2, reg3, reg4 .ifnes "\reg4", "" stmda stack!, {\reg1, \reg2, \reg3, \reg4} @@ -306,6 +289,7 @@ .endif .endm +#define POP java_pop .macro POP reg1, reg2, reg3, reg4 .ifnes "\reg4", "" ldmib stack!, {\reg1, \reg2, \reg3, \reg4} @@ -346,227 +330,6 @@ str jpc, [istate, #ISTATE_BCP] .endm -@ ECN: I assert that istate->locals and istate->stack cannot move on a GC. -@ The reasoning is that istate itself is stored on the Java stack -@ and locals and stack are relative to istate. Therefore if locals or -@ stack were to move, istate itself would have to move and we would -@ lose our entire interpreter state. -@ To prove this I have changed the code which recaches locals and stack -@ to assert that locals == istate->locals and stack == istate->stack. -@ This saves a lot of needles recaching of interpreter state. - .macro ASSERT_LOCALS_CACHED -#if 0 - str ip, [arm_sp, #-4]! - mrs ip, cpsr - str ip, [arm_sp, #-4]! - mov ip, locals - ldr locals, [istate, #ISTATE_LOCALS] - cmp ip, locals - strne r0, [r0, -r0] - ldr ip, [arm_sp], #4 - msr cpsr, ip - ldr ip, [arm_sp], #4 -#endif - .endm - - .macro ASSERT_STACK_CACHED -#if 0 - str ip, [arm_sp, #-4]! - mrs ip, cpsr - str ip, [arm_sp, #-4]! - mov ip, stack - ldr stack, [istate, #ISTATE_STACK] - cmp ip, stack - strne r0, [r0, -r0] - ldr ip, [arm_sp], #4 - msr cpsr, ip - ldr ip, [arm_sp], #4 -#endif - .endm - -@ DISPATCH_LOOP causes the dispatch code to branch every time to a label 'dispatch_loop' -@ This is primarily for debugging so we can stick assertions at the dispatch_loop label -@ which will then be checked after every bytcode. -@ #define DISPATCH_LOOP - -@ CODETRACE tarces bytecodes in a code buffer which can be examined under gdb -@ Note: DISPATCH_LOOP must be enabled for CODETRACE to work -@ #define CODETRACE - -@ DISPATCH_ASSERTS enables various assertions in the dispatch loop, such as checking -@ stack, frame, locals and constpool are all consistent and not corrupted -@#define DISPATCH_ASSERTS - - .macro ABORTNE - strne r0, [r0, -r0] - .endm - - .macro ABORTCS - strcs r0, [r0, -r0] - .endm - - .macro ABORTCC - strcc r0, [r0, -r0] - .endm - - .macro CHECK_CONSTPOOL -#ifdef DISPATCH_ASSERTS - @ First check istate->constpool == method->constpool - ldr r1, [istate, #ISTATE_CONSTANTS] - ldr r2, [istate, #ISTATE_METHOD] - ldr r2, [r2, #METHOD_CONSTANTS] - ldr r2, [r2, #CONSTANTPOOL_CACHE] - cmp r1, r2 - ABORTNE -@ cmp r1, constpool -@ ABORTNE -#endif - .endm - - .macro CHECK_LOCALS -#ifdef DISPATCH_ASSERTS - @ Check cached locals var is the same as that in istate - ldr r1, [istate, #ISTATE_LOCALS] - cmp r1, locals - ABORTNE -#endif - .endm - - .macro CHECK_FRAME -#ifdef DISPATCH_ASSERTS - @ Check #INTERPRETER_FRAME hasn't been overwritten - ldr r1, [istate, #ISTATE_FRAME_TYPE] - cmp r1, #INTERPRETER_FRAME - ABORTNE - @ Check we are still the topmost frame - ldr r1, [istate, #ISTATE_THREAD] - ldr r1, [r1, #THREAD_TOP_ZERO_FRAME] - add r2, istate, #ISTATE_NEXT_FRAME - cmp r1, r2 - ABORTNE - @ And check the NEXT_FRAME pointer points to a valid frame - ldr r1, [istate, #ISTATE_NEXT_FRAME] - ldr r2, [r1, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - bic r2, r2, #7 @ ECN: Allow for differing frames - cmp r2, #0 - ABORTNE -#endif - .endm - - .macro CHECK_BACKTRACE -#ifdef DISPATCH_ASSERTS - add r3, istate, #ISTATE_NEXT_FRAME -@ ECN: Only check a limited no of frames back. topmost frame already checked -@ Check 2nd frame up - ldr r3, [r3] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - cmp r2, #ENTRY_FRAME - beq 2f - cmp ip, #INTERPRETER_FRAME - ABORTNE @ Must be ENTRY_FRAME, or INTERPRETER_FRAME - ldr r1, [r3, #-ISTATE_NEXT_FRAME + ISTATE_CONSTANTS] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_METHOD] - ldr r2, [r2, #12] - ldr r2, [r2, #12] - cmp r1, r2 - ABORTNE -@ Check 3rd frame up - ldr r3, [r3] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - cmp r2, #ENTRY_FRAME - beq 2f - cmp r2, #INTERPRETER_FRAME - ABORTNE @ Must be ENTRY_FRAME, or INTERPRETER_FRAME - ldr r1, [r3, #-ISTATE_NEXT_FRAME + ISTATE_CONSTANTS] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_METHOD] - ldr r2, [r2, #12] - ldr r2, [r2, #12] - cmp r1, r2 - ABORTNE -@ Check 4th frame up - ldr r3, [r3] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - cmp r2, #ENTRY_FRAME - beq 2f - cmp r2, #INTERPRETER_FRAME - ABORTNE @ Must be ENTRY_FRAME, or INTERPRETER_FRAME - ldr r1, [r3, #-ISTATE_NEXT_FRAME + ISTATE_CONSTANTS] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_METHOD] - ldr r2, [r2, #12] - ldr r2, [r2, #12] - cmp r1, r2 - ABORTNE -@ Check 5th frame up - ldr r3, [r3] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - cmp r2, #ENTRY_FRAME - beq 2f - cmp r2, #INTERPRETER_FRAME - ABORTNE @ Must be ENTRY_FRAME, or INTERPRETER_FRAME - ldr r1, [r3, #-ISTATE_NEXT_FRAME + ISTATE_CONSTANTS] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_METHOD] - ldr r2, [r2, #12] - ldr r2, [r2, #12] - cmp r1, r2 - ABORTNE -@ Check 7th frame up - ldr r3, [r3] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - cmp r2, #ENTRY_FRAME - beq 2f - cmp r2, #INTERPRETER_FRAME - ABORTNE @ Must be ENTRY_FRAME, or INTERPRETER_FRAME - ldr r1, [r3, #-ISTATE_NEXT_FRAME + ISTATE_CONSTANTS] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_METHOD] - ldr r2, [r2, #12] - ldr r2, [r2, #12] - cmp r1, r2 - ABORTNE -@ Check 8th frame up - ldr r3, [r3] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_FRAME_TYPE] - cmp r2, #ENTRY_FRAME - beq 2f - cmp r2, #INTERPRETER_FRAME - ABORTNE @ Must be ENTRY_FRAME, or INTERPRETER_FRAME - ldr r1, [r3, #-ISTATE_NEXT_FRAME + ISTATE_CONSTANTS] - ldr r2, [r3, #-ISTATE_NEXT_FRAME + ISTATE_METHOD] - ldr r2, [r2, #12] - ldr r2, [r2, #12] - cmp r1, r2 - ABORTNE -2: -#endif - .endm - - .macro CHECK_STACK -#ifdef DISPATCH_ASSERTS - ldr r1, [istate, #ISTATE_STACK_BASE] - cmp stack, r1 - ABORTCS - ldr r1, [istate, #ISTATE_STACK_LIMIT] - @ ECN: The stack can point below the stack limit in the - @ case that we have a full stack. As long as we dont actually - @ try writing to it. - add r2, stack, #4 - cmp r2, r1 - ABORTCC -#endif - .endm - -#define CODETRACE_BUFFER_SIZE (1 * 1024) - .macro TRACE_CODE -#ifdef CODETRACE - ldr r1, [dispatch, #CodeTrace_Idx-XXX] - cmp r1, #CODETRACE_BUFFER_SIZE - moveq r1, #0 - sub r2, dispatch, #XXX-CodeTrace_Buffer_Base - str jpc, [r2, r1] - add r1, r1, #4 - str r1, [dispatch, #CodeTrace_Idx-XXX] -#endif - .endm - .macro BREAK_DISPATCH ldr r1, [dispatch, #DispatchBreakPoint-XXX] cmp r1, jpc @@ -605,23 +368,6 @@ mov r0, r2 .endm -#ifdef DISPATCH_LOOP - .macro DISPATCH_NEXT - .endm - - .macro DISPATCH_FINISH - b dispatch_loop - .endm - - .macro DISPATCH_BYTECODE - b dispatch_loop - .endm - - .macro DISPATCH step=0 - ldrb r0, [jpc, #\step]! - b dispatch_loop - .endm -#else .macro DISPATCH_1 @ ldrb r1, [jpc, #2] .endm @@ -702,7 +448,6 @@ bic ip, ip, #7 ldr pc, [ip, r1, lsl #2] .endm -#endif // DISPATCH_LOOP #define FFI_TYPE_VOID 0 #define FFI_TYPE_FLOAT 2 @@ -759,105 +504,6 @@ .text -do_dispatch_break: - mov pc, lr - -#ifdef DISPATCH_LOOP -@ r0 = bytecode -@ jpc has been updated -dispatch_loop: - TRACE_CODE -dispatch_check_constpool: - CHECK_CONSTPOOL -dispatch_check_locals: - CHECK_LOCALS -dispatch_check_stack: - CHECK_STACK -dispatch_check_frame: - CHECK_FRAME -dispatch_check_backtrace: - CHECK_BACKTRACE -dispatch_break: - BREAK_DISPATCH - ldrb r1, [jpc, #2] - ldr ip, [dispatch, r0, lsl #2] - ldrb r2, [jpc, #1] - ands lr, ip, #7 - moveq pc, ip - ldrb r1, [jpc, lr] - bic ip, ip, #7 - ldr ip, [ip, r1, lsl #2] - mov pc, ip -#endif - -is_subtype_of: - ldr r2, [r1, #16] - add ip, r0, r2 - ldr ip, [ip, #-8] - cmp ip, r1 - moveq r0, #1 - bxeq lr - cmp r2, #20 - movne r0, #0 - bxne lr - b _ZNK5Klass23search_secondary_supersEP12klassOopDesc - -HandleC: - stmfd sp!, {r4, r5, r6, lr} - ldr r3, HandleC_adcons - subs r5, r1, #0 - mov r4, r0 -.HandleC_pic: - add r3, pc, r3 - streq r5, [r0, #0] - beq 2f - ldr r2, HandleC_adcons+4 - ldr r3, [r3, r2] - ldr r0, [r3, #0] - bl pthread_getspecific - ldr r3, [r0, #THREAD_HANDLE_AREA] - ldr r0, [r3, #8] - ldr r1, [r3, #12] - add r2, r0, #4 - cmp r2, r1 - strls r2, [r3, #8] - bhi 3f -1: - str r5, [r0, #0] - str r0, [r4, #0] -2: - mov r0, r4 - ldmfd sp!, {r4, r5, r6, pc} -3: - mov r0, r3 - mov r1, #4 - bl _ZN5Arena4growEj - b 1b -HandleC_adcons: - .word _GLOBAL_OFFSET_TABLE_-(.HandleC_pic+8) - .word _ZN18ThreadLocalStorage13_thread_indexE(GOT) - -HandleMarkCleanerD: - stmfd sp!, {r4, r5, r6, lr} - ldr r3, [r0, #0] - mov r6, r0 - ldr r4, [r3, #40] - ldr r0, [r4, #8] - ldr r5, [r4, #4] - ldr r3, [r0, #0] - cmp r3, #0 - beq 1f - bl _ZN5Chunk9next_chopEv - ldr r0, [r4, #8] -1: - str r0, [r5, #4] - mov r0, r6 - ldr r3, [r4, #12] - str r3, [r5, #8] - ldr r3, [r4, #16] - str r3, [r5, #12] - ldmfd sp!, {r4, r5, r6, pc} - cmpxchg_ptr: stmfd sp!, {r4, r5, r6, r7, r8, lr} mov r6, #0xffffffc0 @@ -883,126 +529,6 @@ mov r0, r8 ldmfd sp!, {r4, r5, r6, r7, r8, pc} -ThreadInVMfromJavaD: - stmfd sp!, {r4, r5, r6, lr} - ldr r5, ThreadInVMfromJavaD_adcons - ldr r3, ThreadInVMfromJavaD_adcons+4 - mov r2, #_thread_in_vm_trans -.ThreadInVMfromJavaD_pic: - add r5, pc, r5 - ldr r6, [r0, #0] - mov r4, r0 - ldr r3, [r5, r3] - str r2, [r6, #THREAD_STATE] - ldr r3, [r3, #0] - cmp r3, #1 - ble 1f - ldr r3, ThreadInVMfromJavaD_adcons+8 - ldr r3, [r5, r3] - ldrb r3, [r3, #0] @ zero_extendqisi2 - cmp r3, #0 - bne 6f - ldr r3, ThreadInVMfromJavaD_adcons+12 - mov r1, #1 - ldr r2, ThreadInVMfromJavaD_adcons+16 - ldr r3, [r5, r3] - ldr r2, [r5, r2] - ldr r3, [r3, #0] - ldr r2, [r2, #0] - and r3, r3, r6, lsr #3 - str r1, [r2, r3] -1: - ldr r3, ThreadInVMfromJavaD_adcons+20 - ldr r3, [r5, r3] - ldr r3, [r3, #0] - cmp r3, #0 - bne 5f -2: - mov r3, #8 - str r3, [r6, #THREAD_STATE] - ldr r0, [r4, #0] - ldr r3, [r0, #THREAD_SPECIALRUNTIMEEXITCONDITION] - cmp r3, #0 - bne 3f - ldr r3, [r0, #THREAD_SUSPEND_FLAGS] - tst r3, #_thread_external_suspend - beq 4f -3: - mov r1, #1 - bl _ZN10JavaThread37handle_special_runtime_exit_conditionEb - mov r0, r4 - ldmfd sp!, {r4, r5, r6, pc} -4: - ldr r3, [r0, #THREAD_SUSPEND_FLAGS] - tst r3, #_thread_deopt_suspend - bne 3b - mov r0, r4 - ldmfd sp!, {r4, r5, r6, pc} -5: - mov r0, r6 - bl _ZN20SafepointSynchronize5blockEP10JavaThread - b 2b -6: - mov r3, #0xffffffa0 - bic r3, r3, #0xf000 - blx r3 - b 1b -ThreadInVMfromJavaD_adcons: - .word _GLOBAL_OFFSET_TABLE_-(.ThreadInVMfromJavaD_pic+8) - .word _ZN2os16_processor_countE(GOT) - .word UseMembar(GOT) - .word _ZN2os20_serialize_page_maskE(GOT) - .word _ZN2os19_mem_serialize_pageE(GOT) - .word _ZN20SafepointSynchronize6_stateE(GOT) - -#define oop_address_tmp tmp1 -#define oop_value_tmp tmp2 -#define oop_lr locals - - ALIGN_CODE -oop_store: - mov oop_lr, lr -@ mov oop_address_tmp, r0 -@ mov oop_value_tmp, r1 - ldr r3, [dispatch, #oopDesc_Address-XXX] - ldr r3, [r3, #0] - ldr r2, [r3, #8] - cmp r2, #1 - beq 1f - mov r0, r3 - mov r1, oop_address_tmp - ldr r3, [r3, #0] - mov r2, oop_value_tmp - mov lr, pc - ldr pc, [r3, #48] -1: - ldr r3, [dispatch, #always_do_update_barrier_Address-XXX] - ldrb r3, [r3] - cmp r3, #0 - beq 2f - mov r3, #0xffffffa0 - bic r3, r3, #0xf000 - blx r3 -2: - mov lr, oop_lr - CACHE_LOCALS - ldr r3, [dispatch, #oopDesc_Address-XXX] - str oop_value_tmp, [oop_address_tmp, #0] - ldr r3, [r3, #0] - ldr r2, [r3, #8] - cmp r2, #1 - beq 3f - mov r0, r3 - mov r1, oop_address_tmp - mov r2, oop_value_tmp - ldr r3, [r3, #0] - ldr pc, [r3, #52] -3: - ldr r3, [r3, #76] - mov r2, #0 - strb r2, [r3, oop_address_tmp, lsr #9] - mov pc, lr - build_frame: mov r3, r0 ldr r0, [r1, #METHOD_ACCESSFLAGS] @@ -1093,13 +619,6 @@ add r1, r1, ip add r1, r1, r2 @ r1->dispatch -#ifndef USE_COMPILER - ldr r2, [r1, #UseCompiler_Address-XXX] - ldrb r2, [r2] - cmp r2, #0 - bne 1f -#endif - ldr r2, [r1, #can_post_interpreter_events-XXX] ldrb r2, [r2] cmp r2, #0 @@ -1119,26 +638,33 @@ asm_method_table: .word normal_entry .word normal_entry_synchronized -#ifdef NATIVE_ENTRY .word native_entry -#else - .word 0 -#endif - .word 0 @ cppInterpreter can handle native_entry_synchronized + .word native_entry_synchronized .word empty_entry .word accessor_entry - .word normal_entry - .word normal_entry - .word normal_entry - .word normal_entry - .word normal_entry - .word normal_entry - .word normal_entry - .word normal_entry + .word normal_entry @ abstract entry + .word normal_entry @ java_lang_math_sin + .word normal_entry @ java_lang_math_cos + .word normal_entry @ java_lang_math_tan + .word normal_entry @ java_lang_math_abs + .word normal_entry @ java_lang_math_sqrt + .word normal_entry @ java_lang_math_log + .word normal_entry @ java_lang_math_log10 ALIGN_CODE - .global empty_entry +native_entry_synchronized: + b fast_native_entry_synchronized + + ALIGN_CODE +fast_native_entry_synchronized: + b _ZN14CppInterpreter12native_entryEP13methodOopDesciP6Thread + + ALIGN_CODE empty_entry: + b fast_empty_entry + + ALIGN_CODE +fast_empty_entry: ldr r3, .L1359 ldr r1, .L1359+4 .LPIC19: @@ -1160,22 +686,22 @@ @ ---- START execute.s --------------------------------------------------------------------- + .global asm_check_null_ptr +asm_check_null_ptr: + #ifdef HW_NULL_PTR_CHECK #define uc_mcontext 20 #define arm_registers_offset 12 #define arm_cpsr_offset 16*4 - .global asm_check_null_ptr -asm_check_null_ptr: add r0, r0, #uc_mcontext + arm_registers_offset ldr r1, [r0, #15*4] adr ip, abort_table abort_loop: ldr r2, [ip], #8 cmp r2, #0 - moveq r0, #0 - bxeq lr + beq 2f cmp r2, r1 bne abort_loop @@ -1193,6 +719,16 @@ do_setcontext: mov r0, #1 bx lr +#endif // HW_NULL_PTR_CHECK +2: +#ifdef THUMB2EE + b Thumb2_Check_Null +#else + mov r0, #0 + bx lr +#endif + +#ifdef HW_NULL_PTR_CHECK abort_table: .word .abortentry5, 1 .word .abortentry6, 1 @@ -1240,19 +776,6 @@ FBC .word .abortentry59, 2 FBC .word .abortentry60, 2 - NSP FBC .word .abortentry61, 0 - NSP FBC .word .abortentry62, 0 - NSP FBC .word .abortentry63, 0 - NSP FBC .word .abortentry64, 0 - NSP FBC .word .abortentry65, 0 - NSP FBC .word .abortentry66, 0 - NSP FBC .word .abortentry67, 0 - NSP FBC .word .abortentry68, 0 - NSP FBC .word .abortentry69, 0 - NSP FBC .word .abortentry70, 0 - NSP FBC .word .abortentry71, 0 - NSP FBC .word .abortentry72, 0 - FBC .word .abortentry73, 1 FBC .word .abortentry74, 1 FBC .word .abortentry75, 1 @@ -1274,18 +797,6 @@ FBC .word .abortentry89, 5 FBC .word .abortentry90, 4 FBC .word .abortentry91, 4 - NSP FBC .word .abortentry92, 3 - NSP FBC .word .abortentry93, 3 - NSP FBC .word .abortentry94, 3 - NSP FBC .word .abortentry95, 3 - NSP FBC .word .abortentry96, 3 - NSP FBC .word .abortentry97, 3 - NSP FBC .word .abortentry98, 3 - NSP FBC .word .abortentry99, 3 - NSP FBC .word .abortentry100, 3 - NSP FBC .word .abortentry101, 3 - NSP FBC .word .abortentry102, 3 - NSP FBC .word .abortentry103, 3 FBC .word .abortentry104, 0 FBC .word .abortentry105, 1 FBC .word .abortentry106, 1 @@ -1299,28 +810,27 @@ FBC .word .abortentry113, 0 .word .abortentry114, 1 - .word .abortentry115, 0 - .word .abortentry116, abstractmethod_exception FBC .word .abortentry117, 0 .word .abortentry118, 0 - .word .abortentry119, return_throw_illegal_monitor_state - FBC .word .abortentry120, 0 .word 0 -#else - .global asm_check_null_ptr -asm_check_null_ptr: - mov r0, #0 - bx lr - #endif -#ifdef NATIVE_ENTRY + + ALIGN_CODE +native_entry: + stmfd arm_sp!, {regset, lr} + bl fast_native_entry + ldmia sp!, {regset, pc} + ALIGN_CODE fast_native_entry: - mov r2, tmp1 - mov r11, tmp2 -fast_native_entry_with_args: + adrl ip, dispatch_init_adcon + mov r11, r0 + ldm ip, {dispatch, r7} + stmdb sp!, {fast_regset, lr} + add dispatch, dispatch, ip + add dispatch, dispatch, r7 ldrh r1, [r11, #METHOD_SIZEOFPARAMETERS] ldr r4, [r2, #THREAD_JAVA_SP] ldr r3, [r2, #THREAD_TOP_ZERO_FRAME] @@ -1477,24 +987,6 @@ ldr ip, [r11, #METHOD_NATIVEHANDLER] ldrh r11, [r11, #METHOD_SIZEOFPARAMETERS] -#ifdef CODETRACE - ldr r1, [dispatch, #CodeTrace_Idx-XXX] - cmp r1, #CODETRACE_BUFFER_SIZE - moveq r1, #0 - sub r2, dispatch, #XXX-CodeTrace_Buffer_Base - mov r3, #0x4e << 24 @ 'NATV' -> r3 - orr r3, r3, #0x4a << 16 - orr r3, r3, #0x54 << 8 - orr r3, r3, #0x56 - str r3, [r2, r1] - add r1, r1, #4 - cmp r1, #CODETRACE_BUFFER_SIZE - moveq r1, #0 - str ip, [r2, r1] - add r1, r1, #4 - str r1, [dispatch, #CodeTrace_Idx-XXX] -#endif - ldmia arm_sp!, {r0, r1, r2, r3} blx ip @@ -1557,50 +1049,40 @@ str lr, [r9, #THREAD_TOP_ZERO_FRAME] str tmp1, [ip, #JNIHANDLEBLOCK_TOP] str r1, [r5, #4] - cmp istate, #0 str r5, [r9, #THREAD_JAVA_SP] - bne .fast_native_return - ldmfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} + ldmfd arm_sp!, {fast_regset, pc} .fast_native_return_byte: mov r0, r0, lsl #24 str lr, [r9, #THREAD_TOP_ZERO_FRAME] mov r0, r0, asr #24 str tmp1, [ip, #JNIHANDLEBLOCK_TOP] str r0, [r5, #-4]! - cmp istate, #0 str r5, [r9, #THREAD_JAVA_SP] - bne .fast_native_return - ldmfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} + ldmfd arm_sp!, {fast_regset, pc} .fast_native_return_char: mov r0, r0, lsl #16 str lr, [r9, #THREAD_TOP_ZERO_FRAME] mov r0, r0, lsr #16 str tmp1, [ip, #JNIHANDLEBLOCK_TOP] str r0, [r5, #-4]! - cmp istate, #0 str r5, [r9, #THREAD_JAVA_SP] - bne .fast_native_return - ldmfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} + ldmfd arm_sp!, {fast_regset, pc} .fast_native_return_bool: ands r0, r0, #255 str lr, [r9, #THREAD_TOP_ZERO_FRAME] movne r0, #1 str tmp1, [ip, #JNIHANDLEBLOCK_TOP] str r0, [r5, #-4]! - cmp istate, #0 str r5, [r9, #THREAD_JAVA_SP] - bne .fast_native_return - ldmfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} + ldmfd arm_sp!, {fast_regset, pc} .fast_native_return_obj: cmp r0, #0 ldrne r0, [r0] str r0, [r5, #-4]! str lr, [r9, #THREAD_TOP_ZERO_FRAME] str tmp1, [ip, #JNIHANDLEBLOCK_TOP] - cmp istate, #0 str r5, [r9, #THREAD_JAVA_SP] - bne .fast_native_return - ldmfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} + ldmfd arm_sp!, {fast_regset, pc} .fast_native_return_short: mov r0, r0, lsl #16 mov r0, r0, asr #16 @@ -1610,32 +1092,8 @@ str lr, [r9, #THREAD_TOP_ZERO_FRAME] str tmp1, [ip, #JNIHANDLEBLOCK_TOP] .fast_native_exit: - cmp istate, #0 str r5, [r9, #THREAD_JAVA_SP] - ldmeqfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, pc} -.fast_native_return: - ldr r2, [istate, #ISTATE_STACK_LIMIT] - sub r5, r5, #4 - str r5, [istate, #ISTATE_STACK] - - ldr r1, [r9, #THREAD_TOP_ZERO_FRAME] - add r2, r2, #4 - str r2, [r9, #THREAD_JAVA_SP] - str r1, [r9, #THREAD_LAST_JAVA_SP] - ldr r0, [istate, #ISTATE_THREAD] - CACHE_STACK - CACHE_JPC - ldr r3, [r0, #THREAD_PENDING_EXC] - DISPATCH_START 3 - DISPATCH_NEXT - CACHE_CP - DISPATCH_NEXT - cmp r3, #0 - DISPATCH_NEXT - bne invokenative_exception - DISPATCH_NEXT - CACHE_LOCALS - DISPATCH_FINISH + ldmfd arm_sp!, {fast_regset, pc} .fast_native_entry_throw_stack_overflow: str r0, [r9, #THREAD_LAST_JAVA_SP] @@ -1659,958 +1117,46 @@ bl _ZN10JavaThread40check_special_condition_for_native_transEPS_ ldmia arm_sp!, {r0, r1} b .fast_native_entry_do_return -#endif // NATIVE_ENTRY #include "bytecodes_arm.s" Opcode idiv - POP tmp2, tmp1 - DISPATCH_START 1 -int_div: - cmp tmp2, #0x20 - DISPATCH_NEXT - adr r3, .div_table - DISPATCH_NEXT - ldrcc pc, [r3, tmp2, lsl #2] - - ands a4, tmp2, #0x80000000 - rsbmi tmp2, tmp2, #0 - eors lr, a4, tmp1, ASR #32 - rsbcs tmp1, tmp1, #0 - movs a3, tmp2 -.s_loop: - cmp a3, tmp1, LSR #8 - movls a3, a3, LSL #8 - blo .s_loop - cmp a3, tmp1, LSR #1 - bhi .s_jump7 - cmp a3, tmp1, LSR #2 - bhi .s_jump6 - cmp a3, tmp1, LSR #3 - bhi .s_jump5 - cmp a3, tmp1, LSR #4 - bhi .s_jump4 - cmp a3, tmp1, LSR #5 - bhi .s_jump3 - cmp a3, tmp1, LSR #6 - bhi .s_jump2 - cmp a3, tmp1, LSR #7 - bhi .s_jump1 -.s_loop2: -@ not executed when falling into .s_loop2 - movhi a3, a3, LSR #8 - cmp tmp1, a3, LSL #7 - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #7 - cmp tmp1, a3, LSL #6 -.s_jump1: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #6 - cmp tmp1, a3, LSL #5 -.s_jump2: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #5 - cmp tmp1, a3, LSL #4 -.s_jump3: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #4 - cmp tmp1, a3, LSL #3 -.s_jump4: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #3 - cmp tmp1, a3, LSL #2 -.s_jump5: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #2 - cmp tmp1, a3, LSL #1 -.s_jump6: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #1 -.s_jump7: - cmp tmp1, a3 - adc a4, a4, a4 - subcs tmp1, tmp1, a3 - cmp a3, tmp2 - bne .s_loop2 - movs lr, lr, lsl #1 - rsbcs a4, a4, #0 - DISPATCH_NEXT - DISPATCH_NEXT - PUSH a4 - DISPATCH_FINISH - -.div_table: - .word div_zero_jpc_1 - .word .divc_1 - .word .divc_2 - .word .divc_3 - .word .divc_4 - .word .divc_5 - .word .divc_6 - .word .divc_7 - .word .divc_8 - .word .divc_9 - .word .divc_10 - .word .divc_11 - .word .divc_12 - .word .divc_13 - .word .divc_14 - .word .divc_15 - .word .divc_16 - .word .divc_17 - .word .divc_18 - .word .divc_19 - .word .divc_20 - .word .divc_21 - .word .divc_22 - .word .divc_23 - .word .divc_24 - .word .divc_25 - .word .divc_26 - .word .divc_27 - .word .divc_28 - .word .divc_29 - .word .divc_30 - .word .divc_31 - -.divc_1: - DISPATCH_STATE 3 - DISPATCH_NEXT - DISPATCH_NEXT - PUSH tmp1 - DISPATCH_FINISH -.divc_2: - DISPATCH_STATE 3 - DISPATCH_NEXT - add tmp1, tmp1, tmp1, lsr #31 - mov tmp2, tmp1, asr #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_3: - DISPATCH_STATE 3 - ldr tmp2, .dc_3 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - sub tmp2, a4, tmp1, asr #31 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_4: - DISPATCH_STATE 3 - movs a4, tmp1 - DISPATCH_NEXT - addmi a4, a4, #3 - mov tmp2, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_5: - DISPATCH_STATE 3 - ldr tmp2, .dc_5 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_6: - DISPATCH_STATE 3 - ldr tmp2, .dc_6 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - sub tmp2, a4, tmp1, asr #31 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_7: - DISPATCH_STATE 3 - ldr tmp2, .dc_7 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_8: - DISPATCH_STATE 3 - movs lr, tmp1 - DISPATCH_NEXT - addmi lr, lr, #7 - mov tmp2, lr, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_9: - DISPATCH_STATE 3 - ldr tmp2, .dc_9 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_10: - DISPATCH_STATE 3 - ldr tmp2, .dc_10 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_11: - DISPATCH_STATE 3 - ldr tmp2, .dc_11 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_12: - DISPATCH_STATE 3 - ldr tmp2, .dc_12 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_13: - DISPATCH_STATE 3 - ldr tmp2, .dc_13 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_14: - DISPATCH_STATE 3 - ldr tmp2, .dc_14 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_15: - DISPATCH_STATE 3 - ldr tmp2, .dc_15 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_16: - DISPATCH_STATE 3 - movs lr, tmp1 - DISPATCH_NEXT - addmi lr, lr, #15 - mov tmp2, lr, asr #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_17: - DISPATCH_STATE 3 - ldr tmp2, .dc_17 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_18: - DISPATCH_STATE 3 - ldr tmp2, .dc_18 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_19: - DISPATCH_STATE 3 - ldr tmp2, .dc_19 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_20: - DISPATCH_STATE 3 - ldr tmp2, .dc_20 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_21: - DISPATCH_STATE 3 - ldr tmp2, .dc_21 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_22: - DISPATCH_STATE 3 - ldr tmp2, .dc_22 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_23: - DISPATCH_STATE 3 - ldr tmp2, .dc_23 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_24: - DISPATCH_STATE 3 - ldr tmp2, .dc_24 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_25: - DISPATCH_STATE 3 - ldr tmp2, .dc_25 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_26: - DISPATCH_STATE 3 - ldr tmp2, .dc_26 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_27: - DISPATCH_STATE 3 - ldr tmp2, .dc_27 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_28: - DISPATCH_STATE 3 - ldr tmp2, .dc_28 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_29: - DISPATCH_STATE 3 - ldr tmp2, .dc_29 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_30: - DISPATCH_STATE 3 - ldr tmp2, .dc_30 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.divc_31: - DISPATCH_STATE 3 - ldr tmp2, .dc_31 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.dc_7: -.dc_14: - .word 0x92492493 -.dc_15: -.dc_30: - .word 0x88888889 -.dc_23: - .word 0xb21642c9 -.dc_28: - .word 0x92492493 -.dc_29: - .word 0x8d3dcb09 -.dc_31: - .word 0x84210843 -.dc_6: -.dc_12: -.dc_24: - .word 0x2aaaaaab -.dc_19: - .word 0x6bca1af3 -.dc_5: -.dc_10: -.dc_20: - .word 0x66666667 -.dc_21: - .word 0x30c30c31 -.dc_11: -.dc_22: - .word 0x2e8ba2e9 -.dc_26: -.dc_13: - .word 0x4ec4ec4f -.dc_25: - .word 0x51eb851f -.dc_27: - .word 0x4bda12f7 -.dc_3: - .word 0x55555556 -.dc_17: - .word 0x78787879 -.dc_9: -.dc_18: - .word 0x38e38e39 - + POP r1 + POP r0 + cmp r1, #0 + beq divide_by_zero_exception + bl __aeabi_idiv + PUSH r0 + DISPATCH 1 + + Opcode idiv_clz + + POP r1 + POP r0 + bl int_div +idiv_clz_ret: + PUSH r0 + DISPATCH 1 Opcode irem - POP tmp2, tmp1 - DISPATCH_START 1 -int_rem: - cmp tmp2, #0x20 - DISPATCH_NEXT - adr r3, .rem_table - DISPATCH_NEXT - ldrcc pc, [r3, tmp2, lsl #2] - - ands a4, tmp2, #0x80000000 - rsbmi tmp2, tmp2, #0 - eors lr, a4, tmp1, ASR #32 - rsbcs tmp1, tmp1, #0 - movs a3, tmp2 -.r_loop: - cmp a3, tmp1, LSR #8 - movls a3, a3, LSL #8 - blo .r_loop - cmp a3, tmp1, LSR #1 - bhi .r_jump7 - cmp a3, tmp1, LSR #2 - bhi .r_jump6 - cmp a3, tmp1, LSR #3 - bhi .r_jump5 - cmp a3, tmp1, LSR #4 - bhi .r_jump4 - cmp a3, tmp1, LSR #5 - bhi .r_jump3 - cmp a3, tmp1, LSR #6 - bhi .r_jump2 - cmp a3, tmp1, LSR #7 - bhi .r_jump1 -.r_loop2: -@ not executed when falling into .r_loop2 - movhi a3, a3, LSR #8 - cmp tmp1, a3, LSL #7 - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #7 - cmp tmp1, a3, LSL #6 -.r_jump1: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #6 - cmp tmp1, a3, LSL #5 -.r_jump2: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #5 - cmp tmp1, a3, LSL #4 -.r_jump3: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #4 - cmp tmp1, a3, LSL #3 -.r_jump4: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #3 - cmp tmp1, a3, LSL #2 -.r_jump5: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #2 - cmp tmp1, a3, LSL #1 -.r_jump6: - adc a4, a4, a4 - subcs tmp1, tmp1, a3, LSL #1 -.r_jump7: - cmp tmp1, a3 - adc a4, a4, a4 - subcs tmp1, tmp1, a3 - cmp a3, tmp2 - bne .r_loop2 - movs lr, lr, lsl #1 - DISPATCH_NEXT - rsbmi tmp1, tmp1, #0 - DISPATCH_NEXT - PUSH tmp1 - DISPATCH_FINISH - -.rem_table: - .word div_zero_jpc_1 - .word .remc_1 - .word .remc_2 - .word .remc_3 - .word .remc_4 - .word .remc_5 - .word .remc_6 - .word .remc_7 - .word .remc_8 - .word .remc_9 - .word .remc_10 - .word .remc_11 - .word .remc_12 - .word .remc_13 - .word .remc_14 - .word .remc_15 - .word .remc_16 - .word .remc_17 - .word .remc_18 - .word .remc_19 - .word .remc_20 - .word .remc_21 - .word .remc_22 - .word .remc_23 - .word .remc_24 - .word .remc_25 - .word .remc_26 - .word .remc_27 - .word .remc_28 - .word .remc_29 - .word .remc_30 - .word .remc_31 - -.remc_1: - DISPATCH_STATE 3 - DISPATCH_NEXT - mov tmp2, #0 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_2: - DISPATCH_STATE 3 - add lr, tmp1, tmp1, lsr #31 - mov tmp2, lr, asr #1 - DISPATCH_NEXT - sub tmp2, tmp1, tmp2, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_3: - DISPATCH_STATE 3 - ldr tmp2, .dc_3 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - sub tmp2, a4, tmp1, asr #31 - add lr, tmp2, tmp2, lsl #1 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_4: - DISPATCH_STATE 3 - movs lr, tmp1 - DISPATCH_NEXT - addmi lr, lr, #3 - mov tmp2, lr, asr #2 - sub tmp2, tmp1, tmp2, lsl #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_5: - DISPATCH_STATE 3 - ldr tmp2, .dc_5 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - add lr, tmp2, tmp2, lsl #2 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_6: - DISPATCH_STATE 3 - ldr tmp2, .dc_6 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - sub tmp2, a4, tmp1, asr #31 - add lr, tmp2, tmp2, lsl #1 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_7: - DISPATCH_STATE 3 - ldr tmp2, .dc_7 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #2 - rsb lr, tmp2, tmp2, lsl #3 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_8: - DISPATCH_STATE 3 - movs lr, tmp1 - DISPATCH_NEXT - addmi lr, lr, #7 - mov tmp2, lr, asr #3 - sub tmp2, tmp1, tmp2, lsl #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_9: - DISPATCH_STATE 3 - ldr tmp2, .dc_9 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - add lr, tmp2, tmp2, lsl #3 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_10: - DISPATCH_STATE 3 - ldr tmp2, .dc_10 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - add lr, tmp2, tmp2, lsl #2 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_11: - DISPATCH_STATE 3 - ldr tmp2, .dc_11 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - add lr, tmp2, tmp2, lsl #2 - add lr, tmp2, lr, lsl #1 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_12: - DISPATCH_STATE 3 - ldr tmp2, .dc_12 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #1 - add lr, tmp2, tmp2, lsl #1 - sub tmp2, tmp1, lr, lsl #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_13: - DISPATCH_STATE 3 - ldr tmp2, .dc_13 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - add lr, tmp2, tmp2, lsl #1 - add lr, tmp2, lr, lsl #2 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_14: - DISPATCH_STATE 3 - ldr tmp2, .dc_14 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #3 - rsb lr, tmp2, tmp2, lsl #3 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_15: - DISPATCH_STATE 3 - ldr tmp2, .dc_15 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #3 - rsb lr, tmp2, tmp2, lsl #4 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_16: - DISPATCH_STATE 3 - movs lr, tmp1 - DISPATCH_NEXT - addmi lr, lr, #15 - mov tmp2, lr, asr #4 - sub tmp2, tmp1, tmp2, lsl #4 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_17: - DISPATCH_STATE 3 - ldr tmp2, .dc_17 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - add lr, tmp2, tmp2, lsl #4 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_18: - DISPATCH_STATE 3 - ldr tmp2, .dc_18 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - add lr, tmp2, tmp2, lsl #3 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_19: - DISPATCH_STATE 3 - ldr tmp2, .dc_19 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - add lr, tmp2, tmp2, lsl #3 - add lr, tmp2, lr, lsl #1 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_20: - DISPATCH_STATE 3 - ldr tmp2, .dc_20 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - add lr, tmp2, tmp2, lsl #2 - sub tmp2, tmp1, lr, lsl #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_21: - DISPATCH_STATE 3 - ldr tmp2, .dc_21 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - add lr, tmp2, tmp2, lsl #1 - rsb lr, lr, lr, lsl #3 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_22: - DISPATCH_STATE 3 - ldr tmp2, .dc_22 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - add lr, tmp2, tmp2, lsl #2 - add lr, tmp2, lr, lsl #1 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_23: - DISPATCH_STATE 3 - ldr tmp2, .dc_23 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - add lr, tmp2, tmp2, lsl #1 - rsb lr, tmp2, lr, lsl #3 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_24: - DISPATCH_STATE 3 - ldr tmp2, .dc_24 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #2 - add lr, tmp2, tmp2, lsl #1 - sub tmp2, tmp1, lr, lsl #3 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_25: - DISPATCH_STATE 3 - ldr tmp2, .dc_25 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - add lr, tmp2, tmp2, lsl #2 - add lr, lr, lr, lsl #2 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_26: - DISPATCH_STATE 3 - ldr tmp2, .dc_26 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - add lr, tmp2, tmp2, lsl #1 - add lr, tmp2, lr, lsl #2 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_27: - DISPATCH_STATE 3 - ldr tmp2, .dc_27 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov lr, tmp1, asr #31 - rsb tmp2, lr, a4, asr #3 - add lr, tmp2, tmp2, lsl #1 - add lr, lr, lr, lsl #3 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_28: - DISPATCH_STATE 3 - ldr tmp2, .dc_28 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - rsb lr, tmp2, tmp2, lsl #3 - sub tmp2, tmp1, lr, lsl #2 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_29: - DISPATCH_STATE 3 - ldr tmp2, .dc_29 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - rsb lr, tmp2, tmp2, lsl #3 - add lr, tmp2, lr, lsl #2 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_30: - DISPATCH_STATE 3 - ldr tmp2, .dc_30 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - rsb lr, tmp2, tmp2, lsl #4 - sub tmp2, tmp1, lr, lsl #1 - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH -.remc_31: - DISPATCH_STATE 3 - ldr tmp2, .dc_31 - DISPATCH_NEXT - smull lr, a4, tmp1, tmp2 - mov tmp2, tmp1, asr #31 - add lr, tmp1, a4 - rsb tmp2, tmp2, lr, asr #4 - rsb lr, tmp2, tmp2, lsl #5 - sub tmp2, tmp1, lr - DISPATCH_NEXT - PUSH tmp2 - DISPATCH_FINISH + POP r1 + POP r0 + cmp r1, #0 + beq divide_by_zero_exception + bl __aeabi_idivmod + PUSH r1 + DISPATCH 1 + + Opcode irem_clz + + POP r1 + POP r0 + bl int_rem +irem_clz_ret: + PUSH r0 + DISPATCH 1 Opcode goto ldrsb r1, [jpc, #1] @@ -2622,6 +1168,46 @@ ble do_backedge DISPATCH_FINISH +branch_taken_unsafe: + mov r2, r2, lsl #24 + orr tmp1, r1, r2, asr #16 + DISPATCH_START_REG tmp1 + USEC cmp tmp1, #0 + USEC ble do_backedge + DISPATCH_FINISH + +branch_taken_unsafe_1: + add jpc, jpc, #1 + orr tmp1, ip, r1, lsl #8 + DISPATCH_START_REG tmp1 + USEC cmp tmp1, #0 + USEC ble do_backedge + DISPATCH_FINISH + +branch_taken_unsafe_2: + add jpc, jpc, #2 + orr tmp1, ip, r1, lsl #8 + DISPATCH_START_REG tmp1 + USEC cmp tmp1, #0 + USEC ble do_backedge + DISPATCH_FINISH + +branch_taken_unsafe_3: + add jpc, jpc, #3 + orr tmp1, ip, r1, lsl #8 + DISPATCH_START_REG tmp1 + USEC cmp tmp1, #0 + USEC ble do_backedge + DISPATCH_FINISH + +branch_taken_unsafe_4: + add jpc, jpc, #4 + orr tmp1, ip, r1, lsl #8 + DISPATCH_START_REG tmp1 + USEC cmp tmp1, #0 + USEC ble do_backedge + DISPATCH_FINISH + do_backedge: USEC ldr tmp2, [istate, #ISTATE_METHOD] OSR ldr lr, [dispatch, #InterpreterInvocationLimit_Address-XXX] @@ -2631,7 +1217,11 @@ OSR ldr lr, [lr] USEC add ip, ip, #INVOCATIONCOUNTER_COUNTINCREMENT USEC str r1, [tmp2, #METHOD_BACKEDGECOUNTER] +#ifdef THUMB2EE + OSR cmp r1, lr +#else OSR cmp r1, lr, lsl #2 +#endif USEC str ip, [tmp2, #METHOD_INVOCATIONCOUNTER] OSR bcs do_osr @@ -2645,23 +1235,37 @@ do_synchronize: - add r0, istate, #ISTATE_THREAD - bl HandleMarkCleanerD - ldr r0, [istate, #ISTATE_THREAD] DECACHE_JPC DECACHE_STACK - bl _ZN20SafepointSynchronize5blockEP10JavaThread - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] + bl Helper_SafePoint CACHE_CP - ldr r3, [r0, #THREAD_PENDING_EXC] CACHE_JPC - cmp r3, #0 + cmp r0, #0 bne handle_exception DISPATCH 0 #ifdef ON_STACK_REPLACEMENT + +#ifdef THUMB2EE +do_osr: + ldr r3, [tmp2, #METHOD_CONSTMETHOD] + DECACHE_JPC + DECACHE_STACK + ldr r0, [istate, #ISTATE_THREAD] + sub r1, jpc, r3 + sub r1, r1, #CONSTMETHOD_CODEOFFSET + bl FREQ_COUNT_OVERFLOW +1: + cmp r0, #0 + bne call_thumb2 + CACHE_CP + CACHE_JPC + DISPATCH_START 0 + b osr_continue + +#else + do_osr: ldr ip, [dispatch, #UseOnStackReplacement_Address-XXX] ldrb ip, [ip] @@ -2680,15 +1284,13 @@ mov r3, #1 ldr r5, [tmp2] str r3, [tmp2] - bl _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh + bl FREQ_COUNT_OVERFLOW str r5, [tmp2] b 2f 1: - bl _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh + bl FREQ_COUNT_OVERFLOW 2: ldr r3, [istate, #ISTATE_THREAD] - ASSERT_LOCALS_CACHED - ASSERT_STACK_CACHED CACHE_CP ldr r1, [r3, #THREAD_PENDING_EXC] CACHE_JPC @@ -2702,13 +1304,9 @@ 1: DISPATCH_START 0 b osr_continue -#endif - -#ifdef ON_STACK_REPLACEMENT + osr_migrate: ldr tmp1, [r0, #128] @ osr_method->osr_entry() - ldr tmp2, [istate, #ISTATE_ADVANCE_PC] -@ ldr istate, [istate, #ISTATE_NEXT_FRAME] mov r0, r3 bl _ZN13SharedRuntime19OSR_migration_beginEP10JavaThread mov r1, r0 @@ -2730,32 +1328,11 @@ mov lr, pc ldr pc, [tmp1] - cmp tmp2, #0 - ldmeqfd arm_sp!, {regset, pc} - - ldr istate, [istate, #ISTATE_NEXT_FRAME] - ldr lr, [istate, #-ISTATE_NEXT_FRAME+ISTATE_THREAD]! - CACHE_JPC - ldr stack, [lr, #THREAD_JAVA_SP] - ldr r2, [istate, #ISTATE_STACK_LIMIT] - sub stack, stack, #4 - - ldr r1, [lr, #THREAD_TOP_ZERO_FRAME] - add r2, r2, #4 - str r2, [lr, #THREAD_JAVA_SP] - str r1, [lr, #THREAD_LAST_JAVA_SP] - ldr r3, [lr, #THREAD_PENDING_EXC] - DISPATCH_START_REG tmp2 - CACHE_LOCALS - DISPATCH_NEXT - DISPATCH_NEXT - cmp r3, #0 - DISPATCH_NEXT - bne return_exception - DISPATCH_NEXT - CACHE_CP - DISPATCH_FINISH -#endif + ldmfd arm_sp!, {fast_regset, pc} + +#endif // THUMB2EE + +#endif // ON_STACK_REPLACEMENT Opcode ifeq Opcode ifnull @@ -2867,18 +1444,12 @@ ldr r1, [r3] cmp r1, #1 bne handle_return - add r0, istate, #ISTATE_THREAD - bl HandleMarkCleanerD - ldr r0, [istate, #ISTATE_THREAD] DECACHE_JPC DECACHE_STACK - bl _ZN20SafepointSynchronize5blockEP10JavaThread ldr r0, [istate, #ISTATE_THREAD] - ASSERT_STACK_CACHED - ldr r3, [r0, #THREAD_PENDING_EXC] + bl Helper_SafePoint CACHE_JPC -@ CACHE_LOCALS & CACHE_CP not require for handle_retuen / handle_exception - cmp r3, #0 + cmp r0, #0 beq handle_return b handle_exception @@ -2889,8 +1460,6 @@ DECACHE_JPC DECACHE_STACK bl _ZN18InterpreterRuntime15resolve_get_putEP10JavaThreadN9Bytecodes4CodeE - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r3, [r0, #THREAD_PENDING_EXC] @@ -3057,19 +1626,12 @@ stm tmp2, {r2, r3} DISPATCH 3 putfield_a: - GET_STACK 1, r0 - add oop_address_tmp, r0, tmp2 - POP oop_value_tmp - cmp r0, #0 + POP r2, r3 + cmp r3, #0 beq null_ptr_exception - bl oop_store - ldr r3, [dispatch, #Universe_collectedHeap_Address-XXX] - POP r2 - ldr r3, [r3, #0] - ldr r3, [r3, #12] - ldr r3, [r3, #76] - mov tmp2, #0 - strb tmp2, [r3, r2, lsr #9] + str r2, [r3, tmp2] + mov r0, r3 + bl Helper_aputfield DISPATCH 3 #endif @@ -3134,21 +1696,11 @@ stm r2, {r3, tmp2} DISPATCH_FINISH putstatic_a: - POP oop_value_tmp - add oop_address_tmp, r3, r2 - PUSH r3 - bl oop_store - ldr r3, [dispatch, #Universe_collectedHeap_Address-XXX] - DISPATCH_START 3 - POP r2 - ldr r3, [r3] - DISPATCH_NEXT - ldr r3, [r3, #12] - DISPATCH_NEXT - mov tmp2, #0 - ldr r3, [r3, #76] - strb tmp2, [r3, r2, lsr #9] - DISPATCH_FINISH + POP tmp2 + str tmp2, [r3, r2] + mov r0, r3 + bl Helper_aputfield + DISPATCH 3 resolve_invokeinterface: mov r1, #opc_invokeinterface @@ -3167,8 +1719,6 @@ DECACHE_JPC DECACHE_STACK bl _ZN18InterpreterRuntime14resolve_invokeEP10JavaThreadN9Bytecodes4CodeE - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r3, [r0, #4] @@ -3185,109 +1735,17 @@ # r1 = [jpc, #2] Opcode new ldrb r1, [jpc, #2] -#define k_entry tmp2 -#define new_result r7 -#define top_addr r7 -#define uch r7 -#define obj_size tmp1 - ldr r3, [istate, #ISTATE_METHOD] - orr r2, r1, r2, lsl #8 - ldr lr, [r3, #METHOD_CONSTANTS] - ldr r1, [lr, #CONSTANTPOOL_TAGS] - add r1, r1, #12 - ldrb r3, [r1, r2] - cmp r3, #JVM_CONSTANT_UnresolvedClassInError - cmpne r3, #JVM_CONSTANT_UnresolvedClass - beq .new_slow_case - - add r3, lr, #CONSTANTPOOL_BASE - ldr k_entry, [r3, r2, lsl #2] - - add r1, k_entry, #KLASS_PART - ldr r3, [r1, #INSTANCEKLASS_INITSTATE] - cmp r3, #class_fully_initialized - bne .new_slow_case - ldr r3, [r1, #4] - tst r3, #1 - bne .new_slow_case - - mov obj_size, r3, asr #2 -.new_retry: - ldr r0, [dispatch, #Universe_collectedHeap_Address-XXX] - ldr r0, [r0] - bl CollectedHeap_top_addr - mov top_addr, r0 - ldr r0, [dispatch, #Universe_collectedHeap_Address-XXX] - ldr r0, [r0] - bl CollectedHeap_end_addr - mov r1, top_addr - ldr new_result, [top_addr, #0] - add ip, new_result, obj_size, lsl #2 - ldr r3, [r0, #0] - cmp ip, r3 - bhi .new_slow_case - mov r2, new_result - add r0, new_result, obj_size, lsl #2 - bl cmpxchg_ptr - cmp r0, new_result - bne .new_retry - subs r2, obj_size, #2 -@ ECN: sub optimimal memset - tst r2, #1 - add r0, new_result, #8 - mov r1, #0 - mov ip, #0 - strne r1, [r0], #4 - tst r2, #2 - mov r3, #0 - mov lr, #0 - stmneia r0!, {r1, r3} - bics r2, r2, #3 - beq .new_zero_done -1: - subs r2, r2, #4 - stmia r0!, {r1, r3, ip, lr} - bne 1b -.new_zero_done: - ldr r3, [dispatch, #always_do_update_barrier_Address-XXX] - mov r2, #1 - ldrb r1, [r3] @ zero_extendqisi2 - str r2, [new_result, #0] - cmp r1, #0 - bne .new_do_update_barrier - str k_entry, [new_result, #4] -.new_exit: - str new_result, [stack], #-4 - CACHE_LOCALS - DISPATCH 3 -.new_do_update_barrier: - add oop_address_tmp, new_result, #4 -@ mov oop_value_tmp, k_entry @ oop_value_tmp == k_entry - adr lr, .new_exit - b oop_store -.new_slow_case: - ldrb r2, [jpc, #1] - ldrb r1, [jpc, #2] - ldr r3, [istate, #ISTATE_METHOD] DECACHE_JPC DECACHE_STACK - orr r2, r1, r2, lsl #8 - ldr r0, [istate, #ISTATE_THREAD] - ldr r1, [r3, #METHOD_CONSTANTS] - bl _ZN18InterpreterRuntime4_newEP10JavaThreadP19constantPoolOopDesci - ldr r0, [istate, #ISTATE_THREAD] - ASSERT_STACK_CACHED - ldr ip, [r0, #THREAD_PENDING_EXC] + orr r1, r1, r2, lsl #8 + mov r0, r8 + bl Helper_new CACHE_JPC CACHE_CP - cmp ip, #0 - CACHE_LOCALS - bne handle_exception - ldr r2, [r0, #THREAD_VM_RESULT] - str r2, [stack], #-4 - ldr r3, [istate, #ISTATE_THREAD] - str ip, [r3, #THREAD_VM_RESULT] - DISPATCH 3 + cmp r0, #0 + beq handle_exception + PUSH r0 + DISPATCH 3 bytecode_interpreter_str: .ascii "[Bytecode Interpreter]\000" @@ -3300,8 +1758,6 @@ DECACHE_JPC DECACHE_STACK bl _ZN18InterpreterRuntime8newarrayEP10JavaThread9BasicTypei - ASSERT_LOCALS_CACHED - ASSERT_STACK_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr ip, [r0, #THREAD_PENDING_EXC] @@ -3324,8 +1780,6 @@ ldr r1, [lr, #METHOD_CONSTANTS] ldr r0, [istate, #ISTATE_THREAD] bl _ZN18InterpreterRuntime9anewarrayEP10JavaThreadP19constantPoolOopDescii - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr ip, [r0, #THREAD_PENDING_EXC] @@ -3370,174 +1824,34 @@ # r1 = [jpc, #2] Opcode checkcast ldrb r1, [jpc, #2] - ldr r3, [istate, #ISTATE_METHOD] - ldr r0, [stack, #4] - ldr r3, [r3, #METHOD_CONSTANTS] @ R3 = METHOD->constants() - cmp r0, #0 - ldr ip, [r3, #CONSTANTPOOL_TAGS] - beq .checkcast_exit - add ip, ip, #12 - orr tmp2, r1, r2, lsl #8 - ldrb r2, [ip, tmp2] @ zero_extendqisi2 - cmp r2, #JVM_CONSTANT_UnresolvedClassInError - cmpne r2, #JVM_CONSTANT_UnresolvedClass - beq 3f - -4: - ldr r0, [r0, #4] - add r3, r3, tmp2, lsl #2 - ldr tmp1, [r3, #CONSTANTPOOL_BASE] - cmp tmp1, r0 - beq .checkcast_exit - - ldr r2, [tmp1, #16] - add tmp2, r0, #8 - add ip, tmp2, r2 - ldr ip, [ip, #-8] - cmp ip, tmp1 - beq .checkcast_exit - - cmp r2, #secondary_super_cache_offset_in_bytes - bne 2f - - mov r0, tmp2 - mov r1, tmp1 - - bl _ZNK5Klass23search_secondary_supersEP12klassOopDesc - cmp r0, #0 - beq 2f -.checkcast_exit: - DISPATCH 3 - -3: - ldr r0, [istate, #ISTATE_THREAD] DECACHE_JPC DECACHE_STACK - bl _ZN18InterpreterRuntime13quicken_io_ccEP10JavaThread - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED - ldr r0, [istate, #ISTATE_THREAD] + orr r1, r1, r2, lsl #8 + mov r0, r8 + GET_STACK 0, r2 + bl Helper_checkcast CACHE_JPC - ldr r3, [r0, #THREAD_PENDING_EXC] CACHE_CP - cmp r3, #0 - ldr r3, [istate, #ISTATE_METHOD] + cmp r0, #0 bne handle_exception - ldr r0, [stack, #4] - ldr r3, [r3, #METHOD_CONSTANTS] @ METHOD->constanst() might have moved - b 4b - -2: - DECACHE_JPC - DECACHE_STACK - mov r0, tmp2 - ldr r3, [istate, #ISTATE_THREAD] - ldr tmp2, [r3, #THREAD_RESOURCEAREA] - - ldr tmp_chunk, [tmp2, #RESOURCEAREA_CHUNK] - ldr tmp_hwm, [tmp2, #RESOURCEAREA_HWM] - ldr tmp_max, [tmp2, #RESOURCEAREA_MAX] - - bl _ZNK5Klass13external_nameEv - mov ip, r0 - add r0, tmp1, #8 - mov tmp1, ip - bl _ZNK5Klass13external_nameEv - mov r1, r0 - mov r0, tmp1 - bl SharedRuntime_generate_class_cast_message - str r0, [arm_sp, #0] - ldr r0, [istate, #ISTATE_THREAD] - adrl r1, bytecode_interpreter_str - mov r2, #99 - mov r3, #_thread_in_vm - str r3, [r0, #THREAD_STATE] - ldr r3, [dispatch, #VmSymbols_symbols_Address-XXX] - ldr r3, [r3, #VMSYMBOLS_ClassCastException * 4] - bl _ZN10Exceptions10_throw_msgEP6ThreadPKciP13symbolOopDescS3_ - add r0, istate, #ISTATE_THREAD - bl ThreadInVMfromJavaD - mov r0, tmp_chunk - ldr r3, [r0, #0] - CACHE_JPC - cmp r3, #0 - beq 1f - bl _ZN5Chunk9next_chopEv -1: - str tmp_hwm, [tmp2, #RESOURCEAREA_HWM] - str tmp_max, [tmp2, #RESOURCEAREA_MAX] - str tmp_chunk, [tmp2, #RESOURCEAREA_CHUNK] - b handle_exception + DISPATCH 3 # r2 = [jpc, #1] # r1 = [jpc, #2] Opcode instanceof ldrb r1, [jpc, #2] - ldr r3, [istate, #ISTATE_METHOD] - ldr r0, [stack, #4] - ldr r3, [r3, #METHOD_CONSTANTS] - cmp r0, #0 - ldr ip, [r3, #CONSTANTPOOL_TAGS] - beq .instanceof_not_instance - add ip, ip, #BASE_OFFSET_BYTE - orr tmp2, r1, r2, lsl #8 - ldrb r2, [ip, tmp2] - cmp r2, #JVM_CONSTANT_UnresolvedClassInError - cmpne r2, #JVM_CONSTANT_UnresolvedClass - beq 2f - -1: - ldr r0, [r0, #4] - add r3, r3, tmp2, lsl #2 - ldr tmp1, [r3, #CONSTANTPOOL_BASE] - cmp tmp1, r0 - beq .instanceof_is_instance - - ldr r2, [tmp1, #16] - add tmp2, r0, #8 - add ip, tmp2, r2 - ldr ip, [ip, #-8] - cmp ip, tmp1 - beq .instanceof_is_instance - - mov r0, #0 - cmp r2, #secondary_super_cache_offset_in_bytes - bne .instanceof_not_instance - - mov r0, tmp2 - mov r1, tmp1 - - bl _ZNK5Klass23search_secondary_supersEP12klassOopDesc - cmp r0, #0 - beq .instanceof_not_instance - -.instanceof_is_instance: - mov r0, #1 - str r0, [stack, #4] - DISPATCH 3 -.instanceof_not_instance: - mov r0, #0 - str r0, [stack, #4] - DISPATCH 3 - -2: - ldr r0, [istate, #ISTATE_THREAD] DECACHE_JPC DECACHE_STACK - bl _ZN18InterpreterRuntime13quicken_io_ccEP10JavaThread - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED - ldr r0, [istate, #ISTATE_THREAD] + orr r1, r1, r2, lsl #8 + mov r0, r8 + POP r2 + bl Helper_instanceof CACHE_JPC - ldr r3, [r0, #THREAD_PENDING_EXC] CACHE_CP - cmp r3, #0 - bne handle_exception - - ldr r3, [istate, #ISTATE_METHOD] - ldr r0, [stack, #4] - ldr r3, [r3, #METHOD_CONSTANTS] @ METHOD->constanst() might have moved - b 1b + cmp r0, #-1 + beq handle_exception + PUSH r0 + DISPATCH 3 Opcode monitorenter ldr r1, [stack, #4] @@ -3583,8 +1897,6 @@ DECACHE_STACK ldr r0, [istate, #ISTATE_THREAD] bl _ZN18InterpreterRuntime12monitorenterEP10JavaThreadP15BasicObjectLock - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r3, [r0, #THREAD_PENDING_EXC] @@ -3640,7 +1952,6 @@ ldr sl, [istate, #ISTATE_STACK_BASE] ldr r3, [stack, #4] CACHE_JPC - ASSERT_LOCALS_CACHED mov r1, r3 str r3, [sl, #4] ldr r2, [r3, #0] @@ -3663,8 +1974,6 @@ DECACHE_JPC DECACHE_STACK bl _ZN18InterpreterRuntime12monitorenterEP10JavaThreadP15BasicObjectLock - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r3, [r0, #THREAD_PENDING_EXC] @@ -3710,8 +2019,6 @@ ldr r0, [istate, #ISTATE_THREAD] bl _ZN18InterpreterRuntime11monitorexitEP10JavaThreadP15BasicObjectLock ldr r0, [istate, #ISTATE_THREAD] - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r3, [r0, #THREAD_PENDING_EXC] CACHE_JPC cmp r3, #0 @@ -3740,39 +2047,16 @@ ALIGN_WORD Opcode aastore - ldr tmp1, [stack, #12] @ arrObj - ldr tmp_vvv, [stack, #8] - SW_NPC cmp tmp1, #0 - ldr sl, [stack, #4] - SW_NPC beq null_ptr_exception -.abortentry115: - ldr r3, [tmp1, #8] - cmp tmp_vvv, r3 - bcs array_bounds_exception - cmp sl, #0 - beq .aastore_exit - ldr r3, [tmp1, #4] @ arrObj->klass() - ldr r0, [sl, #4] - ldr r1, [r3, #KLASS_PART+OBJARRAYKLASS_ELEMENTKLASS] - cmp r0, r1 - beq .aastore_exit - add r0, r0, #8 - bl is_subtype_of + DECACHE_JPC + DECACHE_STACK + mov r0, r8 + POP r1, r2, r3 + bl Helper_aastore + CACHE_JPC + CACHE_CP cmp r0, #0 - moveq r0, #VMSYMBOLS_ArrayStoreException - beq raise_exception -.aastore_exit: - ldr r2, [dispatch, #Universe_collectedHeap_Address-XXX] - add r1, tmp1, #BASE_OFFSET_WORD - str sl, [r1, tmp_vvv, asl #2]! - ldr r3, [r2] - mov lr, #0 - ldr r3, [r3, #12] - add stack, stack, #12 - ldr r3, [r3, #76] - strb lr, [r3, r1, lsr #9] - CACHE_CP - DISPATCH 1 + bne handle_exception + DISPATCH 1 Opcode wide ldrb r2, [jpc, #1] @@ -3862,8 +2146,6 @@ DECACHE_JPC DECACHE_STACK bl _ZN18InterpreterRuntime14multianewarrayEP10JavaThreadPi - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r1, [r0, #THREAD_PENDING_EXC] @@ -3901,19 +2183,13 @@ ldr r1, [r3] cmp r1, #1 bne 1f - add r0, istate, #ISTATE_THREAD - bl HandleMarkCleanerD - ldr r0, [istate, #ISTATE_THREAD] DECACHE_JPC DECACHE_STACK - bl _ZN20SafepointSynchronize5blockEP10JavaThread - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] + bl Helper_SafePoint CACHE_JPC - ldr r3, [r0, #THREAD_PENDING_EXC] CACHE_CP - cmp r3, #0 + cmp r0, #0 bne handle_exception 1: DISPATCH 0 @@ -3933,8 +2209,6 @@ ldr r2, [istate, #ISTATE_BCP] ldr r1, [istate, #ISTATE_METHOD] bl _ZN18InterpreterRuntime11_breakpointEP10JavaThreadP13methodOopDescPh - ASSERT_STACK_CACHED - ASSERT_LOCALS_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r3, [r0, #THREAD_PENDING_EXC] @@ -3986,7 +2260,7 @@ ldrcc ip, [r2, r3, asl #2] adr r2, unimplemented_opcode_msg mov r1, #99 - str ip, [arm_sp, #0] + str ip, [arm_sp, #-8]! bl _Z19report_fatal_varargPKciS0_z b breakpoint unimplemented_opcode_msg: @@ -4005,7 +2279,6 @@ DECACHE_STACK ldr r0, [istate, #ISTATE_THREAD] bl _ZN18InterpreterRuntime18register_finalizerEP10JavaThreadP7oopDesc - ASSERT_STACK_CACHED ldr r0, [istate, #ISTATE_THREAD] CACHE_JPC ldr r3, [r0, #THREAD_PENDING_EXC] @@ -4014,11 +2287,16 @@ beq handle_return b handle_exception -@ ECN: normal_entry_synchronized doesn't really mean synchronized. It means -@ may or may not be synchronized. So we still have to check the synchronized -@ flag in the synchronized path, otherwise we may get an IllegalMonitor. + ALIGN_CODE normal_entry_synchronized: stmfd arm_sp!, {regset, lr} + bl fast_normal_entry_synchronized + ldmfd arm_sp!, {regset, pc} + + ALIGN_CODE +fast_normal_entry_synchronized: + stmfd arm_sp!, {fast_regset, lr} + mov sl, r0 mov tmp1, r2 @@ -4027,7 +2305,7 @@ rsb r3, r0, r3 rsb r3, r3, arm_sp cmp r3, #32768 - blt stack_overflow_no_frame + blt stack_overflow_before_frame ldrh r2, [sl, #METHOD_MAXLOCALS] ldrh r3, [sl, #METHOD_SIZEOFPARAMETERS] @@ -4041,7 +2319,7 @@ sub r5, r5, #FRAME_SIZE+4 sub r5, r5, r0, lsl #2 cmp r3, r5 - bcs stack_overflow_no_frame + bcs stack_overflow_before_frame cmp r8, #0 ble .normal_entry_synchronized_no_locals @@ -4067,61 +2345,17 @@ ldm ip, {r0, r1} add r0, r0, ip str tmp_vvv, [tmp1, #THREAD_TOP_ZERO_FRAME] - CACHE_JPC +@ CACHE_JPC str tmp_vvv, [tmp1, #THREAD_LAST_JAVA_SP] add dispatch, r1, r0 ldr r0, [istate, #ISTATE_METHOD] - CACHE_STACK - USEC ldr r2, [r0, #METHOD_INVOCATIONCOUNTER] - USEC ldr lr, [dispatch, #InterpreterInvocationLimit_Address-XXX] - USEC add r2, r2, #INVOCATIONCOUNTER_COUNTINCREMENT - USEC ldr lr, [lr] - USEC str r2, [r0, #METHOD_INVOCATIONCOUNTER] - USEC cmp r2, lr ldr r3, [r0, #METHOD_ACCESSFLAGS] - USEC bcs sync_method_entry_freq_count_overflow - CACHE_LOCALS tst r3, #JVM_ACC_SYNCHRONIZED - CACHE_CP - bne normal_do_synchronization - DISPATCH 0 - -#ifdef USE_COMPILER -sync_method_entry_freq_count_overflow: - ldr r3, [r0, #METHOD_CONSTMETHOD] - ldrh r3, [r3, #CONSTMETHOD_CODESIZE] - mov r1, #0 - mov r0, tmp1 - cmp r3, #MAX_FG_METHOD_SIZE - bcc 1f - ldr tmp2, [dispatch, #BackgroundCompilation_Address-XXX] - mov r3, #1 - ldr r5, [tmp2] - str r3, [tmp2] - bl _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh - str r5, [tmp2] - b 2f -1: - bl _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh -2: - ldr r0, [istate, #ISTATE_METHOD] - CACHE_JPC - ldr r3, [r0, #METHOD_ACCESSFLAGS] + beq 1f + +@ Do Synchronisation + CACHE_STACK CACHE_LOCALS - tst r3, #JVM_ACC_SYNCHRONIZED - CACHE_CP - bne normal_do_synchronization - DISPATCH 0 -#endif - -do_execute_java_bytecodes_restore_locals_and_jpc: - CACHE_JPC -do_execute_java_bytecodes_restore_locals: - CACHE_LOCALS - CACHE_CP - DISPATCH 0 - -normal_do_synchronization: tst r3, #JVM_ACC_STATIC ldrne r3, [r0, #METHOD_CONSTANTS] ldreq sl, [locals, #0] @@ -4143,9 +2377,8 @@ blx r3 cmp r0, #0 bne .normal_do_synchronisation_2 + b 1f .normal_do_synchronisation_3: - cmp tmp_xxx, tmp_vvv - beq do_execute_java_bytecodes_restore_locals ldr r0, [istate, #ISTATE_THREAD] bic r1, tmp_xxx, #3 bl JavaThread_is_lock_owned @@ -4153,19 +2386,56 @@ beq .normal_do_synchronisation_4 mov r3, #0 str r3, [tmp1] - b do_execute_java_bytecodes_restore_locals + b 1f .normal_do_synchronisation_4: mov r1, tmp1 DECACHE_STACK ldr r0, [istate, #ISTATE_THREAD] bl _ZN18InterpreterRuntime12monitorenterEP10JavaThreadP15BasicObjectLock ldr r0, [istate, #ISTATE_THREAD] - ASSERT_STACK_CACHED ldr r3, [r0, #THREAD_PENDING_EXC] cmp r3, #0 mov r2, r0 - beq do_execute_java_bytecodes_restore_locals_and_jpc - b handle_exception_do_not_unlock + bne handle_exception_do_not_unlock +1: + USEC ldr r0, [istate, #ISTATE_METHOD] + USEC ldr r2, [r0, #METHOD_INVOCATIONCOUNTER] + USEC ldr lr, [dispatch, #InterpreterInvocationLimit_Address-XXX] + USEC add r2, r2, #INVOCATIONCOUNTER_COUNTINCREMENT + USEC ldr lr, [lr] + USEC str r2, [r0, #METHOD_INVOCATIONCOUNTER] + USEC cmp r2, lr + USEC bcs sync_method_entry_freq_count_overflow + CACHE_JPC + CACHE_LOCALS + CACHE_CP + DISPATCH 0 + +#ifdef USE_COMPILER +sync_method_entry_freq_count_overflow: + ldr r3, [r0, #METHOD_CONSTMETHOD] + ldrh r3, [r3, #CONSTMETHOD_CODESIZE] + mov r1, #0 + ldr r0, [istate, #ISTATE_THREAD] + cmp r3, #MAX_FG_METHOD_SIZE + bcc 1f + ldr tmp2, [dispatch, #BackgroundCompilation_Address-XXX] + mov r3, #1 + ldr r5, [tmp2] + str r3, [tmp2] + bl FREQ_COUNT_OVERFLOW + str r5, [tmp2] + b 2f +1: + bl FREQ_COUNT_OVERFLOW +2: + T2 cmp r0, #0 + CACHE_LOCALS + T2 bne call_thumb2 + CACHE_JPC + CACHE_CP + DISPATCH 0 +#endif # r2 = [jpc, #1] # r1 = [jpc, #2] @@ -4213,12 +2483,11 @@ ldr r2, [r1, #-4] add r3, tmp2, r3, lsl #2 ldr tmp2, [r3, r2] - SW_NPC cmp tmp2, #0 - SW_NPC beq abstractmethod_exception + cmp tmp2, #0 + beq abstractmethod_exception .invokeinterface_invoke: ldr tmp1, [istate, #ISTATE_THREAD] @ str tmp2, [istate, #ISTATE_CALLEE] -.abortentry116: ldr ip, [tmp2, #METHOD_FROM_INTERPRETED] mov r1, #0 str ip, [istate, #36] @@ -4229,20 +2498,20 @@ ldr r3, [ip] - mov tmp_invoke_len, #5 - -#ifdef FASTPATH_ENTRY - adr r0, normal_entry - cmp r3, r0 - beq fast_normal_entry_with_len -#endif - mov r0, tmp2 mov r1, ip +#ifndef SHARK + add r3, r3, #CODE_ALIGN_SIZE +#endif mov r2, tmp1 blx r3 - ASSERT_LOCALS_CACHED + adrl ip, dispatch_init_adcon + ldm ip, {r0, r1} + add r0, r0, ip + add dispatch, r1, r0 + + CACHE_LOCALS ldr ip, [istate, #ISTATE_THREAD] CACHE_JPC @@ -4304,19 +2573,6 @@ str stack, [tmp1, #THREAD_JAVA_SP] ldr r3, [ip, #0] -#ifdef FASTPATH_ENTRY - adr r0, normal_entry - cmp r3, r0 - beq fast_normal_entry -#ifdef NATIVE_ENTRY - adrl r0, native_entry - cmp r3, r0 - beq fast_native_entry -#endif - adr r0, accessor_entry - cmp r3, r0 - beq fast_accessor_entry -#endif b normal_dispatch_and_return #endif // FAST_BYTECODES @@ -4389,28 +2645,22 @@ str stack, [tmp1, #THREAD_JAVA_SP] ldr r3, [ip, #0] -#ifdef FASTPATH_ENTRY - adr r0, normal_entry - cmp r3, r0 - beq fast_normal_entry -#ifdef NATIVE_ENTRY - adr r0, native_entry - cmp r3, r0 - beq fast_native_entry -#endif - adr r0, accessor_entry - cmp r3, r0 - beq fast_accessor_entry -#endif normal_dispatch_and_return: mov r0, tmp2 mov r1, ip +#ifndef SHARK + add r3, r3, #CODE_ALIGN_SIZE +#endif mov r2, tmp1 - ldr r2, [istate, #ISTATE_THREAD] blx r3 - ASSERT_LOCALS_CACHED + adrl ip, dispatch_init_adcon + ldm ip, {r0, r1} + add r0, r0, ip + add dispatch, r1, r0 + + CACHE_LOCALS ldr ip, [istate, #ISTATE_THREAD] CACHE_JPC @@ -4464,48 +2714,8 @@ ldr ip, [istate, #36] ldr r3, [ip, #0] -#ifdef FASTPATH_ENTRY - adr r0, normal_entry - cmp r3, r0 - beq fast_normal_entry -#ifdef NATIVE_ENTRY - adr r0, native_entry - cmp r3, r0 - beq fast_native_entry -#endif - adr r0, accessor_entry - cmp r3, r0 - beq fast_accessor_entry -#endif b normal_dispatch_and_return - ALIGN_CODE -normal_entry: - adrl ip, dispatch_init_adcon - stmfd arm_sp!, {regset, lr} - mov tmp2, r0 - ldm ip, {r0, r1} - - mov tmp_invoke_len, #0 - mov tmp1, r2 - - add r0, r0, ip - add dispatch, r1, r0 - - USEC ldr r2, [r10, #METHOD_INVOCATIONCOUNTER] - - ldr stack, [tmp1, #THREAD_JAVA_SP] - - ldr r0, [tmp1, #THREAD_STACK_SIZE] - USEC add r2, r2, #INVOCATIONCOUNTER_COUNTINCREMENT * 4 - ldr r3, [tmp1, #THREAD_STACK_BASE] - rsb r3, r0, r3 - rsb r3, r3, arm_sp - USEC str r2, [tmp2, #METHOD_INVOCATIONCOUNTER] - cmp r3, #32768 - bge fast_normal_entry_with_len - - b stack_overflow_before_frame Opcode invokespecial ldrb r1, [jpc, #2] @@ -4546,81 +2756,35 @@ str stack, [tmp1, #THREAD_JAVA_SP] ldr r3, [ip, #0] -#ifdef FASTPATH_ENTRY - adr r0, normal_entry - cmp r3, r0 - beq fast_normal_entry -#ifdef NATIVE_ENTRY - adr r0, native_entry - cmp r3, r0 - beq fast_native_entry -#endif - adr r0, accessor_entry - cmp r3, r0 - beq fast_accessor_entry -#endif b normal_dispatch_and_return ALIGN_CODE -accessor_entry: - adrl ip, dispatch_init_adcon - ldr r3, [ip] - add r3, r3, ip - ldr ip, [ip, #12] - ldr ip, [r3, ip] - ldr r1, [r0, #8] - ldr ip, [ip, #0] - ldrb r3, [r1, #50] - ldrb r1, [r1, #51] - cmp ip, #0 - ldr ip, [r0, #12] - bne normal_entry - ldr ip, [ip, #12] - orr r3, r3, r1, lsl #8 @ r3 = index - - add r1, ip, #16 - ldr r3, [r1, r3, lsl #4]! @ r1 = cache, r3 = flags - ldr ip, [r2, #THREAD_JAVA_SP] @ ip == stack - and r3, r3, #0x00ff0000 - cmp r3, #opc_getfield << 16 - ldr r3, [ip, #0] - bne normal_entry - - cmp r3, #0 - beq normal_entry - - ldr r0, [r1, #12] - ldr r1, [r1, #8] - movs r0, r0, lsr #29 - bls accessor_non_w - - ldr r0, [r3, r1] - str r0, [ip, #0] - bx lr - -#ifdef NATIVE_ENTRY - ALIGN_CODE -native_entry: - adrl ip, dispatch_init_adcon - stmfd arm_sp!, {r3, r4, r5, r6, r7, r8, r9, r10, r11, lr} - - ldm ip, {dispatch, r7} - mov r11, r0 - add dispatch, dispatch, ip - add dispatch, dispatch, r7 - - mov istate, #0 - - b fast_native_entry_with_args -#endif - -@ tmp1 = thread -@ tmp2 == method -@ stack == THREAD_JAVA_SP (=> FULL stack) +normal_entry: + stmfd arm_sp!, {regset, lr} + + ldr r7, [r2, #THREAD_STACK_SIZE] + ldr r3, [r2, #THREAD_STACK_BASE] + rsb r3, r7, r3 + rsb r3, r3, arm_sp + cmp r3, #32768 + blt stack_overflow_no_frame + + bl fast_normal_entry + + ldmfd arm_sp!, {regset, pc} + ALIGN_CODE fast_normal_entry: - mov tmp_invoke_len, #3 -fast_normal_entry_with_len: + adrl ip, dispatch_init_adcon + mov tmp2, r0 + ldm ip, {r0, r1} + mov tmp1, r2 + add r0, r0, ip + ldr stack, [tmp1, #THREAD_JAVA_SP] + add dispatch, r1, r0 + + stmdb arm_sp!, {fast_regset, lr} + ldrh r0, [tmp2, #METHOD_MAXLOCALS] mov r1, #0 ldrh r3, [tmp2, #METHOD_SIZEOFPARAMETERS] @@ -4646,9 +2810,10 @@ bcs 1b 3: ldr r3, [tmp1, #THREAD_TOP_ZERO_FRAME] + mov lr, #0 sub istate, stack, #FRAME_SIZE sub r2, istate, r2, lsl #2 - str tmp_invoke_len, [istate, #ISTATE_ADVANCE_PC] + str lr, [istate, #ISTATE_MSG] str r2, [tmp1, #THREAD_JAVA_SP] sub r5, r2, #4 @ stack limit = istate - stackwords - 4 str r3, [istate, #ISTATE_NEXT_FRAME] @@ -4664,7 +2829,7 @@ ldr jpc, [tmp2, #METHOD_CONSTMETHOD] ldr constpool, [tmp2, #METHOD_CONSTANTS] add ip, istate, #ISTATE_NEXT_FRAME - DISPATCH_START 48 + DISPATCH_START CONSTMETHOD_CODEOFFSET ldr constpool, [constpool, #CONSTANTPOOL_CACHE] str ip, [tmp1, #THREAD_TOP_ZERO_FRAME] USEC ldr r3, [r10, #METHOD_INVOCATIONCOUNTER] @@ -4701,22 +2866,35 @@ mov r3, #1 ldr r5, [tmp2] str r3, [tmp2] - bl _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh + bl FREQ_COUNT_OVERFLOW str r5, [tmp2] b 2f 1: - bl _ZN18InterpreterRuntime26frequency_counter_overflowEP10JavaThreadPh + bl FREQ_COUNT_OVERFLOW 2: + T2 cmp r0, #0 + T2 bne call_thumb2 CACHE_JPC CACHE_CP DISPATCH 0 -#endif - + +#ifdef THUMB2EE +call_thumb2: + mov ip, r1 + mov r1, locals + ldr r2, [istate, #ISTATE_THREAD] + add stack, stack, #4 + bx ip +#endif // THUMB2EE + +#endif // USE_COMPILER + .global Thumb2_Install +Thumb2_Install: +@ ldr r0, [r0] + str r1, [r0, #METHOD_FROM_INTERPRETED] + bx lr handle_return: -@ CHECK_CONSTPOOL -@ CHECK_BACKTRACE - ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end @@ -4725,9 +2903,6 @@ cmp tmp1, tmp2 blcc return_check_monitors -@ CHECK_CONSTPOOL -@ CHECK_BACKTRACE - mov r3, #0 ldrb lr, [jpc, #0] @@ -4739,9 +2914,6 @@ add r1, r2, #4 str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - add r1, r1, r0, lsl #2 cmp lr, #opc_lreturn @@ -4756,152 +2928,27 @@ str r1, [tmp_xxx, #THREAD_JAVA_SP] - cmp ip, #0 - - ldmeqfd arm_sp!, {regset, pc} - - ldr lr, [istate, #-ISTATE_NEXT_FRAME+ISTATE_THREAD]! - CACHE_JPC - ldr stack, [lr, #THREAD_JAVA_SP] - ldr r2, [istate, #ISTATE_STACK_LIMIT] - sub stack, stack, #4 - - ldr r1, [lr, #THREAD_TOP_ZERO_FRAME] - add r2, r2, #4 - str r2, [lr, #THREAD_JAVA_SP] - str r1, [lr, #THREAD_LAST_JAVA_SP] - ldr r3, [lr, #THREAD_PENDING_EXC] - DISPATCH_START_REG ip - CACHE_LOCALS - DISPATCH_NEXT - DISPATCH_NEXT - cmp r3, #0 - DISPATCH_NEXT - bne return_exception - DISPATCH_NEXT - CACHE_CP - DISPATCH_FINISH - -@ ip = PC ADVANCE -fast_handle_return: - ldr lr, [istate, #-ISTATE_NEXT_FRAME+ISTATE_THREAD]! - CACHE_JPC - ldr stack, [lr, #THREAD_JAVA_SP] - ldr r2, [istate, #ISTATE_STACK_LIMIT] - sub stack, stack, #4 - - ldr r1, [lr, #THREAD_TOP_ZERO_FRAME] - add r2, r2, #4 - str r2, [lr, #THREAD_JAVA_SP] - str r1, [lr, #THREAD_LAST_JAVA_SP] - ldr r3, [lr, #THREAD_PENDING_EXC] - DISPATCH_START_REG ip - CACHE_LOCALS - DISPATCH_NEXT - DISPATCH_NEXT - cmp r3, #0 - DISPATCH_NEXT - bne return_exception - DISPATCH_NEXT - CACHE_CP - DISPATCH_FINISH - -normal_return: - str stack, [tmp_xxx, #THREAD_JAVA_SP] - ldmfd arm_sp!, {regset, pc} - -return_check_monitors: - ldr r2, [istate, #ISTATE_METHOD] - ldr r0, [r2, #24] - tst r0, #1<<5 - subne tmp2, tmp2, #8 - cmp tmp1, tmp2 - bcs .return_unlock -1: - ldr r3, [tmp1, #4] - cmp r3, #0 - bne return_throw_illegal_monitor_state - add tmp1, tmp1, #8 - cmp tmp1, tmp2 - bcc 1b - -#define RETURN_STACKSIZE SIZEOF_HANDLEMARK - -.return_unlock: - tst r0, #1<<5 - bxeq lr - - ldr tmp1, [tmp2, #4] @ base->obj == NULL - SW_NPC cmp tmp1, #0 - SW_NPC beq return_throw_illegal_monitor_state -.abortentry119: - HW_NPC ldr ip, [tmp1] @ Only to provoke abort - - ldr r0, [tmp2, #0] @ r0 = header - mov r3, #0 - cmp r0, #0 - str r3, [tmp2, #4] @ base->obj = NULL - bxeq lr - - mov tmp_vvv, lr - mov r1, tmp1 - mov r2, tmp2 - bl cmpxchg_ptr - cmp tmp2, r0 - bxeq tmp_vvv - - str tmp1, [tmp2, #4] - sub arm_sp, arm_sp, #RETURN_STACKSIZE - mov r0, arm_sp - mov r1, tmp_xxx - bl _ZN10HandleMark10initializeEP6Thread - mov r1, tmp2 - mov r0, tmp_xxx - DECACHE_JPC - DECACHE_STACK - bl _ZN18InterpreterRuntime11monitorexitEP10JavaThreadP15BasicObjectLock - ASSERT_STACK_CACHED - CACHE_JPC - mov r0, arm_sp - bl _ZN10HandleMarkD1Ev - add arm_sp, arm_sp, #RETURN_STACKSIZE - ldr r3, [tmp_xxx, #THREAD_PENDING_EXC] - cmp r3, #0 - bne handle_exception - mov lr, tmp_vvv - bx lr - -return_throw_illegal_monitor_state: - sub arm_sp, arm_sp, #RETURN_STACKSIZE - mov r0, arm_sp - mov r1, tmp_xxx - bl _ZN10HandleMark10initializeEP6Thread - DECACHE_JPC - DECACHE_STACK - mov r0, tmp_xxx - bl _ZN18InterpreterRuntime37throw_illegal_monitor_state_exceptionEP10JavaThread - mov r0, arm_sp - bl _ZN10HandleMarkD1Ev - add arm_sp, arm_sp, #RETURN_STACKSIZE - b handle_exception_with_bcp + ldmfd arm_sp!, {fast_regset, pc} @ ---------------------------------------------------------------------------------------- stack_overflow_no_frame: - mov tmp_invoke_len, #0 + mov r0, tmp1 + ldr ip, [r0, #THREAD_TOP_ZERO_FRAME] + str ip, [r0, #THREAD_LAST_JAVA_SP] + bl _ZN18InterpreterRuntime24throw_StackOverflowErrorEP10JavaThread + ldmfd arm_sp!, {regset, pc} + stack_overflow_before_frame: mov r0, tmp1 ldr ip, [r0, #THREAD_TOP_ZERO_FRAME] str ip, [r0, #THREAD_LAST_JAVA_SP] - mov tmp1, tmp_invoke_len bl _ZN18InterpreterRuntime24throw_StackOverflowErrorEP10JavaThread - cmp tmp1, #0 - bne handle_exception_with_bcp - ldmfd arm_sp!, {regset, pc} + ldmfd arm_sp!, {fast_regset, pc} handle_exception_do_not_unlock: mov r3, #1 strb r3, [r2, #THREAD_DO_NOT_UNLOCK] - b handle_exception + b handle_exception_with_bcp abstractmethod_exception: mov r0, #VMSYMBOLS_AbstractMethodError @@ -4911,39 +2958,21 @@ raise_exception: adr r1, null_str raise_exception_with_msg: - str r1, [arm_sp] - ldr r3, [dispatch, #VmSymbols_symbols_Address-XXX] - ldr r3, [r3, r0, lsl #2] - ldr r0, [istate, #ISTATE_THREAD] + stmdb sp!, {r0, r1} + bl load_dispatch + ldmia sp!, {r0, r1} DECACHE_JPC DECACHE_STACK - mov ip, #_thread_in_vm - str ip, [r0, #THREAD_STATE] - mov r2, #99 - adrl r1, bytecode_interpreter_str - bl _ZN10Exceptions10_throw_msgEP6ThreadPKciP13symbolOopDescS3_ - add r0, istate, #ISTATE_THREAD - bl ThreadInVMfromJavaD + mov r2, r1 + ldr r1, [dispatch, #VmSymbols_symbols_Address-XXX] + ldr r1, [r1, r0, lsl #2] + ldr r0, [istate, #ISTATE_THREAD] + bl Helper_Raise b handle_exception_with_bcp null_str: .byte 0 ALIGN_WORD -#define EXCEPTION_HANDLEMARK 0 -#define EXCEPTION_THREAD EXCEPTION_HANDLEMARK + SIZEOF_HANDLEMARK -#define EXCEPTION_EXCEPTION EXCEPTION_THREAD + 4 -#define EXCEPTION_EXCEPTION2 EXCEPTION_EXCEPTION + 4 -#define EXCEPTION_MONITORBASE EXCEPTION_EXCEPTION2 + 4 -#define EXCEPTION_TMP1 EXCEPTION_MONITORBASE + 4 -#define EXCEPTION_HANDLEMARK2 EXCEPTION_TMP1 + 4 -#define EXCEPTION_HANDLE EXCEPTION_HANDLEMARK2 + SIZEOF_HANDLEMARK -#define EXCEPTION_HANDLE2 EXCEPTION_HANDLE + 4 -#define EXCEPTION_HANDLE3 EXCEPTION_HANDLE2 + 4 - -#define EXCEPTION_STACKSIZE EXCEPTION_HANDLE3 + 4 - -#define except_sp r13 - invokeinterface_exception_fix: sub jpc, jpc, #2 invoke_exception_fix: @@ -4960,432 +2989,157 @@ @ constpool = garbage DECACHE_JPC handle_exception_with_bcp: - sub except_sp, except_sp, #EXCEPTION_STACKSIZE + bl load_dispatch ldr stack, [istate, #ISTATE_STACK_BASE] sub stack, stack, #4 DECACHE_STACK - ldr r0, [istate, #ISTATE_THREAD] -handle_exception_1: - ldr sl, [r0, #4] - str r0, [except_sp, #EXCEPTION_THREAD] - cmp sl, #0 - moveq tmp_yyy, sl - beq .handle_exception_3 - ldr r0, [r0, #THREAD_HANDLE_AREA] - ldr r1, [r0, #8] - ldr r3, [r0, #12] - add r2, r1, #4 - cmp r2, r3 - movls r3, r1 - strls r2, [r0, #8] - bls .handle_exception_2 - mov r1, #4 - bl _ZN5Arena4growEj - mov r3, r0 -.handle_exception_2: - str sl, [r3, #0] - mov tmp_yyy, r3 - ldr r0, [istate, #ISTATE_THREAD] -.handle_exception_3: - mov r1, r0 - add r0, except_sp, #EXCEPTION_HANDLEMARK - bl _ZN10HandleMark10initializeEP6Thread - ldr r0, [istate, #ISTATE_THREAD] - bl _ZN12ThreadShadow23clear_pending_exceptionEv - ldr r1, [istate, #ISTATE_STACK_BASE] - ldr r0, [istate, #ISTATE_THREAD] - cmp tmp_yyy, #0 - sub stack, r1, #4 - moveq r1, tmp_yyy - DECACHE_STACK - ldrne r1, [tmp_yyy, #0] - bl _ZN18InterpreterRuntime31exception_handler_for_exceptionEP10JavaThreadP7oopDesc - ASSERT_STACK_CACHED - mov sl, r0 - ldr r0, [istate, #ISTATE_THREAD] - ldr r3, [r0, #THREAD_PENDING_EXC] - cmp r3, #0 - beq .handle_exception_5 - add r0, except_sp, #EXCEPTION_HANDLEMARK - bl _ZN10HandleMarkD1Ev - ldr r1, [except_sp, #EXCEPTION_THREAD] - ldr tmp_yyy, [r1, #THREAD_LAST_HANDLE_MARK] - ldr r0, [tmp_yyy, #8] - ldr sl, [tmp_yyy, #4] - ldr r3, [r0, #0] - cmp r3, #0 - beq .handle_exception_4 - bl _ZN5Chunk9next_chopEv - ldr r0, [tmp_yyy, #8] -.handle_exception_4: - str r0, [sl, #4] - ldr r3, [tmp_yyy, #12] - str r3, [sl, #8] - ldr r2, [tmp_yyy, #16] - str r2, [sl, #12] - ldr r0, [istate, #ISTATE_THREAD] - b handle_exception_1 -.handle_exception_5: - ldr tmp_yyy, [r0, #THREAD_VM_RESULT] - cmp tmp_yyy, #0 - moveq r1, tmp_yyy - beq .handle_exception_7 - ldr r3, [dispatch, #ThreadLocalStorage_thread_index-XXX] - ldr r0, [r3] - bl pthread_getspecific - ldr r0, [r0, #THREAD_HANDLE_AREA] - ldr r1, [r0, #8] - ldr r3, [r0, #12] - add r2, r1, #4 - cmp r2, r3 - movls r3, r1 - strls r2, [r0, #8] - bls .handle_exception_6 - mov r1, #4 - bl _ZN5Arena4growEj - mov r3, r0 -.handle_exception_6: - str tmp_yyy, [r3, #0] - mov r1, r3 - ldr r0, [istate, #ISTATE_THREAD] -.handle_exception_7: - cmp sl, #0 + + mov r0, istate + ldr r1, [istate, #ISTATE_THREAD] + bl Helper_HandleException + cmp r0, #0 + beq 1f + + mov jpc, r0 + CACHE_STACK + CACHE_LOCALS + CACHE_CP + DISPATCH 0 +1: + ldr tmp2, [istate, #ISTATE_MONITOR_BASE] @ tmp2 = base + + ldr tmp1, [istate, #ISTATE_STACK_BASE] @ tmp1 = end + ldr tmp_xxx, [istate, #ISTATE_THREAD] + mov r3, #0 - str r3, [r0, #THREAD_VM_RESULT] - blt .handle_exception_9 - cmp r1, r3 - moveq r0, r1 - ldrne r0, [r1, #0] - str r0, [stack, #0] - sub stack, stack, #4 - ldr r3, [istate, #ISTATE_METHOD] - add r0, except_sp, #EXCEPTION_HANDLEMARK - ldr r2, [r3, #8] - add r2, r2, #48 - add ip, r2, sl - str ip, [istate, #ISTATE_BCP] - bl _ZN10HandleMarkD1Ev - ldr r1, [except_sp, #EXCEPTION_THREAD] - ldr tmp_yyy, [r1, #THREAD_LAST_HANDLE_MARK] - ldr r0, [tmp_yyy, #8] - ldr sl, [tmp_yyy, #4] - ldr r3, [r0, #0] + ldrb r0, [tmp_xxx, #THREAD_DO_NOT_UNLOCK] + strb r3, [tmp_xxx, #THREAD_DO_NOT_UNLOCK] + cmp r0, #0 + bne 2f + + cmp tmp1, tmp2 + blcc return_check_monitors + +2: + mov r3, #0 + + ldr r2, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] + str r3, [tmp_xxx, #THREAD_LAST_JAVA_SP] + ldr r0, [istate, #ISTATE_METHOD] + ldr r3, [r2, #0] + ldrh r0, [r0, #40] + add r1, r2, #4 + str r3, [tmp_xxx, #THREAD_TOP_ZERO_FRAME] + + add r1, r1, r0, lsl #2 + + str r1, [tmp_xxx, #THREAD_JAVA_SP] + + ldmfd arm_sp!, {fast_regset, pc} + +return_check_monitors: + stmdb arm_sp!, {r4, lr} + + ldr r2, [istate, #ISTATE_METHOD] + ldr r4, [r2, #METHOD_ACCESSFLAGS] + tst r4, #1<<5 + subne tmp2, tmp2, #8 + cmp tmp1, tmp2 + bcs 2f +1: + ldr r3, [tmp1, #4] cmp r3, #0 - beq .handle_exception_8 - bl _ZN5Chunk9next_chopEv - ldr r0, [tmp_yyy, #8] -.handle_exception_8: - str r0, [sl, #4] - ldr r3, [tmp_yyy, #12] - str r3, [sl, #8] - ldr r2, [tmp_yyy, #16] - str r2, [sl, #12] - add except_sp, except_sp, #EXCEPTION_STACKSIZE - b do_execute_java_bytecodes_restore_locals_and_jpc -.handle_exception_9: - cmp r1, #0 - ldr r0, [istate, #ISTATE_THREAD] - mov r2, #0 - ldrne r1, [r1, #0] - mov r3, r2 - bl _ZN12ThreadShadow21set_pending_exceptionEP7oopDescPKci - ldr r0, [istate, #ISTATE_THREAD] - ldr tmp_yyy, [r0, #4] - cmp tmp_yyy, #0 - streq tmp_yyy, [except_sp, #EXCEPTION_EXCEPTION] - beq .handle_exception_11 - ldr r0, [r0, #THREAD_HANDLE_AREA] - ldr r1, [r0, #8] - ldr r3, [r0, #12] - add r2, r1, #4 - cmp r2, r3 - movls r3, r1 - strls r2, [r0, #8] - bls .handle_exception_10 - mov r1, #4 - bl _ZN5Arena4growEj - mov r3, r0 -.handle_exception_10: - str tmp_yyy, [r3, #0] - ldr r0, [istate, #ISTATE_THREAD] - str r3, [except_sp, #EXCEPTION_EXCEPTION] -.handle_exception_11: - bl _ZN12ThreadShadow23clear_pending_exceptionEv - mov r1, #0 - ldr r0, [istate, #ISTATE_THREAD] - str r1, [except_sp, #EXCEPTION_EXCEPTION2] - ldrb r3, [r0, #THREAD_DO_NOT_UNLOCK] @ zero_extendqisi2 - cmp r3, r1 - beq .handle_exception_15 - strb r1, [r0, #THREAD_DO_NOT_UNLOCK] - ldr r0, [istate, #ISTATE_THREAD] -.handle_exception_12: - ldr r1, [except_sp, #EXCEPTION_EXCEPTION] - cmp r1, #0 - movne r2, r1 - ldrne r1, [r2, #0] -.handle_exception_13: - mov r2, #0 - mov r3, r2 - bl _ZN12ThreadShadow21set_pending_exceptionEP7oopDescPKci - mov r3, #0 - ldr r2, [istate, #ISTATE_BCP] - ldrb r2, [r2, #0] @ zero_extendqisi2 - DECACHE_STACK - str r2, [istate, #ISTATE_CALLEE] - ldr lr, [istate, #ISTATE_THREAD] - ldr r1, [lr, #THREAD_TOP_ZERO_FRAME] - str r3, [lr, #THREAD_LAST_JAVA_SP] - add r2, r1, #4 - str r2, [lr, #THREAD_JAVA_SP] - ldr r3, [r1, #0] - str r3, [lr, #THREAD_TOP_ZERO_FRAME] - ldr r1, [istate, #ISTATE_METHOD] - ldrh r3, [r1, #40] - add r0, except_sp, #EXCEPTION_HANDLEMARK - mov r3, r3, asl #2 - add r2, r2, r3 - str r2, [lr, #THREAD_JAVA_SP] - bl _ZN10HandleMarkD1Ev - ldr r0, [except_sp, #EXCEPTION_THREAD] - ldr tmp_yyy, [r0, #THREAD_LAST_HANDLE_MARK] - ldr r0, [tmp_yyy, #8] - ldr sl, [tmp_yyy, #4] - ldr r3, [r0, #0] - cmp r3, #0 - beq .handle_exception_14 - bl _ZN5Chunk9next_chopEv - ldr r0, [tmp_yyy, #8] -.handle_exception_14: - str r0, [sl, #4] - ldr r3, [tmp_yyy, #12] - str r3, [sl, #8] - ldr r2, [tmp_yyy, #16] - str r2, [sl, #12] - add except_sp, except_sp, #EXCEPTION_STACKSIZE - ldr ip, [istate, #ISTATE_ADVANCE_PC] - ldr istate, [istate, #ISTATE_NEXT_FRAME] - cmp ip, #0 - bne fast_handle_return - ldmfd arm_sp!, {regset, pc} -.handle_exception_15: - ldr ip, [istate, #ISTATE_MONITOR_BASE] - ldr r2, [istate, #ISTATE_METHOD] - str ip, [except_sp, #EXCEPTION_MONITORBASE] - ldr tmp_vvv, [istate, #ISTATE_STACK_BASE] - ldr r3, [r2, #24] - mov r3, r3, lsr #5 - ands r3, r3, #1 - subne ip, ip, #8 - strne ip, [except_sp, #EXCEPTION_MONITORBASE] - ldr lr, [except_sp, #EXCEPTION_MONITORBASE] - str r3, [except_sp, #EXCEPTION_TMP1] - cmp tmp_vvv, lr - bcs .handle_exception_21 - - .p2align 3 -.handle_exception_16: - ldr tmp_yyy, [tmp_vvv, #4] - cmp tmp_yyy, #0 - beq .handle_exception_20 - ldr fp, [tmp_vvv, #0] - mov r2, #0 - cmp fp, r2 - str r2, [tmp_vvv, #4] - beq .handle_exception_19 - .p2align 3 -.handle_exception_17: - ldr sl, [tmp_yyy, #0] - cmp tmp_vvv, sl - bne .handle_exception_18 - mov r0, tmp_vvv - mov r1, fp - mov r2, tmp_yyy - mov r3, #0xffffffc0 - bic r3, r3, #0xf000 - blx r3 - cmp r0, #0 - bne .handle_exception_17 -.handle_exception_18: - cmp tmp_vvv, sl - beq .handle_exception_19 - str tmp_yyy, [tmp_vvv, #4] - add r0, except_sp, #EXCEPTION_HANDLEMARK2 - ldr r1, [istate, #ISTATE_THREAD] - bl _ZN10HandleMark10initializeEP6Thread - mov r1, tmp_vvv - ldr r0, [istate, #ISTATE_THREAD] - DECACHE_STACK - bl _ZN18InterpreterRuntime11monitorexitEP10JavaThreadP15BasicObjectLock - ASSERT_STACK_CACHED - add r0, except_sp, #EXCEPTION_HANDLEMARK2 - bl _ZN10HandleMarkD1Ev -.handle_exception_19: - ldr r1, [except_sp, #EXCEPTION_EXCEPTION2] - cmp r1, #0 - beq .handle_exception_27 - ldr r3, [r1, #0] - cmp r3, #0 - beq .handle_exception_27 -.handle_exception_20: - ldr r3, [except_sp, #EXCEPTION_MONITORBASE] - add tmp_vvv, tmp_vvv, #8 - cmp tmp_vvv, r3 - bcc .handle_exception_16 -.handle_exception_21: - ldr ip, [except_sp, #EXCEPTION_TMP1] - cmp ip, #0 - beq .handle_exception_23 - ldr r0, [except_sp, #EXCEPTION_MONITORBASE] - ldr sl, [r0, #4] - cmp sl, #0 - beq .handle_exception_26 - mov ip, r0 - ldr r0, [r0, #0] + bne 3f + add tmp1, tmp1, #8 + cmp tmp1, tmp2 + bcc 1b + +2: + tst r4, #1<<5 + + ldmeqia arm_sp!, {r4, pc} + + ldr tmp1, [tmp2, #4] @ base->obj == NULL + cmp tmp1, #0 + beq 4f + + ldr r0, [tmp2, #0] @ r0 = header mov r3, #0 cmp r0, #0 - str r3, [ip, #4] - beq .handle_exception_23 - mov r1, sl - ldr r2, [except_sp, #EXCEPTION_MONITORBASE] + str r3, [tmp2, #4] @ base->obj = NULL + + ldmeqia arm_sp!, {r4, pc} + + mov r1, tmp1 + mov r2, tmp2 bl cmpxchg_ptr - ldr r1, [except_sp, #EXCEPTION_MONITORBASE] - cmp r1, r0 - beq .handle_exception_22 - ldr r3, [except_sp, #EXCEPTION_MONITORBASE] - add tmp_yyy, except_sp, #EXCEPTION_HANDLEMARK2 - mov r0, tmp_yyy - str sl, [r3, #4] - ldr r1, [istate, #ISTATE_THREAD] - bl _ZN10HandleMark10initializeEP6Thread - ldr r1, [except_sp, #EXCEPTION_MONITORBASE] - ldr r0, [istate, #ISTATE_THREAD] - DECACHE_STACK - bl _ZN18InterpreterRuntime11monitorexitEP10JavaThreadP15BasicObjectLock - mov r0, tmp_yyy - ASSERT_STACK_CACHED - bl _ZN10HandleMarkD1Ev - ldr r0, [istate, #ISTATE_THREAD] - ldr r1, [r0, #4] - cmp r1, #0 - beq .handle_exception_24 - add r0, except_sp, #EXCEPTION_HANDLE2 - bl HandleC - ldr r1, [except_sp, #EXCEPTION_HANDLE2] - ldr r0, [istate, #ISTATE_THREAD] - str r1, [except_sp, #EXCEPTION_EXCEPTION2] - bl _ZN12ThreadShadow23clear_pending_exceptionEv -.handle_exception_22: - ldr r0, [istate, #ISTATE_THREAD] - b .handle_exception_24 -.handle_exception_23: + cmp tmp2, r0 + + ldmeqia arm_sp!, {r4, pc} + + str tmp1, [tmp2, #4] + + mov r1, tmp2 ldr r0, [istate, #ISTATE_THREAD] -.handle_exception_24: - ldr r3, [except_sp, #EXCEPTION_EXCEPTION2] - cmp r3, #0 - beq .handle_exception_12 -.handle_exception_25: - ldr lr, [except_sp, #EXCEPTION_EXCEPTION2] - ldr r1, [lr, #0] - cmp r1, #0 - bne .handle_exception_13 - b .handle_exception_12 -.handle_exception_26: - ldr r1, [except_sp, #EXCEPTION_EXCEPTION2] - cmp r1, #0 - beq .handle_exception_29 - ldr r3, [r1, #0] - cmp r3, #0 - beq .handle_exception_29 - ldr r0, [istate, #ISTATE_THREAD] - b .handle_exception_25 - -.handle_exception_27: - add r0, except_sp, #EXCEPTION_HANDLEMARK2 - ldr r1, [istate, #ISTATE_THREAD] - bl _ZN10HandleMark10initializeEP6Thread + bl Helper_synchronized_exit + + ldmeqia arm_sp!, {r4, pc} + +3: ldr r0, [istate, #ISTATE_THREAD] - DECACHE_STACK - bl _ZN18InterpreterRuntime37throw_illegal_monitor_state_exceptionEP10JavaThread - add r0, except_sp, #EXCEPTION_HANDLEMARK2 - ASSERT_STACK_CACHED - bl _ZN10HandleMarkD1Ev - add r0, except_sp, #EXCEPTION_HANDLE - ldr r3, [istate, #ISTATE_THREAD] - ldr r1, [r3, #4] - bl HandleC - ldr r2, [except_sp, #EXCEPTION_HANDLE] + bl Helper_RaiseIllegalMonitorException + b 2b + +4: ldr r0, [istate, #ISTATE_THREAD] - str r2, [except_sp, #EXCEPTION_EXCEPTION2] - bl _ZN12ThreadShadow23clear_pending_exceptionEv - b .handle_exception_20 -.handle_exception_29: - add tmp_yyy, except_sp, #EXCEPTION_HANDLEMARK2 - mov r0, tmp_yyy - ldr r1, [istate, #ISTATE_THREAD] - bl _ZN10HandleMark10initializeEP6Thread - ldr r0, [istate, #ISTATE_THREAD] - DECACHE_STACK - bl _ZN18InterpreterRuntime37throw_illegal_monitor_state_exceptionEP10JavaThread - mov r0, tmp_yyy - ASSERT_STACK_CACHED - bl _ZN10HandleMarkD1Ev - ldr r3, [istate, #ISTATE_THREAD] - add r0, except_sp, #EXCEPTION_HANDLE3 - ldr r1, [r3, #4] - bl HandleC - ldr r2, [except_sp, #EXCEPTION_HANDLE3] - ldr r0, [istate, #ISTATE_THREAD] - str r2, [except_sp, #EXCEPTION_EXCEPTION2] - bl _ZN12ThreadShadow23clear_pending_exceptionEv - ldr r0, [istate, #ISTATE_THREAD] - b .handle_exception_24 - -#ifdef FASTPATH_ENTRY + bl Helper_RaiseIllegalMonitorException + ldmia arm_sp!, {r4, pc} + + ALIGN_CODE +accessor_entry: + b slow_accessor_entry ALIGN_CODE -fast_accessor_entry: - ldr ip, [dispatch, #SafePointSynchronize_state_Address-XXX] - ldr r3, [tmp2, #8] - ldr ip, [ip, #0] - ldrb r2, [r3, #50] - ldrb r3, [r3, #51] - cmp ip, #0 - ldr ip, [tmp2, #12] - bne fast_normal_entry - ldr ip, [ip, #12] - - DISPATCH_START 3 - - orr r2, r2, r3, lsl #8 @ r2 = index - add r3, ip, #16 - ldr r2, [r3, r2, lsl #4]! @ r3 = cache, r2 = flags - - DISPATCH_NEXT - - cmp r2, #opc_getfield << 16 - GET_STACK 0, r2 - bne fast_normal_entry - - cmp r2, #0 - beq fast_normal_entry - - - ldr lr, [r3, #12] - ldr r3, [r3, #8] - movs lr, lr, lsr #29 - bls .fast_accessor_non_w - - DISPATCH_NEXT - - ldr tmp1, [r2, r3] - - DISPATCH_NEXT - DISPATCH_NEXT - - PUT_STACK 0, tmp1 - - DISPATCH_FINISH +slow_accessor_entry: + USEC adrl ip, dispatch_init_adcon + USEC ldr r3, [ip] + USEC add r3, r3, ip + USEC ldr ip, [ip, #invocationlimit_adcon-dispatch_init_adcon] + USEC ldr ip, [r3, ip] + + USEC ldr r3, [r0, #METHOD_INVOCATIONCOUNTER] + USEC ldr ip, [ip, #0] + USEC add r3, r3, #INVOCATIONCOUNTER_COUNTINCREMENT + USEC str r3, [r0, #METHOD_INVOCATIONCOUNTER] + USEC cmp r3, ip + USEC bcs normal_entry + + ldr r1, [r0, #METHOD_CONSTMETHOD] + ldrb r3, [r1, #CONSTMETHOD_CODEOFFSET+2] + ldrb r1, [r1, #CONSTMETHOD_CODEOFFSET+3] + ldr ip, [r0, #METHOD_CONSTANTS] + ldr ip, [ip, #CONSTANTPOOL_CACHE] + orr r3, r3, r1, lsl #8 @ r3 = index + + add r1, ip, #CP_OFFSET + ldr r3, [r1, r3, lsl #4]! @ r1 = cache, r3 = flags + ldr ip, [r2, #THREAD_JAVA_SP] @ ip == stack + and r3, r3, #0x00ff0000 + cmp r3, #opc_getfield << 16 + ldr r3, [ip, #0] + bne normal_entry + + cmp r3, #0 + beq normal_entry + + ldr r0, [r1, #12] + ldr r1, [r1, #8] + movs r0, r0, lsr #29 + bls accessor_non_w + + ldr r0, [r3, r1] + str r0, [ip, #0] + bx lr .fast_accessor_non_w: bcs .fast_accessor_h @@ -5427,10 +3181,8 @@ PUSH tmp2 DISPATCH_FINISH -#endif // FASTPATH_ENTRY - div_zero_jpc_1: - sub jpc, jpc, #1 @ Point to idiv + sub jpc, jpc, #1 .lrem_0: .ldiv_0: divide_by_zero_exception: @@ -5465,30 +3217,12 @@ sub jpc, jpc, #1 array_bound_exception_jpc_0: array_bounds_exception: - adr r1, percent_d_str - sub arm_sp, arm_sp, #16 - add r0, arm_sp, #4 - bl sprintf - add r1, arm_sp, #4 - mov r0, #VMSYMBOLS_ArrayIndexOutOfBounds - str r1, [arm_sp] - ldr r3, [dispatch, #VmSymbols_symbols_Address-XXX] - ldr r3, [r3, r0, lsl #2] - ldr r0, [istate, #ISTATE_THREAD] DECACHE_JPC DECACHE_STACK - mov ip, #_thread_in_vm - str ip, [r0, #THREAD_STATE] - mov r2, #99 - adrl r1, bytecode_interpreter_str - bl _ZN10Exceptions10_throw_msgEP6ThreadPKciP13symbolOopDescS3_ - add r0, istate, #ISTATE_THREAD - bl ThreadInVMfromJavaD - add arm_sp, arm_sp, #16 + mov r1, r2 + ldr r0, [istate, #ISTATE_THREAD] + bl Helper_RaiseArrayBoundException b handle_exception_with_bcp -percent_d_str: - .ascii "%d\000" - ALIGN_WORD #ifndef HW_NULL_PTR_CHECK null_ptr_exception_jpc_5: @@ -5780,8 +3514,6 @@ bpl .dadd_exit b .return_double_NaN -@ ECN: load 1st arg off stack and do a reverse subtract -@ ECN: We want TOSM1 - TOS, but args end up in wrong order so do rsb @ --- do_dsub_itos ------------------------------------------------- Opcode dsub POP al, ah, bl, bh @@ -6189,7 +3921,6 @@ orr ah, ah, al, LSR ul @ put in high end of low word mov al, tl -@ ECN: Reload tmp mov tmp, #0x7f00000 orr tmp, tmp, #0x00f0000 @@ -6228,7 +3959,6 @@ orr bh, bh, bl, LSR ul @ put in high end of low word mov bl, tl -@ ECN: Reload tmp mov tmp, #0x7f00000 orr tmp, tmp, #0x00f0000 @@ -6293,9 +4023,9 @@ strb r3, [r2, #0] adrl r3, main_dispatch_table #ifdef HW_FP - ldr r0, [ip, #VFP_Flag-XXX] - cmp r0, #0 - bne 2f + ldr r0, [ip, #CPUInfo-XXX] + tst r0, #ARCH_VFP + beq 2f #endif mov r2, #256 1: @@ -6303,7 +4033,8 @@ str r1, [ip], #4 subs r2, r2, #1 bne 1b - bx lr + sub ip, ip, #4 * 256 + b 4f @ No HW FP - must update the table from a combination main_dispatch_table and @ vfp_table. Previously this updated from main_dispatch_table first, and then @@ -6327,9 +4058,23 @@ add r2, r2, #1 cmp r2, #256 bcc 3b + sub ip, ip, #4 * 256 ldmia arm_sp!, {r4, lr} #endif // HW_FP + +4: + ldr r0, [ip, #CPUInfo-XXX] + tst r0, #ARCH_CLZ + beq 5f + + adrl r0, do_idiv_clz + str r0, [ip, #opc_idiv * 4] + adrl r0, do_irem_clz + str r0, [ip, #opc_irem * 4] + +5: #endif // NOTICE_SAFEPOINTS + bx lr @ --- notice_safepoints --------------------------------------------------------------------------- @@ -6384,6 +4129,9 @@ subs r1, r1, #1 bne 2b + bl hwcap + str r0, [r4, #CPUInfo-XXX] + #ifdef USE_COMPILER #define NPROCESSORS_CONF 83 @@ -6403,51 +4151,18 @@ ldr r1, [r4, #CompileThreshold_Address-XXX] str r0, [r1] - #endif // USE_COMPILER - ldmfd sp!, {r4, lr} +#ifdef THUMB2EE + ldr r1, [r4, #CPUInfo-XXX] + tst r1, #ARCH_THUMBEE + blne Thumb2_Initialize +#endif #ifdef HW_FP -vfp_init: - stmfd sp!, {r4, r5, lr} - sub sp, sp, #132 - mov r4, #0 - adr r0, proc_self_auxv - mov r1, #0 - bl open - subs r5, r0, #0 - blt .exit_vfp_init -.vfp_init_read_loop: - mov r2, #128 - mov r0, r5 - mov r1, sp - bl read - mov r2, sp - mov r3, r0, lsr #3 - b .vfp_init_1 -.vfp_init_vec_loop: - ldmia r2!, {r1, ip} - cmp r1, #0 - beq .fini_vfp_init - cmp r1, #16 - bne .vfp_init_1 - tst ip, #64 - movne r4, #1 - bne .fini_vfp_init -.vfp_init_1: - subs r3, r3, #1 - bpl .vfp_init_vec_loop - cmp r0, #128 - beq .vfp_init_read_loop -.fini_vfp_init: - mov r0, r5 - bl close -.exit_vfp_init: - movs r0, r4 - add sp, sp, #132 - ldmfd sp!, {r4, r5, lr} - bxne lr @ We have HW FP - just exit + ldr r0, [r4, #CPUInfo-XXX] + tst r0, #ARCH_VFP + bne 4f @ No HW FP - replace the HW FP entries with SW entries update_vfp_table: @@ -6456,17 +4171,26 @@ ldm ip, {r2, r3} add r2, r2, ip add ip, r3, r2 - mov r1, #1 - str r1, [ip, #VFP_Flag-XXX] .update_vfp_loop: ldr r1, [r0], #4 cmp r1, #0 ldrne r2, [r0], #4 strne r2, [ip, r1, lsl #2] bne .update_vfp_loop +4: #endif // HW_FP - bx lr + ldr r0, [r4, #CPUInfo-XXX] + tst r0, #ARCH_CLZ + beq 5f + + adrl r0, do_idiv_clz + str r0, [r4, #opc_idiv * 4] + adrl r0, do_irem_clz + str r0, [r4, #opc_irem * 4] + +5: + ldmia sp!, {r4, pc} #ifdef HW_FP vfp_table: @@ -6483,13 +4207,15 @@ .word opc_dcmpl, do_dcmpl .word opc_dcmpg, do_dcmpg .word 0 - -proc_self_auxv: - .ascii "/proc/self/auxv\000" - .align 2 - #endif // HW_FP +load_dispatch: + adrl ip, dispatch_init_adcon + ldm ip, {r0, r1} + add r0, r0, ip + add dispatch, r1, r0 + mov pc, lr + ALIGN_DATA dispatch_init_adcon: .word _GLOBAL_OFFSET_TABLE_-dispatch_init_adcon, opclabels_data(GOTOFF) @@ -6506,6 +4232,7 @@ .word PrintCommandLineFlags(GOT) .word _ZN11JvmtiExport28_can_post_interpreter_eventsE(GOT) .word UseCompiler(GOT) +invocationlimit_adcon: .word _ZN17InvocationCounter26InterpreterInvocationLimitE(GOT) .word CompileThreshold(GOT) .word BackgroundCompilation(GOT) @@ -6516,8 +4243,6 @@ main_dispatch_table: MAIN_DISPATCH_TABLE -@ ECN: Strange logic here! We don't need the safe_dispatch_table if NOTICE_SAFEPOINTS is -@ disabled because in this case the main_dispatch_table must be safepoint safe. #ifdef NOTICE_SAFEPOINTS safe_dispatch_table: .word do_nop @@ -6780,19 +4505,1717 @@ SUB_DISPATCH_TABLES + .arch armv7-a + + ALIGN_CODE + .global Thumb2_stubs +Thumb2_stubs: + .global Thumb2_idiv_stub +Thumb2_idiv_stub: +int_div: + cmp r1, #0x21 + adr r3, 1f + eor r12, r0, r1 + ldrcc pc, [r3, r1, lsl #2] + rsblt r1, r1, #0 + subs r2, r1, #1 + beq 2f + movs r3, r0 + rsbmi r3, r0, #0 + cmp r3, r1 + bls 3f + tst r1, r2 + beq 4f + clz r2, r3 + clz r0, r1 + sub r2, r0, r2 + rsbs r2, r2, #31 + add r2, r2, r2, lsl #1 + mov r0, #0 + add pc, pc, r2, lsl #2 + mov r0, #0 + cmp r3, r1, lsl #31 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #31 + cmp r3, r1, lsl #30 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #30 + cmp r3, r1, lsl #29 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #29 + cmp r3, r1, lsl #28 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #28 + cmp r3, r1, lsl #27 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #27 + cmp r3, r1, lsl #26 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #26 + cmp r3, r1, lsl #25 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #25 + cmp r3, r1, lsl #24 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #24 + cmp r3, r1, lsl #23 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #23 + cmp r3, r1, lsl #22 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #22 + cmp r3, r1, lsl #21 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #21 + cmp r3, r1, lsl #20 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #20 + cmp r3, r1, lsl #19 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #19 + cmp r3, r1, lsl #18 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #18 + cmp r3, r1, lsl #17 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #17 + cmp r3, r1, lsl #16 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #16 + cmp r3, r1, lsl #15 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #15 + cmp r3, r1, lsl #14 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #14 + cmp r3, r1, lsl #13 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #13 + cmp r3, r1, lsl #12 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #12 + cmp r3, r1, lsl #11 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #11 + cmp r3, r1, lsl #10 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #10 + cmp r3, r1, lsl #9 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #9 + cmp r3, r1, lsl #8 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #8 + cmp r3, r1, lsl #7 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #7 + cmp r3, r1, lsl #6 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #6 + cmp r3, r1, lsl #5 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #5 + cmp r3, r1, lsl #4 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #4 + cmp r3, r1, lsl #3 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #3 + cmp r3, r1, lsl #2 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #2 + cmp r3, r1, lsl #1 + adc r0, r0, r0 + subcs r3, r3, r1, lsl #1 + cmp r3, r1 + adc r0, r0, r0 + subcs r3, r3, r1 + cmp r12, #0 + rsbmi r0, r0, #0 + bx lr +2: + teq r12, r0 + rsbmi r0, r0, #0 + bx lr +3: + movcc r0, #0 + asreq r0, r12, #31 + orreq r0, r0, #1 + bx lr +4: + clz r2, r1 + rsb r2, r2, #31 + cmp r12, #0 + lsr r0, r3, r2 + rsbmi r0, r0, #0 + bx lr +1: + .word Thumb2_DivZero_Handler + .word jdiv_1 + .word jdiv_2 + .word jdiv_3 + .word jdiv_4 + .word jdiv_5 + .word jdiv_6 + .word jdiv_7 + .word jdiv_8 + .word jdiv_9 + .word jdiv_10 + .word jdiv_11 + .word jdiv_12 + .word jdiv_13 + .word jdiv_14 + .word jdiv_15 + .word jdiv_16 + .word jdiv_17 + .word jdiv_18 + .word jdiv_19 + .word jdiv_20 + .word jdiv_21 + .word jdiv_22 + .word jdiv_23 + .word jdiv_24 + .word jdiv_25 + .word jdiv_26 + .word jdiv_27 + .word jdiv_28 + .word jdiv_29 + .word jdiv_30 + .word jdiv_31 + .word jdiv_32 + ALIGN_CODE + .global Thumb2_irem_stub +Thumb2_irem_stub: +int_rem: + cmp r1, #0x21 + adr r3, 1f + ldrcc pc, [r3, r1, lsl #2] + rsblt r1, r1, #0 + subs r2, r1, #1 + beq 2f + movs r12, r0 + rsbmi r0, r0, #0 + cmp r0, r1 + bls 3f + tst r1, r2 + beq 4f + clz r2, r0 + clz r3, r1 + sub r2, r3, r2 + rsbs r2, r2, #31 + add pc, pc, r2, lsl #3 + mov r3, #0 + cmp r0, r1, lsl #31 + subcs r0, r0, r1, lsl #31 + cmp r0, r1, lsl #30 + subcs r0, r0, r1, lsl #30 + cmp r0, r1, lsl #29 + subcs r0, r0, r1, lsl #29 + cmp r0, r1, lsl #28 + subcs r0, r0, r1, lsl #28 + cmp r0, r1, lsl #27 + subcs r0, r0, r1, lsl #27 + cmp r0, r1, lsl #26 + subcs r0, r0, r1, lsl #26 + cmp r0, r1, lsl #25 + subcs r0, r0, r1, lsl #25 + cmp r0, r1, lsl #24 + subcs r0, r0, r1, lsl #24 + cmp r0, r1, lsl #23 + subcs r0, r0, r1, lsl #23 + cmp r0, r1, lsl #22 + subcs r0, r0, r1, lsl #22 + cmp r0, r1, lsl #21 + subcs r0, r0, r1, lsl #21 + cmp r0, r1, lsl #20 + subcs r0, r0, r1, lsl #20 + cmp r0, r1, lsl #19 + subcs r0, r0, r1, lsl #19 + cmp r0, r1, lsl #18 + subcs r0, r0, r1, lsl #18 + cmp r0, r1, lsl #17 + subcs r0, r0, r1, lsl #17 + cmp r0, r1, lsl #16 + subcs r0, r0, r1, lsl #16 + cmp r0, r1, lsl #15 + subcs r0, r0, r1, lsl #15 + cmp r0, r1, lsl #14 + subcs r0, r0, r1, lsl #14 + cmp r0, r1, lsl #13 + subcs r0, r0, r1, lsl #13 + cmp r0, r1, lsl #12 + subcs r0, r0, r1, lsl #12 + cmp r0, r1, lsl #11 + subcs r0, r0, r1, lsl #11 + cmp r0, r1, lsl #10 + subcs r0, r0, r1, lsl #10 + cmp r0, r1, lsl #9 + subcs r0, r0, r1, lsl #9 + cmp r0, r1, lsl #8 + subcs r0, r0, r1, lsl #8 + cmp r0, r1, lsl #7 + subcs r0, r0, r1, lsl #7 + cmp r0, r1, lsl #6 + subcs r0, r0, r1, lsl #6 + cmp r0, r1, lsl #5 + subcs r0, r0, r1, lsl #5 + cmp r0, r1, lsl #4 + subcs r0, r0, r1, lsl #4 + cmp r0, r1, lsl #3 + subcs r0, r0, r1, lsl #3 + cmp r0, r1, lsl #2 + subcs r0, r0, r1, lsl #2 + cmp r0, r1, lsl #1 + subcs r0, r0, r1, lsl #1 + cmp r0, r1 + subcs r0, r0, r1 + cmp r12, #0 + rsbmi r0, r0, #0 + bx lr +2: + mov r0, #0 + bx lr +3: + moveq r0, #0 + cmp r12, #0 + rsbmi r0, r0, #0 + bx lr +4: + and r0, r0, r2 + cmp r12, #0 + rsbmi r0, r0, #0 + bx lr +1: + .word Thumb2_DivZero_Handler + .word jrem_1 + .word jrem_2 + .word jrem_3 + .word jrem_4 + .word jrem_5 + .word jrem_6 + .word jrem_7 + .word jrem_8 + .word jrem_9 + .word jrem_10 + .word jrem_11 + .word jrem_12 + .word jrem_13 + .word jrem_14 + .word jrem_15 + .word jrem_16 + .word jrem_17 + .word jrem_18 + .word jrem_19 + .word jrem_20 + .word jrem_21 + .word jrem_22 + .word jrem_23 + .word jrem_24 + .word jrem_25 + .word jrem_26 + .word jrem_27 + .word jrem_28 + .word jrem_29 + .word jrem_30 + .word jrem_31 + .word jrem_32 + +#ifdef THUMB2EE +@ R0 = BCI +@ R1 = index +#define Rthread r9 + .global Thumb2_invokeinterface_stub +Thumb2_invokeinterface_stub: + stmdb sp!, {ip, lr} + ldr ip, [istate, #ISTATE_METHOD] + sub stack, stack, #4 + ldr r2, [istate, #ISTATE_CONSTANTS] + ldr ip, [ip, #METHOD_CONSTMETHOD] + DECACHE_STACK + add jpc, ip, r0 + + add r0, r2, r1, lsl #4 + DECACHE_JPC + + ldr r2, [r0, #CP_OFFSET] + and r2, r2, #0x00ff0000 + cmp r2, #opc_invokeinterface << 16 + bne istub_resolve +2: + ldr r3, [r0, #CP_OFFSET+12] + and r2, r3, #255 + ldr r2, [stack, r2, lsl #2] + cmp r2, #0 + beq istub_null_ptr_exception + ldr tmp2, [r2, #4] @ rcvr->klass() + tst r3, #flag_methodInterface + bne istub_methodInterface + + ldr lr, [r0, #CP_OFFSET+4] @ lr = iclass + + add r1, tmp2, #INSTANCEKLASS_VTABLE_OFFSET + ldr r2, [tmp2, #KLASS_PART+INSTANCEKLASS_VTABLE_LEN] + ldr ip, [tmp2, #KLASS_PART+INSTANCEKLASS_ITABLE_LEN] + add r2, r2, #1 + bic r2, r2, #1 + + add r1, r1, r2, lsl #2 + + mov r2, #0 +1: + cmp r2, ip + beq istub_incompatibleclass_exception + ldr r3, [r1], #8 + add r2, r2, #1 + cmp lr, r3 + bne 1b + + ldr r3, [r0, #CP_OFFSET+8] + ldr r2, [r1, #-4] + add r3, tmp2, r3, lsl #2 + ldr tmp2, [r3, r2] + cmp tmp2, #0 + beq istub_abstractmethod_exception +istub_invoke: + ldr ip, [tmp2, #METHOD_FROM_INTERPRETED] + mov r1, #0 + str ip, [istate, #36] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + + add stack, stack, #4 + str stack, [Rthread, #THREAD_JAVA_SP] + + ldr r3, [ip] + + mov r0, tmp2 + mov r1, ip +#ifndef SHARK + add r3, r3, #CODE_ALIGN_SIZE +#endif + mov r2, Rthread + blx r3 + + ldr Rthread, [istate, #ISTATE_THREAD] + + ldr stack, [Rthread, #THREAD_JAVA_SP] + ldr r2, [istate, #ISTATE_STACK_LIMIT] + + ldr r1, [Rthread, #THREAD_TOP_ZERO_FRAME] + add r2, r2, #4 + str r2, [Rthread, #THREAD_JAVA_SP] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + ldr r3, [Rthread, #4] + cmp r3, #0 + bne istub_exception + ldmia sp!, {ip, pc} + +istub_methodInterface: + tst r3, #flag_vfinalMethod + ldrne tmp2, [r0, #CP_OFFSET+8] + bne istub_invoke + ldr r1, [r0, #CP_OFFSET+8] + add r3, tmp2, r1, lsl #2 + ldr tmp2, [r3, #INSTANCEKLASS_VTABLE_OFFSET] + b istub_invoke + +istub_resolve: + mov tmp2, r1 + mov r1, #opc_invokeinterface + ldr r0, [istate, #ISTATE_THREAD] + ldr ip, resolve_invoke_adcon + blx ip + ldr r3, [Rthread, #4] + ldr r2, [istate, #ISTATE_CONSTANTS] + cmp r3, #0 + bne istub_exception + add r0, r2, tmp2, lsl #4 @ r1 = cache + b 2b + +istub_exception: + ldmia sp!, {ip, lr} + ldr ip, handle_exception_adcon + bx ip + +istub_null_ptr_exception: + mov r0, #VMSYMBOLS_NullPointerException + b 3f +istub_abstractmethod_exception: + mov r0, #VMSYMBOLS_AbstractMethodError + b 3f +istub_incompatibleclass_exception: + mov r0, #VMSYMBOLS_IncompatibleClassChangeError +3: + CACHE_JPC + ldmia sp!, {ip, lr} + ldr ip, raise_exception_adcon + bx ip + +resolve_invoke_adcon: + .word _ZN18InterpreterRuntime14resolve_invokeEP10JavaThreadN9Bytecodes4CodeE +resolve_get_put_adcon: + .word _ZN18InterpreterRuntime15resolve_get_putEP10JavaThreadN9Bytecodes4CodeE +handle_exception_adcon: + .word handle_exception_with_bcp +raise_exception_adcon: + .word raise_exception +helper_aputfield_adcon: + .word Helper_aputfield + +@ R0 = BCI +@ R1 = index + .global Thumb2_invokevirtual_stub +Thumb2_invokevirtual_stub: + stmdb sp!, {ip, lr} + ldr ip, [istate, #ISTATE_METHOD] + sub stack, stack, #4 + ldr r2, [istate, #ISTATE_CONSTANTS] + ldr ip, [ip, #METHOD_CONSTMETHOD] + DECACHE_STACK + add jpc, ip, r0 + + add r0, r2, r1, lsl #4 + DECACHE_JPC + + ldr r2, [r0, #CP_OFFSET] + and r2, r2, #0xff000000 + cmp r2, #opc_invokevirtual << 24 + bne ivstub_resolve +2: + + ldr r3, [r0, #CP_OFFSET+12] + and r2, r3, #255 + ldr r2, [stack, r2, asl #2] + cmp r2, #0 + beq istub_null_ptr_exception + + ldr tmp2, [r0, #CP_OFFSET+8] + tst r3, #flag_vfinalMethod + bne 1f + + ldr r3, [r2, #4] + add r3, r3, tmp2, lsl #2 + ldr tmp2, [r3, #INSTANCEKLASS_VTABLE_OFFSET] +1: + mov r1, #0 + ldr ip, [tmp2, #METHOD_FROM_INTERPRETED] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + str ip, [istate, #36] + + add stack, stack, #4 + str stack, [Rthread, #THREAD_JAVA_SP] + + ldr r3, [ip, #0] + + mov r0, tmp2 + mov r1, ip +#ifndef SHARK + add r3, r3, #CODE_ALIGN_SIZE +#endif + mov r2, Rthread + blx r3 + + ldr Rthread, [istate, #ISTATE_THREAD] + + ldr stack, [Rthread, #THREAD_JAVA_SP] + ldr r2, [istate, #ISTATE_STACK_LIMIT] + + ldr r1, [Rthread, #THREAD_TOP_ZERO_FRAME] + add r2, r2, #4 + str r2, [Rthread, #THREAD_JAVA_SP] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + ldr r3, [Rthread, #4] + cmp r3, #0 + bne istub_exception + ldmia sp!, {ip, pc} + +ivstub_resolve: + mov tmp2, r1 + mov r1, #opc_invokevirtual + ldr r0, [istate, #ISTATE_THREAD] + ldr ip, resolve_invoke_adcon + blx ip + ldr r3, [Rthread, #4] + ldr r2, [istate, #ISTATE_CONSTANTS] + cmp r3, #0 + bne istub_exception + add r0, r2, tmp2, lsl #4 @ r1 = cache + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_invokestatic_stub +Thumb2_invokestatic_stub: + stmdb sp!, {ip, lr} + ldr ip, [istate, #ISTATE_METHOD] + sub stack, stack, #4 + ldr r2, [istate, #ISTATE_CONSTANTS] + ldr ip, [ip, #METHOD_CONSTMETHOD] + DECACHE_STACK + add jpc, ip, r0 + + add r0, r2, r1, lsl #4 + DECACHE_JPC + + ldr r2, [r0, #CP_OFFSET] + and r2, r2, #0x00ff0000 + cmp r2, #opc_invokestatic << 16 + bne isstub_resolve +2: + ldr tmp2, [r0, #CP_OFFSET+4] + mov r1, #0 + ldr ip, [tmp2, #METHOD_FROM_INTERPRETED] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + str ip, [istate, #36] + + add stack, stack, #4 + str stack, [Rthread, #THREAD_JAVA_SP] + + ldr r3, [ip, #0] + + mov r0, tmp2 + mov r1, ip +#ifndef SHARK + add r3, r3, #CODE_ALIGN_SIZE +#endif + mov r2, Rthread + blx r3 + + ldr Rthread, [istate, #ISTATE_THREAD] + + ldr stack, [Rthread, #THREAD_JAVA_SP] + ldr r2, [istate, #ISTATE_STACK_LIMIT] + + ldr r1, [Rthread, #THREAD_TOP_ZERO_FRAME] + add r2, r2, #4 + str r2, [Rthread, #THREAD_JAVA_SP] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + ldr r3, [Rthread, #4] + cmp r3, #0 + bne istub_exception + ldmia sp!, {ip, pc} + +isstub_resolve: + mov tmp2, r1 + mov r1, #opc_invokestatic + ldr r0, [istate, #ISTATE_THREAD] + ldr ip, resolve_invoke_adcon + blx ip + ldr r3, [Rthread, #4] + ldr r2, [istate, #ISTATE_CONSTANTS] + cmp r3, #0 + bne istub_exception + add r0, r2, tmp2, lsl #4 @ r1 = cache + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_invokespecial_stub +Thumb2_invokespecial_stub: + stmdb sp!, {ip, lr} + ldr ip, [istate, #ISTATE_METHOD] + sub stack, stack, #4 + ldr r2, [istate, #ISTATE_CONSTANTS] + ldr ip, [ip, #METHOD_CONSTMETHOD] + DECACHE_STACK + add jpc, ip, r0 + + add r0, r2, r1, lsl #4 + DECACHE_JPC + + ldr r2, [r0, #CP_OFFSET] + and r2, r2, #0x00ff0000 + cmp r2, #opc_invokespecial << 16 + bne ispstub_resolve +2: + ldr r3, [r0, #CP_OFFSET+12] + and r3, r3, #255 + ldr r2, [stack, r3, asl #2] + cmp r2, #0 + beq istub_null_ptr_exception + + ldr tmp2, [r0, #CP_OFFSET+4] + mov r1, #0 + ldr ip, [tmp2, #METHOD_FROM_INTERPRETED] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + str ip, [istate, #36] + + add stack, stack, #4 + str stack, [Rthread, #THREAD_JAVA_SP] + + ldr r3, [ip, #0] + + mov r0, tmp2 + mov r1, ip +#ifndef SHARK + add r3, r3, #CODE_ALIGN_SIZE +#endif + mov r2, Rthread + blx r3 + + ldr Rthread, [istate, #ISTATE_THREAD] + + ldr stack, [Rthread, #THREAD_JAVA_SP] + ldr r2, [istate, #ISTATE_STACK_LIMIT] + + ldr r1, [Rthread, #THREAD_TOP_ZERO_FRAME] + add r2, r2, #4 + str r2, [Rthread, #THREAD_JAVA_SP] + str r1, [Rthread, #THREAD_LAST_JAVA_SP] + ldr r3, [Rthread, #4] + cmp r3, #0 + bne istub_exception + ldmia sp!, {ip, pc} + +ispstub_resolve: + mov tmp2, r1 + mov r1, #opc_invokespecial + ldr r0, [istate, #ISTATE_THREAD] + ldr ip, resolve_invoke_adcon + blx ip + ldr r3, [Rthread, #4] + ldr r2, [istate, #ISTATE_CONSTANTS] + cmp r3, #0 + bne istub_exception + add r0, r2, tmp2, lsl #4 @ r1 = cache + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_getfield_word_stub +Thumb2_getfield_word_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getfield << 16 + bne 1f +2: + ldr r3, [stack], #4 @ POP r3 + ldr ip, [r2, #CP_OFFSET+8] + cmp r3, #0 + beq field_null_ptr_exception + + ldr r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getfield_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_getfield_sh_stub +Thumb2_getfield_sh_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getfield << 16 + bne 1f +2: + ldr r3, [stack], #4 @ POP r3 + ldr ip, [r2, #CP_OFFSET+8] + cmp r3, #0 + beq field_null_ptr_exception + + ldrsh r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getfield_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_getfield_h_stub +Thumb2_getfield_h_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getfield << 16 + bne 1f +2: + ldr r3, [stack], #4 @ POP r3 + ldr ip, [r2, #CP_OFFSET+8] + cmp r3, #0 + beq field_null_ptr_exception + + ldrh r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getfield_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_getfield_sb_stub +Thumb2_getfield_sb_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getfield << 16 + bne 1f +2: + ldr r3, [stack], #4 @ POP r3 + ldr ip, [r2, #CP_OFFSET+8] + cmp r3, #0 + beq field_null_ptr_exception + + ldrsb r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getfield_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_getfield_dw_stub +Thumb2_getfield_dw_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getfield << 16 + bne 1f +2: + ldr r3, [stack], #4 @ POP r3 + ldr ip, [r2, #CP_OFFSET+8] + cmp r3, #0 + beq field_null_ptr_exception + + ldrd r2, r3, [r3, ip] + stmdb stack!, {r2, r3} @ PUSH r2, r3 + bx lr +1: + mov ip, lr + bl getfield_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index +putstatic_stub_unresolved: + mov r2, #opc_putstatic + b field_stub_unresolved +getstatic_stub_unresolved: + mov r2, #opc_getstatic + b field_stub_unresolved +putfield_stub_unresolved: + mov r2, #opc_putfield + b field_stub_unresolved +getfield_stub_unresolved: + mov r2, #opc_getfield +field_stub_unresolved: + stmdb sp!, {r0, r1, ip, lr} + ldr ip, [istate, #ISTATE_METHOD] + sub r3, stack, #4 + ldr ip, [ip, #METHOD_CONSTMETHOD] + str r3, [istate, #ISTATE_STACK] @ DECACHE_STACK + add r3, ip, r0 + str r3, [istate, #ISTATE_BCP] @ DECACHE_JPC + ldr ip, resolve_get_put_adcon + mov r1, r2 + ldr r0, [istate, #ISTATE_THREAD] + blx ip + ldmia sp!, {r0, r1, ip, lr} + ldr r3, [Rthread, #4] + ldr r2, [istate, #ISTATE_CONSTANTS] + cmp r3, #0 + bne field_exception + add r2, r2, r1, lsl #4 + bx lr + +field_null_ptr_exception: + ldr ip, [istate, #ISTATE_METHOD] + ldr ip, [ip, #METHOD_CONSTMETHOD] + add jpc, ip, r0 + mov r0, #VMSYMBOLS_NullPointerException + ldr ip, raise_exception_adcon + bx ip + +field_exception: + ldr ip, handle_exception_adcon + bx ip + +@ R0 = BCI +@ R1 = index + .global Thumb2_putfield_word_stub +Thumb2_putfield_word_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putfield << 24 + bne 1f +2: + ldr ip, [r2, #CP_OFFSET+8] + ldmia stack!, {r2, r3} @ r2 = value, r3 = obj + cmp r3, #0 + beq field_null_ptr_exception + + str r2, [r3, ip] + bx lr +1: + mov ip, lr + bl putfield_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_putfield_h_stub +Thumb2_putfield_h_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putfield << 24 + bne 1f +2: + ldr ip, [r2, #CP_OFFSET+8] + ldmia stack!, {r2, r3} @ r2 = value, r3 = obj + cmp r3, #0 + beq field_null_ptr_exception + + strh r2, [r3, ip] + bx lr +1: + mov ip, lr + bl putfield_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_putfield_b_stub +Thumb2_putfield_b_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putfield << 24 + bne 1f +2: + ldr ip, [r2, #CP_OFFSET+8] + ldmia stack!, {r2, r3} @ r2 = value, r3 = obj + cmp r3, #0 + beq field_null_ptr_exception + + strb r2, [r3, ip] + bx lr +1: + mov ip, lr + bl putfield_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_putfield_a_stub +Thumb2_putfield_a_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putfield << 24 + bne 1f +2: + ldr ip, [r2, #CP_OFFSET+8] + ldmia stack!, {r2, r3} @ r2 = value, r3 = obj + cmp r3, #0 + beq field_null_ptr_exception + + str r2, [r3, ip] + ldr ip, helper_aputfield_adcon + mov r0, r3 + bx ip +1: + mov ip, lr + bl putfield_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_putfield_dw_stub +Thumb2_putfield_dw_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putfield << 24 + bne 1f +2: + ldr r1, [r2, #CP_OFFSET+8] + ldmia stack!, {r2, r3, ip} @ r2,r3 = value, ip = obj + cmp ip, #0 + beq field_null_ptr_exception + + strd r2,r3, [ip, r1] + bx lr +1: + mov ip, lr + bl putfield_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_getstatic_word_stub +Thumb2_getstatic_word_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getstatic << 16 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + + ldr r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getstatic_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_getstatic_h_stub +Thumb2_getstatic_h_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getstatic << 16 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + + ldrh r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getstatic_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_getstatic_sh_stub +Thumb2_getstatic_sh_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getstatic << 16 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + + ldrsh r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getstatic_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_getstatic_sb_stub +Thumb2_getstatic_sb_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getstatic << 16 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + + ldrsb r3, [r3, ip] + str r3, [stack, #-4]! @ PUSH r3 + bx lr +1: + mov ip, lr + bl getstatic_stub_unresolved + mov lr, ip + b 2b + + .global Thumb2_getstatic_dw_stub +Thumb2_getstatic_dw_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0x00ff0000 + cmp r3, #opc_getstatic << 16 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + + ldrd r2, r3, [r3, ip] + stmdb stack!, {r2, r3} @ PUSH r2, r3 + bx lr +1: + mov ip, lr + bl getstatic_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_putstatic_word_stub +Thumb2_putstatic_word_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putstatic << 24 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + ldr r2, [stack], #4 @ POP r2 + + str r2, [r3, ip] + bx lr +1: + mov ip, lr + bl putstatic_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_putstatic_h_stub +Thumb2_putstatic_h_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putstatic << 24 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + ldr r2, [stack], #4 @ POP r2 + + strh r2, [r3, ip] + bx lr +1: + mov ip, lr + bl putstatic_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_putstatic_b_stub +Thumb2_putstatic_b_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putstatic << 24 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + ldr r2, [stack], #4 @ POP r2 + + strb r2, [r3, ip] + bx lr +1: + mov ip, lr + bl putstatic_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_putstatic_dw_stub +Thumb2_putstatic_dw_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putstatic << 24 + bne 1f +2: + ldr r1, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + ldmia stack!, {r2, r3} + + strd r2,r3, [r1, ip] + bx lr +1: + mov ip, lr + bl putstatic_stub_unresolved + mov lr, ip + b 2b + +@ R0 = BCI +@ R1 = index + .global Thumb2_putstatic_a_stub +Thumb2_putstatic_a_stub: + ldr r2, [istate, #ISTATE_CONSTANTS] + add r2, r2, r1, lsl #4 + ldr r3, [r2, #CP_OFFSET] + and r3, r3, #0xff000000 + cmp r3, #opc_putstatic << 24 + bne 1f +2: + ldr r3, [r2, #CP_OFFSET+4] + ldr ip, [r2, #CP_OFFSET+8] + ldr r2, [stack], #4 @ POP r2 + + str r2, [r3, ip] + ldr ip, helper_aputfield_adcon + mov r0, r3 + bx ip +1: + mov ip, lr + bl putstatic_stub_unresolved + mov lr, ip + b 2b + +#endif // THUMB2EE + + .global Thumb2_stubs_end +Thumb2_stubs_end: + + ALIGN_CODE +jdiv_1: + bx lr +jdiv_2: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 + bx lr +jdiv_24: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_12: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_6: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_3: + ldr r1, dc_3 + smull r3, r2, r0, r1 + sub r0, r2, r0, asr #31 + bx lr +jdiv_4: + mov r1, r0, asr #31 + add r0, r0, r1, lsr #30 + mov r0, r0, asr #2 + bx lr +jdiv_20: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_10: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_5: + ldr r1, dc_5 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #1 + bx lr +jdiv_28: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_14: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_7: + ldr r1, dc_7 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r0, r1, r3, asr #2 + bx lr +jdiv_8: + mov r1, r0, asr #31 + add r0, r0, r1, lsr #29 + mov r0, r0, asr #3 + bx lr +jdiv_18: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_9: + ldr r1, dc_9 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #1 + bx lr +jdiv_22: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_11: + ldr r1, dc_11 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #1 + bx lr +jdiv_26: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_13: + ldr r1, dc_13 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #2 + bx lr +jdiv_30: + add r0, r0, r0, lsr #31 + mov r0, r0, asr #1 +jdiv_15: + ldr r1, dc_15 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r0, r1, r3, asr #3 + bx lr +jdiv_16: + mov r1, r0, asr #31 + add r0, r0, r1, lsr #28 + mov r0, r0, asr #4 + bx lr +jdiv_17: + ldr r1, dc_17 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #3 + bx lr +jdiv_19: + ldr r1, dc_19 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #3 + bx lr +jdiv_21: + ldr r1, dc_21 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #2 + bx lr +jdiv_23: + ldr r1, dc_23 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r0, r1, r3, asr #4 + bx lr +jdiv_25: + ldr r1, dc_25 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #3 + bx lr +jdiv_27: + ldr r1, dc_27 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r0, r3, r2, asr #3 + bx lr +jdiv_29: + ldr r1, dc_29 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r0, r1, r3, asr #4 + bx lr +jdiv_31: + ldr r1, dc_31 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r0, r1, r3, asr #4 + bx lr +jdiv_32: + mov r1, r0, asr #31 + add r0, r0, r1, lsr #27 + mov r0, r0, asr #5 + bx lr +jrem_1: + mov r0, #0 + bx lr +jrem_2: + add r3, r0, r0, lsr #31 + mov r1, r3, asr #1 + sub r0, r0, r1, lsl #1 + bx lr +jrem_3: + ldr r1, dc_3 + smull r3, r2, r0, r1 + sub r1, r2, r0, asr #31 + add r3, r1, r1, lsl #1 + sub r0, r0, r3 + bx lr +jrem_4: + movs r3, r0 + addmi r3, r3, #3 + mov r1, r3, asr #2 + sub r0, r0, r1, lsl #2 + bx lr +jrem_5: + ldr r1, dc_5 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #1 + add r3, r1, r1, lsl #2 + sub r0, r0, r3 + bx lr +jrem_6: + ldr r1, dc_6 + smull r3, r2, r0, r1 + sub r1, r2, r0, asr #31 + add r3, r1, r1, lsl #1 + sub r0, r0, r3, lsl #1 + bx lr +jrem_7: + ldr r1, dc_7 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #2 + rsb r3, r1, r1, lsl #3 + sub r0, r0, r3 + bx lr +jrem_8: + movs r3, r0 + addmi r3, r3, #7 + mov r1, r3, asr #3 + sub r0, r0, r1, lsl #3 + bx lr +jrem_9: + ldr r1, dc_9 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #1 + add r3, r1, r1, lsl #3 + sub r0, r0, r3 + bx lr +jrem_10: + ldr r1, dc_10 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #2 + add r3, r1, r1, lsl #2 + sub r0, r0, r3, lsl #1 + bx lr +jrem_11: + ldr r1, dc_11 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #1 + add r3, r1, r1, lsl #2 + add r3, r1, r3, lsl #1 + sub r0, r0, r3 + bx lr +jrem_12: + ldr r1, dc_12 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #1 + add r3, r1, r1, lsl #1 + sub r0, r0, r3, lsl #2 + bx lr +jrem_13: + ldr r1, dc_13 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #2 + add r3, r1, r1, lsl #1 + add r3, r1, r3, lsl #2 + sub r0, r0, r3 + bx lr +jrem_14: + ldr r1, dc_14 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #3 + rsb r3, r1, r1, lsl #3 + sub r0, r0, r3, lsl #1 + bx lr +jrem_15: + ldr r1, dc_15 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #3 + rsb r3, r1, r1, lsl #4 + sub r0, r0, r3 + bx lr +jrem_16: + movs r3, r0 + addmi r3, r3, #15 + mov r1, r3, asr #4 + sub r0, r0, r1, lsl #4 + bx lr +jrem_17: + ldr r1, dc_17 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #3 + add r3, r1, r1, lsl #4 + sub r0, r0, r3 + bx lr +jrem_18: + ldr r1, dc_18 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #2 + add r3, r1, r1, lsl #3 + sub r0, r0, r3, lsl #1 + bx lr +jrem_19: + ldr r1, dc_19 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #3 + add r3, r1, r1, lsl #3 + add r3, r1, r3, lsl #1 + sub r0, r0, r3 + bx lr +jrem_20: + ldr r1, dc_20 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #3 + add r3, r1, r1, lsl #2 + sub r0, r0, r3, lsl #2 + bx lr +jrem_21: + ldr r1, dc_21 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #2 + add r3, r1, r1, lsl #1 + rsb r3, r3, r3, lsl #3 + sub r0, r0, r3 + bx lr +jrem_22: + ldr r1, dc_22 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #2 + add r3, r1, r1, lsl #2 + add r3, r1, r3, lsl #1 + sub r0, r0, r3, lsl #1 + bx lr +jrem_23: + ldr r1, dc_23 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #4 + add r3, r1, r1, lsl #1 + rsb r3, r1, r3, lsl #3 + sub r0, r0, r3 + bx lr +jrem_24: + ldr r1, dc_24 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #2 + add r3, r1, r1, lsl #1 + sub r0, r0, r3, lsl #3 + bx lr +jrem_25: + ldr r1, dc_25 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #3 + add r3, r1, r1, lsl #2 + add r3, r3, r3, lsl #2 + sub r0, r0, r3 + bx lr +jrem_26: + ldr r1, dc_26 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #3 + add r3, r1, r1, lsl #1 + add r3, r1, r3, lsl #2 + sub r0, r0, r3, lsl #1 + bx lr +jrem_27: + ldr r1, dc_27 + smull r3, r2, r0, r1 + mov r3, r0, asr #31 + rsb r1, r3, r2, asr #3 + add r3, r1, r1, lsl #1 + add r3, r3, r3, lsl #3 + sub r0, r0, r3 + bx lr +jrem_28: + ldr r1, dc_28 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #4 + rsb r3, r1, r1, lsl #3 + sub r0, r0, r3, lsl #2 + bx lr +jrem_29: + ldr r1, dc_29 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #4 + rsb r3, r1, r1, lsl #3 + add r3, r1, r3, lsl #2 + sub r0, r0, r3 + bx lr +jrem_30: + ldr r1, dc_30 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #4 + rsb r3, r1, r1, lsl #4 + sub r0, r0, r3, lsl #1 + bx lr +jrem_31: + ldr r1, dc_31 + smull r3, r2, r0, r1 + mov r1, r0, asr #31 + add r3, r0, r2 + rsb r1, r1, r3, asr #4 + rsb r3, r1, r1, lsl #5 + sub r0, r0, r3 + bx lr +jrem_32: + movs r3, r0 + addmi r3, r3, #31 + mov r1, r3, asr #5 + sub r0, r0, r1, lsl #5 + bx lr + ALIGN_DATA +dc_7: +dc_14: + .word 0x92492493 +dc_15: +dc_30: + .word 0x88888889 +dc_23: + .word 0xb21642c9 +dc_28: + .word 0x92492493 +dc_29: + .word 0x8d3dcb09 +dc_31: + .word 0x84210843 +dc_6: +dc_12: +dc_24: + .word 0x2aaaaaab +dc_19: + .word 0x6bca1af3 +dc_5: +dc_10: +dc_20: + .word 0x66666667 +dc_21: + .word 0x30c30c31 +dc_11: +dc_22: + .word 0x2e8ba2e9 +dc_26: +dc_13: + .word 0x4ec4ec4f +dc_25: + .word 0x51eb851f +dc_27: + .word 0x4bda12f7 +dc_3: + .word 0x55555556 +dc_17: + .word 0x78787879 +dc_9: +dc_18: + .word 0x38e38e39 + + .global Thumb2_DivZero_Handler +Thumb2_DivZero_Handler: + adrl r0, idiv_clz_ret + cmp r0, lr + addne r0, r0, #irem_clz_ret - idiv_clz_ret + cmpne r0, lr + beq divide_by_zero_exception + ldr r0, [istate, #ISTATE_METHOD] + ldr jpc, [r0, #METHOD_CONSTMETHOD] + add jpc, jpc, #CONSTMETHOD_CODEOFFSET + bl load_dispatch + b divide_by_zero_exception + +#ifdef THUMB2EE + + .global Thumb2_Handle_Exception + .global Thumb2_ArrayBounds_Handler + .global Thumb2_NullPtr_Handler +Thumb2_ArrayBounds_Handler: + ldr r0, [istate, #ISTATE_METHOD] + ldr jpc, [r0, #METHOD_CONSTMETHOD] + add jpc, jpc, #CONSTMETHOD_CODEOFFSET + bl load_dispatch + mov r0, #VMSYMBOLS_ArrayIndexOutOfBounds + b raise_exception +Thumb2_Handle_Exception: + ldr r0, [istate, #ISTATE_METHOD] + ldr jpc, [r0, #METHOD_CONSTMETHOD] + add jpc, jpc, #CONSTMETHOD_CODEOFFSET + bl load_dispatch + b handle_exception + + .global Thumb2_Exit_To_Interpreter +Thumb2_Exit_To_Interpreter: + bl load_dispatch + sub stack, stack, #4 + CACHE_CP + CACHE_LOCALS + DISPATCH 0 + +Thumb2_NullPtr_Handler: + ldr r0, [istate, #ISTATE_METHOD] + ldr jpc, [r0, #METHOD_CONSTMETHOD] + add jpc, jpc, #CONSTMETHOD_CODEOFFSET + bl load_dispatch + b null_ptr_exception + + .global Thumb2_Clear_Cache +Thumb2_Clear_Cache: + stmdb sp!, {r7} + mov r2, #0 + mov r7, #2 + orr r7, r7, #0xf0000 + svc 0 + ldmia sp!, {r7} + bx lr + +#endif // THUMB2EE + .section .init_array,"aw",%init_array .word bci_init(target1) .data + .global CPUInfo ALIGN_DATA -#ifdef CODETRACE -CodeTrace_Buffer_Base: - .space CODETRACE_BUFFER_SIZE -#endif .word 0, 0, 0, 0, 0, 0, 0, 0 .word 0, 0, 0, 0, 0 DispatchBreakPoint: .word 0 -VFP_Flag: .word 0 +CPUInfo: .word 0 CodeTrace_Idx: .word 0 UseOnStackReplacement_Address: .word 0 BackgroundCompilation_Address: .word 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ports/hotspot/src/cpu/zero/vm/thumb2.cpp Thu Jan 28 16:34:49 2010 +0000 @@ -0,0 +1,7141 @@ +#ifdef THUMB2EE + +#define T2EE_PRINT_COMPILATION +#define T2EE_PRINT_STATISTICS +//#define T2EE_PRINT_DISASS +#define T2EE_PRINT_REGUSAGE + +#ifdef T2EE_PRINT_COMPILATION +static char *t2ee_print_compilation; +#endif + +#ifdef T2EE_PRINT_STATISTICS +static char *t2ee_print_statistics; +#endif + +#ifdef T2EE_PRINT_DISASS +static char *t2ee_print_disass; +#endif + +#ifdef T2EE_PRINT_REGUSAGE +static char *t2ee_print_regusage; +#endif + +#define THUMB2_CODEBUF_SIZE (8 * 1024 * 1024) + +#include <sys/mman.h> + +#include "incls/_precompiled.incl" + +#ifdef T2EE_PRINT_DISASS +#include "dis-asm.h" +#include "bfd.h" +#endif + +#define opc_nop 0x00 +#define opc_aconst_null 0x01 +#define opc_iconst_m1 0x02 +#define opc_iconst_0 0x03 +#define opc_iconst_1 0x04 +#define opc_iconst_2 0x05 +#define opc_iconst_3 0x06 +#define opc_iconst_4 0x07 +#define opc_iconst_5 0x08 +#define opc_lconst_0 0x09 +#define opc_lconst_1 0x0a +#define opc_fconst_0 0x0b +#define opc_fconst_1 0x0c +#define opc_fconst_2 0x0d +#define opc_dconst_0 0x0e +#define opc_dconst_1 0x0f +#define opc_bipush 0x10 +#define opc_sipush 0x11 +#define opc_ldc 0x12 +#define opc_ldc_w 0x13 +#define opc_ldc2_w 0x14 +#define opc_iload 0x15 +#define opc_lload 0x16 +#define opc_fload 0x17 +#define opc_dload 0x18 +#define opc_aload 0x19 +#define opc_iload_0 0x1a +#define opc_iload_1 0x1b +#define opc_iload_2 0x1c +#define opc_iload_3 0x1d +#define opc_lload_0 0x1e +#define opc_lload_1 0x1f +#define opc_lload_2 0x20 +#define opc_lload_3 0x21 +#define opc_fload_0 0x22 +#define opc_fload_1 0x23 +#define opc_fload_2 0x24 +#define opc_fload_3 0x25 +#define opc_dload_0 0x26 +#define opc_dload_1 0x27 +#define opc_dload_2 0x28 +#define opc_dload_3 0x29 +#define opc_aload_0 0x2a +#define opc_aload_1 0x2b +#define opc_aload_2 0x2c +#define opc_aload_3 0x2d +#define opc_iaload 0x2e +#define opc_laload 0x2f +#define opc_faload 0x30 +#define opc_daload 0x31 +#define opc_aaload 0x32 +#define opc_baload 0x33 +#define opc_caload 0x34 +#define opc_saload 0x35 +#define opc_istore 0x36 +#define opc_lstore 0x37 +#define opc_fstore 0x38 +#define opc_dstore 0x39 +#define opc_astore 0x3a +#define opc_istore_0 0x3b +#define opc_istore_1 0x3c +#define opc_istore_2 0x3d +#define opc_istore_3 0x3e +#define opc_lstore_0 0x3f +#define opc_lstore_1 0x40 +#define opc_lstore_2 0x41 +#define opc_lstore_3 0x42 +#define opc_fstore_0 0x43 +#define opc_fstore_1 0x44 +#define opc_fstore_2 0x45 +#define opc_fstore_3 0x46 +#define opc_dstore_0 0x47 +#define opc_dstore_1 0x48 +#define opc_dstore_2 0x49 +#define opc_dstore_3 0x4a +#define opc_astore_0 0x4b +#define opc_astore_1 0x4c +#define opc_astore_2 0x4d +#define opc_astore_3 0x4e +#define opc_iastore 0x4f +#define opc_lastore 0x50 +#define opc_fastore 0x51 +#define opc_dastore 0x52 +#define opc_aastore 0x53 +#define opc_bastore 0x54 +#define opc_castore 0x55 +#define opc_sastore 0x56 +#define opc_pop 0x57 +#define opc_pop2 0x58 +#define opc_dup 0x59 +#define opc_dup_x1 0x5a +#define opc_dup_x2 0x5b +#define opc_dup2 0x5c +#define opc_dup2_x1 0x5d +#define opc_dup2_x2 0x5e +#define opc_swap 0x5f +#define opc_iadd 0x60 +#define opc_ladd 0x61 +#define opc_fadd 0x62 +#define opc_dadd 0x63 +#define opc_isub 0x64 +#define opc_lsub 0x65 +#define opc_fsub 0x66 +#define opc_dsub 0x67 +#define opc_imul 0x68 +#define opc_lmul 0x69 +#define opc_fmul 0x6a +#define opc_dmul 0x6b +#define opc_idiv 0x6c +#define opc_ldiv 0x6d +#define opc_fdiv 0x6e +#define opc_ddiv 0x6f +#define opc_irem 0x70 +#define opc_lrem 0x71 +#define opc_frem 0x72 +#define opc_drem 0x73 +#define opc_ineg 0x74 +#define opc_lneg 0x75 +#define opc_fneg 0x76 +#define opc_dneg 0x77 +#define opc_ishl 0x78 +#define opc_lshl 0x79 +#define opc_ishr 0x7a +#define opc_lshr 0x7b +#define opc_iushr 0x7c +#define opc_lushr 0x7d +#define opc_iand 0x7e +#define opc_land 0x7f +#define opc_ior 0x80 +#define opc_lor 0x81 +#define opc_ixor 0x82 +#define opc_lxor 0x83 +#define opc_iinc 0x84 +#define opc_i2l 0x85 +#define opc_i2f 0x86 +#define opc_i2d 0x87 +#define opc_l2i 0x88 +#define opc_l2f 0x89 +#define opc_l2d 0x8a +#define opc_f2i 0x8b +#define opc_f2l 0x8c +#define opc_f2d 0x8d +#define opc_d2i 0x8e +#define opc_d2l 0x8f +#define opc_d2f 0x90 +#define opc_i2b 0x91 +#define opc_i2c 0x92 +#define opc_i2s 0x93 +#define opc_lcmp 0x94 +#define opc_fcmpl 0x95 +#define opc_fcmpg 0x96 +#define opc_dcmpl 0x97 +#define opc_dcmpg 0x98 +#define opc_ifeq 0x99 +#define opc_ifne 0x9a +#define opc_iflt 0x9b +#define opc_ifge 0x9c +#define opc_ifgt 0x9d +#define opc_ifle 0x9e +#define opc_if_icmpeq 0x9f +#define opc_if_icmpne 0xa0 +#define opc_if_icmplt 0xa1 +#define opc_if_icmpge 0xa2 +#define opc_if_icmpgt 0xa3 +#define opc_if_icmple 0xa4 +#define opc_if_acmpeq 0xa5 +#define opc_if_acmpne 0xa6 +#define opc_goto 0xa7 +#define opc_jsr 0xa8 +#define opc_ret 0xa9 +#define opc_tableswitch 0xaa +#define opc_lookupswitch 0xab +#define opc_ireturn 0xac +#define opc_lreturn 0xad +#define opc_freturn 0xae +#define opc_dreturn 0xaf +#define opc_areturn 0xb0 +#define opc_return 0xb1 +#define opc_getstatic 0xb2 +#define opc_putstatic 0xb3 +#define opc_getfield 0xb4 +#define opc_putfield 0xb5 +#define opc_invokevirtual 0xb6 +#define opc_invokespecial 0xb7 +#define opc_invokestatic 0xb8 +#define opc_invokeinterface 0xb9 +#define opc_new 0xbb +#define opc_newarray 0xbc +#define opc_anewarray 0xbd +#define opc_arraylength 0xbe +#define opc_athrow 0xbf +#define opc_checkcast 0xc0 +#define opc_instanceof 0xc1 +#define opc_monitorenter 0xc2 +#define opc_monitorexit 0xc3 +#define opc_wide 0xc4 +#define opc_multianewarray 0xc5 +#define opc_ifnull 0xc6 +#define opc_ifnonnull 0xc7 +#define opc_goto_w 0xc8 +#define opc_jsr_w 0xc9 +#define opc_breakpoint 0xca + +#define OPC_LAST_JAVA_OP 0xca + +#define opc_bgetfield 0xcc +#define opc_cgetfield 0xcd +#define opc_igetfield 0xd0 +#define opc_lgetfield 0xd1 +#define opc_sgetfield 0xd2 +#define opc_aputfield 0xd3 +#define opc_bputfield 0xd4 +#define opc_cputfield 0xd5 +#define opc_iputfield 0xd8 +#define opc_lputfield 0xd9 +#define opc_iaccess_0 0xdb +#define opc_iaccess_1 0xdc +#define opc_iaccess_2 0xdd +#define opc_iaccess_3 0xde +#define opc_invokeresolved 0xdf +#define opc_invokespecialresolved 0xe0 +#define opc_invokestaticresolved 0xe1 +#define opc_invokevfinal 0xe2 +#define opc_iload_iload 0xe3 +#define opc_iload_iload_N 0xe4 +#define opc_return_register_finalizer 0xe5 +#define opc_dmac 0xe6 +#define opc_iload_0_iconst_N 0xe7 +#define opc_iload_1_iconst_N 0xe8 +#define opc_iload_2_iconst_N 0xe9 +#define opc_iload_3_iconst_N 0xea +#define opc_iload_iconst_N 0xeb +#define opc_iadd_istore_N 0xec +#define opc_isub_istore_N 0xed +#define opc_iand_istore_N 0xee +#define opc_ior_istore_N 0xef +#define opc_ixor_istore_N 0xf0 +#define opc_iadd_u4store 0xf1 +#define opc_isub_u4store 0xf2 +#define opc_iand_u4store 0xf3 +#define opc_ior_u4store 0xf4 +#define opc_ixor_u4store 0xf5 +#define opc_iload_0_iload 0xf6 +#define opc_iload_1_iload 0xf7 +#define opc_iload_2_iload 0xf8 +#define opc_iload_3_iload 0xf9 +#define opc_iload_0_iload_N 0xfa +#define opc_iload_1_iload_N 0xfb +#define opc_iload_2_iload_N 0xfc +#define opc_iload_3_iload_N 0xfd + +#define H_IREM 0 +#define H_IDIV 1 +#define H_LDIV 2 +#define H_LREM 3 +#define H_FREM 4 +#define H_DREM 5 +#define H_LDC 6 +#define H_NEW 8 +#define H_I2F 9 +#define H_I2D 10 +#define H_L2F 11 +#define H_L2D 12 +#define H_F2I 13 +#define H_F2L 14 +#define H_F2D 15 +#define H_D2I 16 +#define H_D2L 17 +#define H_D2F 18 +#define H_NEWARRAY 19 +#define H_ANEWARRAY 20 +#define H_MULTIANEWARRAY 21 +#define H_INSTANCEOF 22 +#define H_CHECKCAST 23 +#define H_AASTORE 24 +#define H_APUTFIELD 25 +#define H_SYNCHRONIZED_ENTER 26 +#define H_SYNCHRONIZED_EXIT 27 + +#define H_EXIT_TO_INTERPRETER 28 + +#define H_GETSTATIC H_EXIT_TO_INTERPRETER +#define H_PUTSTATIC H_EXIT_TO_INTERPRETER +#define H_JSR H_EXIT_TO_INTERPRETER +#define H_RET H_EXIT_TO_INTERPRETER +#define H_ZOMBIE H_EXIT_TO_INTERPRETER +#define H_MONITOR H_EXIT_TO_INTERPRETER +#define H_ATHROW H_EXIT_TO_INTERPRETER + +#define H_HANDLE_EXCEPTION 29 +#define H_ARRAYBOUND 30 +#define H_UNKNOWN 31 + +#define H_DEBUG_METHODENTRY 32 +#define H_DEBUG_METHODEXIT 33 +#define H_DEBUG_METHODCALL 34 + +#define H_INVOKEINTERFACE 35 +#define H_INVOKEVIRTUAL 36 +#define H_INVOKESTATIC 37 +#define H_INVOKESPECIAL 38 + +#define H_GETFIELD_WORD 39 +#define H_GETFIELD_SH 40 +#define H_GETFIELD_H 41 +#define H_GETFIELD_SB 42 +#define H_GETFIELD_DW 43 + +#define H_PUTFIELD_WORD 44 +#define H_PUTFIELD_H 45 +#define H_PUTFIELD_B 46 +#define H_PUTFIELD_A 47 +#define H_PUTFIELD_DW 48 + +#define H_GETSTATIC_WORD 49 +#define H_GETSTATIC_SH 50 +#define H_GETSTATIC_H 51 +#define H_GETSTATIC_SB 52 +#define H_GETSTATIC_DW 53 + +#define H_PUTSTATIC_WORD 54 +#define H_PUTSTATIC_H 55 +#define H_PUTSTATIC_B 56 +#define H_PUTSTATIC_A 57 +#define H_PUTSTATIC_DW 58 + +unsigned handlers[59]; + +#define JASSERT(cond, msg) do { if (!(cond)) fatal(msg); } while (0) +#define J_Unimplemented() { report_unimplemented(__FILE__, __LINE__); BREAKPOINT; } + +#define GET_NATIVE_U2(p) (*(unsigned short *)(p)) + +#define GET_JAVA_S1(p) (((signed char *)(p))[0]) +#define GET_JAVA_S2(p) ((((signed char *)(p))[0] << 8) + (p)[1]) +#define GET_JAVA_U2(p) (((p)[0] << 8) + (p)[1]) +#define GET_JAVA_U4(p) (((p)[0] << 24) + ((p)[1] << 16) + ((p)[2] << 8) + (p)[3]) + +#define BYTESEX_REVERSE(v) (((v)<<24) | (((v)<<8) & 0xff0000) | (((v)>>8) & 0xff00) | ((v)>>24)) +#define BYTESEX_REVERSE_U2(v) (((v)<<8) | ((v)>>8)) + +typedef struct Thumb2_CodeBuf { + unsigned size; + char *sp; + char *hp; +} Thumb2_CodeBuf; + +Thumb2_CodeBuf *thumb2_codebuf; + +unsigned bc_stackinfo[8000]; +unsigned locals_info[1000]; +unsigned stack[1000]; +unsigned r_local[1000]; + +#ifdef T2EE_PRINT_DISASS +short start_bci[65000]; +short end_bci[65000]; +#endif + +// XXX hardwired constants! +#define ENTRY_FRAME 1 +#define INTERPRETER_FRAME 2 +#define SHARK_FRAME 3 +#define FAKE_STUB_FRAME 4 + +#include "offsets_arm.s" + +#define BC_FLAGS_MASK 0xfc000000 +#define BC_VISITED_P1 0x80000000 +#define BC_BRANCH_TARGET 0x40000000 +#define BC_COMPILED 0x20000000 +#define BC_VISITED_P2 0x10000000 +#define BC_ZOMBIE 0x08000000 +#define BC_BACK_TARGET 0x04000000 + +#define IS_DEAD(x) (((x) & BC_VISITED_P1) == 0) +#define IS_ZOMBIE(x) (((x) & BC_ZOMBIE) || ((x) & BC_VISITED_P2) == 0) + +#define LOCAL_MODIFIED 31 +#define LOCAL_REF 30 +#define LOCAL_DOUBLE 29 +#define LOCAL_FLOAT 28 +#define LOCAL_LONG 27 +#define LOCAL_INT 26 +#define LOCAL_ALLOCATED 25 + +#define LOCAL_COUNT_BITS 10 +#define LOCAL_READ_POS 0 +#define LOCAL_WRITE_POS LOCAL_COUNT_BITS + +#define LOCAL_READS(x) (((x) >> LOCAL_READ_POS) & ((1<<LOCAL_COUNT_BITS)-1)) +#define LOCAL_WRITES(x) (((x) >> LOCAL_WRITE_POS) & ((1<<LOCAL_COUNT_BITS)-1)) +#define LOCAL_SET_COUNTS(r, w) (((r) << LOCAL_READ_POS) | (((w) << LOCAL_WRITE_POS))) +#define LOCAL_INC_COUNT(c) ((c) < ((1<<LOCAL_COUNT_BITS)-1) ? (c)+1 : (c)) + +#define STACK_REGS 4 +#define FP_STACK_REGS 4 + +typedef unsigned u32; +typedef unsigned Reg; + +#define ARM_R0 0 +#define ARM_R1 1 +#define ARM_R2 2 +#define ARM_R3 3 +#define ARM_R4 4 +#define ARM_R5 5 +#define ARM_R6 6 +#define ARM_R7 7 +#define ARM_R8 8 +#define ARM_R9 9 +#define ARM_R10 10 +#define ARM_R11 11 +#define ARM_IP 12 +#define ARM_SP 13 +#define ARM_LR 14 +#define ARM_PC 15 +#define ARM_CPSR 16 // CPSR in sigcontext +#define ARM_FAULT 17 // fault address in sigcontext + +#define CPSR_THUMB_BIT (1<<5) + +#define VFP_S0 32 +#define VFP_S1 33 +#define VFP_S2 34 +#define VFP_S3 35 +#define VFP_S4 36 +#define VFP_S5 37 +#define VFP_S6 38 +#define VFP_S7 39 + +#define VFP_D0 64 +#define VFP_D1 65 +#define VFP_D2 66 +#define VFP_D3 67 +#define VFP_D4 68 +#define VFP_D5 69 +#define VFP_D6 70 +#define VFP_D7 71 + +#define JAZ_V1 ARM_R6 +#define JAZ_V2 ARM_R5 +#define JAZ_V3 ARM_R7 +#define JAZ_V4 ARM_R11 +#define JAZ_V5 ARM_R10 + +#define Rstack ARM_R4 +#define Rlocals ARM_R7 +#define Ristate ARM_R8 +#define Rthread ARM_R9 + +#define Rint_stack ARM_R4 +#define Rint_jpc ARM_R5 +#define Rint_istate ARM_R8 + +#define IS_ARM_INT_REG(r) ((r) <= ARM_PC) +#define IS_ARM_FP_REG(r) (!IS_ARM_INT_REG(r)) + +#define I_REGSET ((1<<ARM_R4) | (1<<ARM_R5) | (1<<ARM_R6) | (1<<ARM_R7) | \ + (1<<ARM_R9) | (1<<ARM_R10) | (1<<ARM_R11)) +#define C_REGSET (1<<ARM_R8) + +#define LOG2(n) binary_log2(n) + +unsigned binary_log2(unsigned n) +{ + unsigned r = 0; + if ((n & 0xffff) == 0) r = 16, n >>= 16; + if ((n & 0xff) == 0) r += 8, n >>= 8; + if ((n & 0xf) == 0) r += 4, n >>= 4; + if ((n & 3) == 0) r += 2, n >>= 2; + if ((n & 1) == 0) r += 1; + return r; +} + +typedef struct CodeBuf { + unsigned short *codebuf; + unsigned idx; +} CodeBuf; + +typedef struct Thumb2_Stack { + unsigned *stack; + unsigned depth; +} Thumb2_Stack; + +#define IS_SREG(r) ((r) < STACK_REGS) + +typedef struct Thumb2_Registers { + unsigned *r_local; +} Thumb2_Registers; + +typedef struct Thumb2_Info { + JavaThread *thread; + methodOop method; + unsigned *bc_stackinfo; + unsigned *locals_info; + jubyte *code_base; + unsigned code_size; + CodeBuf *codebuf; + Thumb2_Stack *jstack; + Thumb2_Registers *jregs; + unsigned compiled_return; + unsigned zombie_bytes; +} Thumb2_Info; + +#define IS_INT_SIZE_BASE_TYPE(c) (c=='B' || c=='C' || c=='F' || c=='I' || c=='S' || c=='Z') +#define IS_INT_SIZE_TYPE(c) (IS_INT_SIZE_BASE_TYPE(c) || c == 'L' || c == '[') + +static int method_stackchange(jbyte *base) +{ + jbyte c; + int stackchange = 0; + + c = *base++; + JASSERT(c == '(', "Invalid signature, missing '('"); + while ((c = *base++) != ')') { + stackchange -= 1; + if (c == 'J' || c == 'D') { + stackchange -= 1; + } else if (c == '[') { + do { c = *base++; } while (c == '['); + if (c == 'L') + do { c = *base++; } while (c != ';'); + } else if (c == 'L') { + do { c = *base++; } while (c != ';'); + } else { + JASSERT(IS_INT_SIZE_BASE_TYPE(c), "Invalid signature, bad arg type"); + } + } + JASSERT(c == ')', "Invalid signature, missing ')'"); + c = *base++; + if (c == 'J' || c == 'D') stackchange += 2; + else if (c != 'V') { + stackchange += 1; + JASSERT(IS_INT_SIZE_TYPE(c), "Invalid signature, bad ret type"); + } + return stackchange; +} + +static void Thumb2_local_info_from_sig(Thumb2_Info *jinfo, methodOop method, jbyte *base) +{ + jbyte c; + unsigned arg = 0; + unsigned *locals_info = jinfo->locals_info; + unsigned local_info; + + if (!method->is_static()) locals_info[arg++] = 1 << LOCAL_REF; + c = *base++; + JASSERT(c == '(', "Invalid signature, missing '('"); + while ((c = *base++) != ')') { + local_info = 1 << LOCAL_INT; + if (c == 'J') local_info = 1 << LOCAL_LONG; + else if (c == 'D') local_info = 1 << LOCAL_DOUBLE; + else if (c == '[') { + local_info = 1 << LOCAL_REF; + do { c = *base++; } while (c == '['); + if (c == 'L') + do { c = *base++; } while (c != ';'); + } else if (c == 'L') { + local_info = 1 << LOCAL_REF; + do { c = *base++; } while (c != ';'); + } else { + JASSERT(IS_INT_SIZE_BASE_TYPE(c), "Invalid signature, bad arg type"); + } + locals_info[arg++] = local_info; + } +} + +#define T_UNDEFINED_32 0xf7f0a000 +#define T_UNDEFINED_16 0xde00 + +static const char *local_types[] = { "int", "long", "float", "double", "ref" }; + +#ifdef T2EE_PRINT_DISASS +void Thumb2_disass(Thumb2_Info *jinfo) +{ + unsigned code_size = jinfo->code_size; + jubyte *code_base = jinfo->code_base; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + unsigned *locals_info = jinfo->locals_info; + unsigned nlocals = jinfo->method->max_locals(); + int bci = 0; + int last_bci = -1; + int start_b, end_b; + unsigned nodisass; + + struct disassemble_info info; + unsigned short *codebuf = jinfo->codebuf->codebuf; + unsigned idx, compiled_len; + +#if 0 + printf("Local Variable Usage\n"); + printf("====================\n"); + for (idx = 0; idx < nlocals; idx++) { + unsigned linfo = locals_info[idx]; + unsigned typ = (linfo >> LOCAL_INT) & 0x1f; + + printf("Local %d, type = %s (%x)", idx, typ ? local_types[LOG2(typ)] : "!!!unknown!!!", typ); + if (linfo & (1 << LOCAL_MODIFIED)) printf(", modified"); + if (idx < (unsigned)jinfo->method->size_of_parameters()) printf(", parameter"); + putchar('\n'); + } +#endif + + init_disassemble_info(&info, stdout, (fprintf_ftype)fprintf); + info.arch = bfd_arch_arm; + disassemble_init_for_target(&info); + info.endian = BFD_ENDIAN_LITTLE; + info.endian_code = BFD_ENDIAN_LITTLE; + info.buffer = (bfd_byte *)codebuf; + info.buffer_vma = (bfd_vma)codebuf; + info.buffer_length = jinfo->codebuf->idx * sizeof(short); + info.disassembler_options = (char *)"force-thumb"; + + compiled_len = jinfo->codebuf->idx * 2; + for (idx = 0; idx < compiled_len; ) { + nodisass = 0; + start_b = start_bci[idx/2]; + end_b = end_bci[idx/2]; + if (start_b != -1) { + last_bci != -1; + for (bci = start_b; bci < end_b; ) { + unsigned stackinfo = bc_stackinfo[bci]; + unsigned opcode; + int len; + + if (stackinfo & BC_BRANCH_TARGET) + printf("----- Basic Block -----\n"); + JASSERT(bci > last_bci, "disass not advancing"); + last_bci = bci; + printf("%c%4d : ", (stackinfo & BC_VISITED_P1) ? ' ' : '?', bci); + opcode = code_base[bci]; + if (opcode > OPC_LAST_JAVA_OP) { + if (Bytecodes::is_defined((Bytecodes::Code)opcode)) + opcode = (unsigned)Bytecodes::java_code((Bytecodes::Code)opcode); + } + len = Bytecodes::length_for((Bytecodes::Code)opcode); + if (len <= 0) len = Bytecodes::special_length_at((address)(code_base+bci), (address)(code_base+code_size)); + switch (opcode) { + case opc_tableswitch: { + int nbci = (bci & ~3) + 4; + int low, high; + unsigned w; + unsigned *table; + int def; + unsigned n, i; + + printf("%02x ", opcode); + for (int i = 1; i < 5; i++) + printf(" "); + printf("%s\n", Bytecodes::name((Bytecodes::Code)opcode)); + printf("\t%d bytes padding\n", nbci - (bci+1)); + w = *(unsigned int *)(code_base + nbci + 4); + low = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 8); + high = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 0); + def = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 12); + printf("\tdefault:\t0x%08x\n", def); + printf("\tlow:\t\t0x%08x\n", low); + printf("\thigh:\t\t0x%08x\n", high); + n = high - low + 1; + while (low <= high) { + int off; + + w = *table++; + off = (int)BYTESEX_REVERSE(w); + printf("\toffset %d:\t0x%08x\n", low, off); + low++; + } + bci += len; + for (i = 0; i < 4; i++) { + printf("0x%08x:\t", (int)codebuf+idx); + { + int len = print_insn_little_arm((bfd_vma)codebuf+idx, &info); + if (len == -1) len = 2; + idx += len; + putchar('\n'); + } + } + for (i = 0; i < n; i++) { + printf("0x%08x:\t.short\t0x%04x\n", (int)codebuf+idx, *(short *)((int)codebuf + idx)); + idx += 2; + } + nodisass = 1; + break; + } + case opc_lookupswitch: { + unsigned w; + unsigned nbci = (bci & ~3) + 4;; + int def; + int npairs; // The Java spec says signed but must be >= 0?? + unsigned *table; + + printf("%02x ", opcode); + for (int i = 1; i < 5; i++) + printf(" "); + printf("%s\n", Bytecodes::name((Bytecodes::Code)opcode)); + printf("\t%d bytes padding\n", nbci - (bci+1)); + + w = *(unsigned int *)(code_base + nbci + 0); + def = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 4); + npairs = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 8); + printf("\tdefault:\t0x%08x\n", def); + printf("\tnpairs:\t\t0x%08x\n", npairs); + for (int i = 0; i < npairs; i++) { + unsigned match, off; + w = table[0]; + match = BYTESEX_REVERSE(w); + w = table[1]; + table += 2; + off = BYTESEX_REVERSE(w); + printf("\t match: 0x%08x, offset: 0x%08x\n", match, off); + } + break; + } + + default: + for (int i = 0; i < 5; i++) { + if (i < len) + printf("%02x ", code_base[bci+i]); + else + printf(" "); + } + printf("%s\n", Bytecodes::name((Bytecodes::Code)code_base[bci])); + break; + } + bci += len; + } + } + if (!nodisass) { + printf("0x%08x:\t", (int)codebuf+idx); + { + int len; + unsigned s1, s2; + + s1 = *(unsigned short *)((int)codebuf + idx); + s2 = *(unsigned short *)((int)codebuf + idx + 2); + if (s1 == T_UNDEFINED_16 || ((s1 << 16) + s2) == T_UNDEFINED_32) { + if (s1 == T_UNDEFINED_16) { + printf("undefined (0xde00) - UNPATCHED BRANCH???"); + len = 2; + } else { + printf("undefined (0xf7f0a000) - UNPATCHED BRANCH???"); + len = 4; + } + } else { + len = print_insn_little_arm((bfd_vma)codebuf+idx, &info); + if (len == -1) len = 2; + idx += len; + } + putchar('\n'); + } + } + } +} +#endif + +#define BCI(len, pop, push, special, islocal, islocal_n, isstore, local_n, local_type) \ + ((len) | ((pop)<<3) | ((push)<<6) | (unsigned)((special) << 31) | ((islocal) << 30) | ((islocal_n) << 29) | ((isstore) << 28) | ((local_n) << 9) | ((local_type) << 11)) + +#define BCI_LEN(x) ((x) & 7) +#define BCI_POP(x) (((x)>>3) & 7) +#define BCI_PUSH(x) (((x)>>6) & 7) +#define BCI_LOCAL_N(x) (((x)>>9) & 3) +#define BCI_LOCAL_TYPE(x) (((x) >> 11) & 7) + +#define BCI_TYPE_INT 0 +#define BCI_TYPE_LONG 1 +#define BCI_TYPE_FLOAT 2 +#define BCI_TYPE_DOUBLE 3 +#define BCI_TYPE_REF 4 + +#define BCI_SPECIAL(x) ((x) & 0x80000000) +#define BCI_ISLOCAL(x) ((x) & 0x40000000) +#define BCI_ISLOCAL_N(x) ((x) & 0x20000000) +#define BCI_ISSTORE(x) ((x) & 0x10000000) + +static const unsigned bcinfo[256] = { + BCI(1, 0, 0, 0, 0, 0, 0, 0, 0), // nop + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // aconst_null + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_m1 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_0 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_1 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_2 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_3 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_4 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // iconst_5 + BCI(1, 0, 2, 0, 0, 0, 0, 0, 0), // lconst_0 + BCI(1, 0, 2, 0, 0, 0, 0, 0, 0), // lconst_1 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // fconst_0 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // fconst_1 + BCI(1, 0, 1, 0, 0, 0, 0, 0, 0), // fconst_2 + BCI(1, 0, 2, 0, 0, 0, 0, 0, 0), // dconst_0 + BCI(1, 0, 2, 0, 0, 0, 0, 0, 0), // dconst_1 + BCI(2, 0, 1, 0, 0, 0, 0, 0, 0), // bipush + BCI(3, 0, 1, 0, 0, 0, 0, 0, 0), // bipush + BCI(2, 0, 1, 0, 0, 0, 0, 0, 0), // ldc + BCI(3, 0, 1, 0, 0, 0, 0, 0, 0), // ldc_w + BCI(3, 0, 2, 0, 0, 0, 0, 0, 0), // ldc2_w + BCI(2, 0, 1, 0, 1, 0, 0, 0, BCI_TYPE_INT), // iload + BCI(2, 0, 2, 0, 1, 0, 0, 0, BCI_TYPE_LONG), // lload + BCI(2, 0, 1, 0, 1, 0, 0, 0, BCI_TYPE_FLOAT), // fload + BCI(2, 0, 2, 0, 1, 0, 0, 0, BCI_TYPE_DOUBLE), // dload + BCI(2, 0, 1, 0, 1, 0, 0, 0, BCI_TYPE_REF), // aload + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_INT), // iload_0 + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_INT), // iload_1 + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_INT), // iload_2 + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_INT), // iload_3 + BCI(1, 0, 2, 0, 1, 1, 0, 0, BCI_TYPE_LONG), // lload_0 + BCI(1, 0, 2, 0, 1, 1, 0, 1, BCI_TYPE_LONG), // lload_1 + BCI(1, 0, 2, 0, 1, 1, 0, 2, BCI_TYPE_LONG), // lload_2 + BCI(1, 0, 2, 0, 1, 1, 0, 3, BCI_TYPE_LONG), // lload_3 + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_FLOAT), // fload_0 + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_FLOAT), // fload_1 + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_FLOAT), // fload_2 + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_FLOAT), // fload_3 + BCI(1, 0, 2, 0, 1, 1, 0, 0, BCI_TYPE_DOUBLE), // dload_0 + BCI(1, 0, 2, 0, 1, 1, 0, 1, BCI_TYPE_DOUBLE), // dload_1 + BCI(1, 0, 2, 0, 1, 1, 0, 2, BCI_TYPE_DOUBLE), // dload_2 + BCI(1, 0, 2, 0, 1, 1, 0, 3, BCI_TYPE_DOUBLE), // dload_3 + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_REF), // aload_0 + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_REF), // aload_1 + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_REF), // aload_2 + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_REF), // aload_3 + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iaload + BCI(1, 2, 2, 0, 0, 0, 0, 0, 0), // laload + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // faload + BCI(1, 2, 2, 0, 0, 0, 0, 0, 0), // daload + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // aaload + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // baload + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // caload + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // saload + BCI(2, 1, 0, 0, 1, 0, 1, 0, BCI_TYPE_INT), // istore + BCI(2, 2, 0, 0, 1, 0, 1, 0, BCI_TYPE_LONG), // lstore + BCI(2, 1, 0, 0, 1, 0, 1, 0, BCI_TYPE_FLOAT), // fstore + BCI(2, 2, 0, 0, 1, 0, 1, 0, BCI_TYPE_DOUBLE), // dstore + BCI(2, 1, 0, 0, 1, 0, 1, 0, BCI_TYPE_REF), // astore + BCI(1, 1, 0, 0, 1, 1, 1, 0, BCI_TYPE_INT), // istore_0 + BCI(1, 1, 0, 0, 1, 1, 1, 1, BCI_TYPE_INT), // istore_1 + BCI(1, 1, 0, 0, 1, 1, 1, 2, BCI_TYPE_INT), // istore_2 + BCI(1, 1, 0, 0, 1, 1, 1, 3, BCI_TYPE_INT), // istore_3 + BCI(1, 2, 0, 0, 1, 1, 1, 0, BCI_TYPE_LONG), // lstore_0 + BCI(1, 2, 0, 0, 1, 1, 1, 1, BCI_TYPE_LONG), // lstore_1 + BCI(1, 2, 0, 0, 1, 1, 1, 2, BCI_TYPE_LONG), // lstore_2 + BCI(1, 2, 0, 0, 1, 1, 1, 3, BCI_TYPE_LONG), // lstore_3 + BCI(1, 1, 0, 0, 1, 1, 1, 0, BCI_TYPE_FLOAT), // fstore_0 + BCI(1, 1, 0, 0, 1, 1, 1, 1, BCI_TYPE_FLOAT), // fstore_1 + BCI(1, 1, 0, 0, 1, 1, 1, 2, BCI_TYPE_FLOAT), // fstore_2 + BCI(1, 1, 0, 0, 1, 1, 1, 3, BCI_TYPE_FLOAT), // fstore_3 + BCI(1, 2, 0, 0, 1, 1, 1, 0, BCI_TYPE_DOUBLE), // dstore_0 + BCI(1, 2, 0, 0, 1, 1, 1, 1, BCI_TYPE_DOUBLE), // dstore_1 + BCI(1, 2, 0, 0, 1, 1, 1, 2, BCI_TYPE_DOUBLE), // dstore_2 + BCI(1, 2, 0, 0, 1, 1, 1, 3, BCI_TYPE_DOUBLE), // dstore_3 + BCI(1, 1, 0, 0, 1, 1, 1, 0, BCI_TYPE_REF), // astore_0 + BCI(1, 1, 0, 0, 1, 1, 1, 1, BCI_TYPE_REF), // astore_1 + BCI(1, 1, 0, 0, 1, 1, 1, 2, BCI_TYPE_REF), // astore_2 + BCI(1, 1, 0, 0, 1, 1, 1, 3, BCI_TYPE_REF), // astore_3 + BCI(1, 3, 0, 0, 0, 0, 0, 0, 0), // iastore + BCI(1, 4, 0, 0, 0, 0, 0, 0, 0), // dastore + BCI(1, 3, 0, 0, 0, 0, 0, 0, 0), // fastore + BCI(1, 4, 0, 0, 0, 0, 0, 0, 0), // lastore + BCI(1, 3, 0, 0, 0, 0, 0, 0, 0), // aastore + BCI(1, 3, 0, 0, 0, 0, 0, 0, 0), // bastore + BCI(1, 3, 0, 0, 0, 0, 0, 0, 0), // castore + BCI(1, 3, 0, 0, 0, 0, 0, 0, 0), // sastore + BCI(1, 1, 0, 0, 0, 0, 0, 0, 0), // pop + BCI(1, 2, 0, 0, 0, 0, 0, 0, 0), // pop2 + BCI(1, 1, 2, 0, 0, 0, 0, 0, 0), // dup + BCI(1, 2, 3, 0, 0, 0, 0, 0, 0), // dup_x1 + BCI(1, 3, 4, 0, 0, 0, 0, 0, 0), // dup_x2 + BCI(1, 2, 4, 0, 0, 0, 0, 0, 0), // dup2 + BCI(1, 3, 5, 0, 0, 0, 0, 0, 0), // dup2_x1 + BCI(1, 4, 6, 0, 0, 0, 0, 0, 0), // dup2_x2 + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // swap + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iadd + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // ladd + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // fadd + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // dadd + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // isub + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // lsub + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // fsub + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // dsub + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // imul + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // lmul + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // fmul + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // dmul + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // idiv + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // ldiv + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // fdiv + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // ddiv + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // irem + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // lrem + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // frem + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // drem + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // ineg + BCI(1, 2, 2, 0, 0, 0, 0, 0, 0), // lneg + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // fneg + BCI(1, 2, 2, 0, 0, 0, 0, 0, 0), // dneg + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ishl + BCI(1, 3, 2, 0, 0, 0, 0, 0, 0), // lshl + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ishr + BCI(1, 3, 2, 0, 0, 0, 0, 0, 0), // lshr + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iushr + BCI(1, 3, 2, 0, 0, 0, 0, 0, 0), // lushr + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iand + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // land + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ior + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // lor + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ixor + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // lxor + BCI(3, 0, 0, 0, 1, 0, 1, 0, BCI_TYPE_INT), // iinc + BCI(1, 1, 2, 0, 0, 0, 0, 0, 0), // i2l + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // i2f + BCI(1, 1, 2, 0, 0, 0, 0, 0, 0), // i2d + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // l2i + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // l2f + BCI(1, 2, 2, 0, 0, 0, 0, 0, 0), // l2d + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // f2i + BCI(1, 1, 2, 0, 0, 0, 0, 0, 0), // f2l + BCI(1, 1, 2, 0, 0, 0, 0, 0, 0), // f2d + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // d2i + BCI(1, 2, 2, 0, 0, 0, 0, 0, 0), // d2l + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // d2f + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // i2b + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // i2c + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // i2s + BCI(1, 4, 1, 0, 0, 0, 0, 0, 0), // lcmp + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // fcmpl + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // fcmpg + BCI(1, 4, 1, 0, 0, 0, 0, 0, 0), // dcmpl + BCI(1, 4, 1, 0, 0, 0, 0, 0, 0), // dcmpg + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifeq + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifne + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // iflt + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifge + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifgt + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifle + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_icmpeq + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_icmpne + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_icmplt + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_icmpge + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_icmpgt + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_icmple + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_acmpeq + BCI(3, 2, 0, 1, 0, 0, 0, 0, 0), // if_acmpne + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // goto + BCI(3, 0, 1, 1, 0, 0, 0, 0, 0), // jsr + BCI(2, 0, 0, 1, 0, 0, 0, 0, 0), // ret + BCI(0, 1, 0, 1, 0, 0, 0, 0, 0), // tableswitch + BCI(0, 1, 0, 1, 0, 0, 0, 0, 0), // lookupswitch + BCI(1, 1, 0, 1, 0, 0, 0, 0, 0), // ireturn + BCI(1, 2, 0, 1, 0, 0, 0, 0, 0), // lreturn + BCI(1, 1, 0, 1, 0, 0, 0, 0, 0), // freturn + BCI(1, 2, 0, 1, 0, 0, 0, 0, 0), // dreturn + BCI(1, 1, 0, 1, 0, 0, 0, 0, 0), // areturn + BCI(1, 0, 0, 1, 0, 0, 0, 0, 0), // return + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // getstatic + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // putstatic + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // getfield + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // putfield + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokevirtual + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokespecial + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokestatic + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokeinterface + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // xxxunusedxxx + BCI(3, 0, 1, 0, 0, 0, 0, 0, 0), // new + BCI(2, 1, 1, 0, 0, 0, 0, 0, 0), // newarray + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // anewarray + BCI(1, 1, 1, 0, 0, 0, 0, 0, 0), // arraylength + BCI(1, 1, 1, 1, 0, 0, 0, 0, 0), // athrow + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // checkcast + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // instanceof + BCI(1, 1, 0, 0, 0, 0, 0, 0, 0), // monitorenter + BCI(1, 1, 0, 0, 0, 0, 0, 0, 0), // monitorexit + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // wide + BCI(4, 0, 0, 1, 0, 0, 0, 0, 0), // multianewarray + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifnull + BCI(3, 1, 0, 1, 0, 0, 0, 0, 0), // ifnonnull + BCI(5, 0, 0, 1, 0, 0, 0, 0, 0), // goto_w + BCI(5, 0, 0, 1, 0, 0, 0, 0, 0), // jsr_w + BCI(1, 0, 0, 1, 0, 0, 0, 0, 0), // breakpoint + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // unused 0xcb + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // bgetfield + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // cgetfield + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // unused 0xce + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // unused 0xcf + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // igetfield + BCI(3, 1, 2, 0, 0, 0, 0, 0, 0), // lgetfield + BCI(3, 1, 1, 0, 0, 0, 0, 0, 0), // sgetfield + BCI(3, 2, 0, 0, 0, 0, 0, 0, 0), // aputfield + BCI(3, 2, 0, 0, 0, 0, 0, 0, 0), // bputfield + BCI(3, 2, 0, 0, 0, 0, 0, 0, 0), // cputfield + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // unused 0xd6 + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // unused 0xd7 + BCI(3, 2, 0, 0, 0, 0, 0, 0, 0), // iputfield + BCI(3, 3, 0, 0, 0, 0, 0, 0, 0), // lputfield + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // unused 0xda + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_REF), // iaccess_0 + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_REF), // iaccess_1 + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_REF), // iaccess_2 + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_REF), // iaccess_3 + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokeresolved + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokespecialresolved + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokestaticresolved + BCI(3, 0, 0, 1, 0, 0, 0, 0, 0), // invokevfinal + BCI(2, 0, 1, 0, 1, 0, 0, 0, BCI_TYPE_INT), // iload_iload + BCI(2, 0, 1, 0, 1, 0, 0, 0, BCI_TYPE_INT), // iload_iload_N + BCI(1, 0, 0, 1, 0, 0, 0, 0, 0), // return_register_finalizer + BCI(1, 4, 2, 0, 0, 0, 0, 0, 0), // dmac + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_INT), // iload_0_iconst_N + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_INT), // iload_1_iconst_N + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_INT), // iload_2_iconst_N + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_INT), // iload_3_iconst_N + BCI(2, 0, 1, 0, 1, 0, 0, 0, BCI_TYPE_INT), // iload_iconst_N + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iadd_istore_N + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // isub_istore_N + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iand_istore_N + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ior_istore_N + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ixor_istore_N + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iadd_u4store + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // isub_u4store + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // iand_u4store + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ior_u4store + BCI(1, 2, 1, 0, 0, 0, 0, 0, 0), // ixor_u4store + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_INT), // iload_0_iload + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_INT), // iload_1_iload + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_INT), // iload_2_iload + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_INT), // iload_3_iload + BCI(1, 0, 1, 0, 1, 1, 0, 0, BCI_TYPE_INT), // iload_0_iload_N + BCI(1, 0, 1, 0, 1, 1, 0, 1, BCI_TYPE_INT), // iload_1_iload_N + BCI(1, 0, 1, 0, 1, 1, 0, 2, BCI_TYPE_INT), // iload_2_iload_N + BCI(1, 0, 1, 0, 1, 1, 0, 3, BCI_TYPE_INT), // iload_3_iload_N + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // impdep1 + BCI(0, 0, 0, 1, 0, 0, 0, 0, 0), // impdep2 +}; + +void Thumb2_pass1(Thumb2_Info *jinfo, unsigned bci) +{ + unsigned code_size = jinfo->code_size; + jubyte *code_base = jinfo->code_base; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + unsigned *locals_info = jinfo->locals_info; + //constantPoolCacheOop cp = jinfo->method->constants()->cache(); + + bc_stackinfo[bci] |= BC_BRANCH_TARGET; + while (bci < code_size) { + unsigned stackinfo = bc_stackinfo[bci]; + unsigned bytecodeinfo; + unsigned opcode; + + if (stackinfo & BC_VISITED_P1) break; + bc_stackinfo[bci] = (stackinfo & BC_FLAGS_MASK) | BC_VISITED_P1; + opcode = code_base[bci]; +// printf("bci = 0x%04x, opcode = 0x%02x (%s)", bci, opcode, Bytecodes::name((Bytecodes::Code)opcode)); + bytecodeinfo = bcinfo[opcode]; + if (!BCI_SPECIAL(bytecodeinfo)) { + bci += BCI_LEN(bytecodeinfo); + continue; + } + + switch (opcode) { + + case opc_goto: { + int off = GET_JAVA_S2(code_base+bci+1); + bci += off; + bc_stackinfo[bci] |= BC_BRANCH_TARGET; + if (off < 0) bc_stackinfo[bci] |= BC_BACK_TARGET; + break; + } + case opc_goto_w: { + int off = GET_JAVA_U4(code_base+bci+1); + bci += off; + bc_stackinfo[bci] |= BC_BRANCH_TARGET; + if (off < 0) bc_stackinfo[bci] |= BC_BACK_TARGET; + break; + } + + case opc_if_icmpeq: + case opc_if_icmpne: + case opc_if_icmplt: + case opc_if_icmpge: + case opc_if_icmpgt: + case opc_if_icmple: + case opc_if_acmpeq: + case opc_if_acmpne: + case opc_ifeq: + case opc_ifne: + case opc_iflt: + case opc_ifge: + case opc_ifgt: + case opc_ifle: + case opc_ifnull: + case opc_ifnonnull: { + int off = GET_JAVA_S2(code_base+bci+1); + if (off < 0) bc_stackinfo[bci+off] |= BC_BACK_TARGET; + Thumb2_pass1(jinfo, bci + off); + bci += 3; + break; + } + + case opc_jsr: { + int off = GET_JAVA_S2(code_base+bci+1); + if (off < 0) bc_stackinfo[bci+off] |= BC_BACK_TARGET; + Thumb2_pass1(jinfo, bci + off); + bci += 3; + break; + } + case opc_jsr_w: { + int off = GET_JAVA_U4(code_base+bci+1); + if (off < 0) bc_stackinfo[bci+off] |= BC_BACK_TARGET; + Thumb2_pass1(jinfo, bci + off); + bci += 5; + break; + } + + case opc_ireturn: + case opc_lreturn: + case opc_freturn: + case opc_dreturn: + case opc_areturn: + case opc_return: + case opc_return_register_finalizer: + case opc_ret: + case opc_athrow: + // The test for BC_VISITED_P1 above will break out of the loop!!! + break; + + case opc_tableswitch: { + int low, high; + unsigned w; + unsigned *table; + unsigned nbci; + int def; + + nbci = bci & ~3; + w = *(unsigned int *)(code_base + nbci + 8); + low = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 12); + high = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 4); + def = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 16); + + while (low <= high) { + int off; + w = *table++; + off = (int)BYTESEX_REVERSE(w); + if (off < 0) bc_stackinfo[bci+off] |= BC_BACK_TARGET; + Thumb2_pass1(jinfo, bci + off); + low++; + } + + bci += def; + bc_stackinfo[bci] |= BC_BRANCH_TARGET; + if (def < 0) bc_stackinfo[bci] |= BC_BACK_TARGET; + break; + } + + case opc_lookupswitch: { + unsigned w; + unsigned nbci; + int def; + int npairs; // The Java spec says signed but must be >= 0?? + unsigned *table; + + nbci = bci & ~3; + w = *(unsigned int *)(code_base + nbci + 4); + def = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 8); + npairs = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 16); + + for (int i = 0; i < npairs; i++) { + int off; + w = *table; + table += 2; + off = (int)BYTESEX_REVERSE(w); + if (off < 0) bc_stackinfo[bci+off] |= BC_BACK_TARGET; + Thumb2_pass1(jinfo, bci + off); + } + + bci += def; + bc_stackinfo[bci] |= BC_BRANCH_TARGET; + if (def < 0) bc_stackinfo[bci] |= BC_BACK_TARGET; + break; + } + + case opc_getstatic: + case opc_putstatic: + case opc_getfield: + case opc_putfield: { + bci += 3; + break; + } + + case opc_invokeresolved: + case opc_invokespecialresolved: + case opc_invokestaticresolved: + case opc_invokevfinal: + case opc_invokevirtual: + case opc_invokespecial: + case opc_invokestatic: + bci += 3; + break; + + case opc_invokeinterface: + bci += 5; + break; + + case opc_multianewarray: + bci += 4; + break; + + case opc_wide: + opcode = code_base[bci+1]; + if (opcode == opc_iinc) { + bci += 6; + } else { + bci += 4; + } + break; + + default: + opcode = code_base[bci]; + fatal1("Undefined opcode %d\n", opcode); + break; + } + } +} + +#ifdef ZOMBIE_DETECTION +int Thumb2_is_zombie(Thumb2_Info *jinfo, unsigned bci) +{ + unsigned code_size = jinfo->code_size; + jubyte *code_base = jinfo->code_base; + unsigned bytecodeinfo; + unsigned opcode; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + + do { + opcode = code_base[bci]; + // Short circuit exit - commented out because even if it has been executed + // we treat throw, jsr, and ret as zombies because they will call out to the + // interpreter. + // if (opcode > OPC_LAST_JAVA_OP) return 0; + bytecodeinfo = bcinfo[opcode]; + if (!BCI_SPECIAL(bytecodeinfo)) { + bci += BCI_LEN(bytecodeinfo); +#if 0 + if (opcode >= opc_iload_iload) { + opcode = code_base[bci]; + bci += BCI_LEN(bcinfo[opcode]); + } else if (BCI_ISLOCAL(bytecodeinfo)) { + if (opcode == opc_iload || (opcode >= opc_iload_0 && opcode <= opc_iload_3)) { + opcode = code_base[bci]; + if (opcode == opc_iload || (opcode >= opc_iload_0 && opcode <= opc_iload_3) || + (opcode >= opc_iconst_m1 && opcode <= opc_iconst_5)) { + printf("found new zombie at %d\n", bci); + return 1; + } + } + } else if (opcode == opc_iadd || opcode == opc_isub || + opcode == opc_iand || opcode == opc_ior || opcode == opc_ixor) { + opcode = code_base[bci]; + if (opcode == opc_istore || (opcode >= opc_istore_0 && opcode <= opc_istore_3)) { + printf("found new zombie at %d\n", bci); + return 1; + } + } +#endif + } else { + switch (opcode) { + case opc_goto: + case opc_goto_w: + case opc_ifeq: + case opc_ifne: + case opc_iflt: + case opc_ifge: + case opc_ifgt: + case opc_ifle: + case opc_ifnull: + case opc_ifnonnull: + case opc_if_icmpeq: + case opc_if_icmpne: + case opc_if_icmplt: + case opc_if_icmpge: + case opc_if_icmpgt: + case opc_if_icmple: + case opc_if_acmpeq: + case opc_if_acmpne: + case opc_tableswitch: + case opc_lookupswitch: + return 0; + case opc_ireturn: + case opc_lreturn: + case opc_freturn: + case opc_dreturn: + case opc_areturn: + case opc_return: + case opc_return_register_finalizer: + return 0; + case opc_jsr: + case opc_jsr_w: + case opc_ret: + case opc_athrow: + return 1; + case opc_invokeinterface: + case opc_invokevirtual: + case opc_invokespecial: + case opc_invokestatic: + case opc_putfield: + case opc_getfield: + case opc_putstatic: + case opc_getstatic: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) return 1; + bci += 3; + if (opcode == opc_invokeinterface) bci += 2; + break; + + } + case opc_invokeresolved: + case opc_invokespecialresolved: + case opc_invokestaticresolved: + case opc_invokevfinal: + bci += 3; + break; + + case opc_multianewarray: + bci += 4; + break; + + case opc_wide: + opcode = code_base[bci+1]; + if (opcode == opc_iinc) { + bci += 6; + } else { + bci += 4; + } + break; + + default: + opcode = code_base[bci]; + fatal1("Undefined opcode %d\n", opcode); + break; + } + } + if (bci >= code_size) break; + } while (!(bc_stackinfo[bci] & BC_BRANCH_TARGET)); + return 0; +} +#endif // ZOMBIT_DETECTION + +void Thumb2_RegAlloc(Thumb2_Info *jinfo, unsigned *pregs, unsigned npregs) +{ + unsigned *locals_info = jinfo->locals_info; + unsigned i, j; + unsigned linfo; + unsigned score, max_score; + unsigned local; + unsigned nlocals = jinfo->method->max_locals(); + + for (i = 0; i < npregs; i++) { + max_score = 0; + for (j = 0; j < nlocals; j++) { + linfo = locals_info[j]; + + if (linfo & ((1<<LOCAL_ALLOCATED)|(1<<LOCAL_DOUBLE))) continue; + score = LOCAL_READS(linfo) + LOCAL_WRITES(linfo); + if (linfo & (1<<LOCAL_MODIFIED)) score = (score+1) >> 2; + if (linfo & (1<<LOCAL_REF)) score = score - (score >> 2); + if (linfo & (1<<LOCAL_LONG)) score = (score+1) >> 2; + if (score > max_score) max_score = score, local = j; + } + if (max_score < 2) break; + locals_info[local] |= 1<<LOCAL_ALLOCATED; + jinfo->jregs->r_local[local] = pregs[i]; + } +#ifdef T2EE_PRINT_REGUSAGE + if (t2ee_print_regusage) { + printf("Regalloc: %d physical registers allocated as follows\n", npregs); + for (j = 0; j < nlocals; j++) { + unsigned r = jinfo->jregs->r_local[j]; + if (r) { + unsigned typ = (locals_info[j] >> LOCAL_INT) & 0x1f; + printf(" ARM Reg R%d -> local %d (type = %s)\n", r, j, local_types[LOG2(typ)]); + } + } + } +#endif +} + +void Thumb2_pass2(Thumb2_Info *jinfo, unsigned stackdepth, unsigned bci) +{ + unsigned code_size = jinfo->code_size; + jubyte *code_base = jinfo->code_base; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + unsigned *locals_info = jinfo->locals_info; + unsigned check_zombie = 0; + //constantPoolCacheOop cp = jinfo->method->constants()->cache(); + + while (bci < code_size) { + unsigned stackinfo = bc_stackinfo[bci]; + unsigned bytecodeinfo; + unsigned opcode; + + if (stackinfo & BC_VISITED_P2) break; + JASSERT((int)stackdepth >= 0, "stackdepth < 0!!"); + bc_stackinfo[bci] = (stackinfo & BC_FLAGS_MASK) | stackdepth | BC_VISITED_P2; +#ifdef ZOMBIE_DETECTION + if (check_zombie || (stackinfo & BC_BRANCH_TARGET)) { + if (Thumb2_is_zombie(jinfo, bci)) { + printf("zombie code at %d\n", bci); + bc_stackinfo[bci] |= BC_ZOMBIE; + return; + } + check_zombie = 0; + } +#endif + opcode = code_base[bci]; +// printf("bci = 0x%04x, opcode = 0x%02x (%s), stackdepth = %d\n", bci, opcode, Bytecodes::name((Bytecodes::Code)opcode), stackdepth); + bytecodeinfo = bcinfo[opcode]; + if (!BCI_SPECIAL(bytecodeinfo)) { + if (BCI_ISLOCAL(bytecodeinfo)) { + unsigned local = BCI_LOCAL_N(bytecodeinfo); + unsigned local_type = BCI_LOCAL_TYPE(bytecodeinfo) + LOCAL_INT; + unsigned local_modified = 0; + unsigned linfo; + unsigned read_count, write_count; + + if (!BCI_ISLOCAL_N(bytecodeinfo)) local = code_base[bci+1]; + if (BCI_ISSTORE(bytecodeinfo)) local_modified = 1U << LOCAL_MODIFIED; + linfo = locals_info[local]; + read_count = LOCAL_READS(linfo); + write_count = LOCAL_WRITES(linfo); + if (local_modified) + write_count = LOCAL_INC_COUNT(write_count); + else + read_count = LOCAL_INC_COUNT(read_count); + + locals_info[local] |= (1 << local_type) | LOCAL_SET_COUNTS(read_count, write_count) | local_modified; + if (local_type == LOCAL_LONG || local_type == LOCAL_DOUBLE) { + locals_info[local+1] |= (1 << local_type) | LOCAL_SET_COUNTS(read_count, write_count) | local_modified; + } + } + bci += BCI_LEN(bytecodeinfo); + stackdepth += BCI_PUSH(bytecodeinfo) - BCI_POP(bytecodeinfo); + JASSERT(stackdepth <= (unsigned)jinfo->method->max_stack(), "stack over/under flow?"); + continue; + } + + switch (opcode) { + + case opc_goto: + bci += GET_JAVA_S2(code_base+bci+1); + break; + case opc_goto_w: + bci += GET_JAVA_U4(code_base+bci+1); + break; + + case opc_ifeq: + case opc_ifne: + case opc_iflt: + case opc_ifge: + case opc_ifgt: + case opc_ifle: + case opc_ifnull: + case opc_ifnonnull: + stackdepth -= 1; + Thumb2_pass2(jinfo, stackdepth, bci + GET_JAVA_S2(code_base+bci+1)); + check_zombie = 1; + bci += 3; + break; + + case opc_if_icmpeq: + case opc_if_icmpne: + case opc_if_icmplt: + case opc_if_icmpge: + case opc_if_icmpgt: + case opc_if_icmple: + case opc_if_acmpeq: + case opc_if_acmpne: + stackdepth -= 2; + Thumb2_pass2(jinfo, stackdepth, bci + GET_JAVA_S2(code_base+bci+1)); + check_zombie = 1; + bci += 3; + break; + + case opc_jsr: + Thumb2_pass2(jinfo, stackdepth+1, bci + GET_JAVA_S2(code_base+bci+1)); + bci += 3; + stackdepth = 0; + break; + case opc_jsr_w: + Thumb2_pass2(jinfo, stackdepth+1, bci + GET_JAVA_U4(code_base+bci+1)); + bci += 5; + break; + + case opc_ireturn: + case opc_lreturn: + case opc_freturn: + case opc_dreturn: + case opc_areturn: + case opc_return: + case opc_return_register_finalizer: + case opc_ret: + case opc_athrow: + // The test for BC_VISITED_P2 above will break out of the loop!!! + break; + + case opc_tableswitch: { + int low, high; + unsigned w; + unsigned *table; + unsigned nbci; + int def; + + stackdepth -= 1; + nbci = bci & ~3; + w = *(unsigned int *)(code_base + nbci + 8); + low = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 12); + high = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 4); + def = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 16); + + while (low <= high) { + int off; + w = *table++; + off = (int)BYTESEX_REVERSE(w); + Thumb2_pass2(jinfo, stackdepth, bci + off); + low++; + } + + check_zombie = 1; + bci += def; + break; + } + + case opc_lookupswitch: { + unsigned w; + unsigned nbci; + int def; + int npairs; // The Java spec says signed but must be >= 0?? + unsigned *table; + + stackdepth -= 1; + nbci = bci & ~3; + w = *(unsigned int *)(code_base + nbci + 4); + def = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 8); + npairs = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 16); + + for (int i = 0; i < npairs; i++) { + int off; + w = *table; + table += 2; + off = (int)BYTESEX_REVERSE(w); + Thumb2_pass2(jinfo, stackdepth, bci + off); + } + + check_zombie = 1; + bci += def; + break; + } + + case opc_getstatic: + case opc_putstatic: + case opc_getfield: + case opc_putfield: { + int index = GET_JAVA_U2(code_base+bci+1); + constantPoolOop pool = jinfo->method->constants(); + symbolOop sig = pool->signature_ref_at(index); + jbyte *base = sig->base(); + jbyte c = *base; + int stackchange; + + opcode = code_base[bci]; + if (opcode == opc_getfield || opcode == opc_putfield) + stackdepth -= 1; + stackchange = 1; + if (c == 'J' || c == 'D') stackchange = 2; + if (opcode == opc_getfield || opcode == opc_getstatic) + stackdepth += stackchange; + else + stackdepth -= stackchange; + bci += 3; + break; + } + + case opc_invokeresolved: + case opc_invokespecialresolved: + case opc_invokestaticresolved: + case opc_invokevfinal: + case opc_invokeinterface: + case opc_invokevirtual: + case opc_invokespecial: + case opc_invokestatic: { + int index = GET_JAVA_U2(code_base+bci+1); + constantPoolOop pool = jinfo->method->constants(); + //symbolOop name = pool->name_ref_at(index); + symbolOop sig = pool->signature_ref_at(index); + jbyte *base = sig->base(); + + //tty->print("%d: %s: %s\n", opcode, name->as_C_string(), sig->as_C_string()); + stackdepth += method_stackchange(base); + opcode = code_base[bci]; + bci += 3; + if (opcode == opc_invokeinterface) bci += 2; + if (opcode != opc_invokestatic && opcode != opc_invokestaticresolved) + stackdepth -= 1; + break; + } + + case opc_multianewarray: + stackdepth = (stackdepth - code_base[bci+3]) + 1; + bci += 4; + break; + + case opc_wide: + opcode = code_base[bci+1]; + if (opcode == opc_iinc) { + bci += 6; + } else { + bci += 4; + if (opcode == opc_iload || + opcode == opc_fload || opcode == opc_aload) + stackdepth += 1; + else if (opcode == opc_lload || opcode == opc_dload) + stackdepth += 2; + else if (opcode == opc_istore || + opcode == opc_fstore || opcode == opc_astore) + stackdepth -= 1; + else if (opcode == opc_lstore || opcode == opc_dstore) + stackdepth -= 2; + else if (opcode != opc_ret) + fatal1("Undefined wide opcode %d\n", opcode); + } + break; + + default: + opcode = code_base[bci]; + fatal1("Undefined opcode %d\n", opcode); + break; + } + } +} + +//------------------------------------------------------------------------------------- + +#define Thumb2 1 +#define ThumbEE 0 + +#define DA 0 +#define IA 1 +#define DB 2 +#define IB 3 + +#define PUSH_ED 0 +#define PUSH_EA 1 +#define PUSH_FD 2 +#define PUSH_FA 3 + +#define POP_FA 0 +#define POP_FD 1 +#define POP_EA 2 +#define POP_ED 3 + +#define ROR(imm, sh) (((imm) >> (sh)) | ((imm) << (32 - (sh)))) +#define ROL(imm, sh) (((imm) << (sh)) | ((imm) >> (32 - (sh)))) + +#define abs(i) ((i) < 0 ? -(i) : (i)) +#define U(i) ((i) < 0 ? 0 : 1) + +#define LS_STR 0 +#define LS_STRB 1 +#define LS_STRH 2 +#define LS_LDRSB 3 +#define LS_LDR 4 +#define LS_LDRB 5 +#define LS_LDRH 6 +#define LS_LDRSH 7 + +#define LS_IS_LDR(op) ((op) >= LS_LDRSB) +#define LS_IS_WORD(op) (((op) & 3) == LS_STR) +#define LS_IS_BYTE(op) (((op) & 3) == LS_STRB || (op) == LS_LDRSB) +#define LS_IS_HW(op) (((op) & 3) == LS_STRH || (op) == LS_LDRSH) + +static const unsigned t_ls_ops[16] = { + 0x5000, 0xf8400000, + 0x5400, 0xf8000000, + 0x5200, 0xf8200000, + 0x5600, 0xf9100000, + 0x5800, 0xf8500000, + 0x5c00, 0xf8100000, + 0x5a00, 0xf8300000, + 0x5e00, 0xf9300000, +}; + +#define DP_ADC 0 +#define DP_ADD 1 +#define DP_AND 2 +#define DP_ASR 3 +#define DP_BIC 4 +#define DP_CMN 5 +#define DP_CMP 6 +#define DP_EOR 7 +#define DP_LSL 8 +#define DP_LSR 9 +#define DP_MOV 10 +#define DP_MVN 11 +#define DP_ORN 12 +#define DP_ORR 13 +#define DP_ROR 14 +#define DP_RSB 15 +#define DP_SBC 16 +#define DP_SUB 17 +#define DP_TEQ 18 +#define DP_TST 19 +#define DP_MUL 20 + +static const unsigned n_ops[] = { + DP_SBC, // ADC x, y == SBC x, ~y + DP_SUB, // ADD x, y == SUB x, -y + DP_BIC, // AND x, y == BIX x, ~y + (unsigned)-1, // ASR + DP_AND, // BIC x, y == AND x, ~y + DP_CMP, // CMN x, y == CMP x, -y + DP_CMN, // CMP x, y == CMN x, -y + (unsigned)-1, // EOR + (unsigned)-1, // LSL + (unsigned)-1, // LSR + DP_MVN, // MOV x, y == MVN x, ~y + DP_MOV, // MVN x, y == MOV x, ~y + DP_ORR, // ORN x, y == ORR x, ~y + DP_ORN, // ORR x, y == ORN x, ~y + (unsigned)-1, // ROR + (unsigned)-1, // RSB + DP_ADC, // SBC x, y == ADC x, ~y + DP_ADD, // ADD x, y == SUB x, -y + (unsigned)-1, // TEQ + (unsigned)-1, // TST + (unsigned)-1, // MUL +}; + +#define N_OP(op) n_ops[(op)] + +static const unsigned t_dop_ops[] = { +// Rd, Rm, #N Rd, Rn, Rm + 0xf1400000, 0xeb400000, // ADC + 0xf1000000, 0xeb000000, // ADD + 0xf0000000, 0xea000000, // AND + 0xea4f0020, 0xfa40f000, // ASR + 0xf0200000, 0xea200000, // BIC + 0xf1100f00, 0xeb100f00, // CMN + 0xf1b00f00, 0xebb00f00, // CMP + 0xf0800000, 0xea800000, // EOR + 0xea4f0000, 0xfa00f000, // LSL + 0xea4f0010, 0xfa20f000, // LSR + 0xf04f0000, 0xea4f0000, // MOV + 0xf06f0000, 0xea6f0000, // MVN + 0xf0600000, 0xea600000, // ORN + 0xf0400000, 0xea400000, // ORR + 0xea4f0030, 0xfa6f0000, // ROR + 0xf1c00000, 0xebc00000, // RSB + 0xf1600000, 0xeb600000, // SBC + 0xf1a00000, 0xeba00000, // SUB + 0xf0900f00, 0xea900f00, // TEQ + 0xf0100f00, 0xea100f00, // TST + (unsigned)-1, 0xfb00f000, // MUL +}; + +#define DP_IMM(op) t_dop_ops[(op)*2] +#define DP_REG(op) t_dop_ops[(op)*2+1] + +#define VP_ADD 0 +#define VP_SUB 1 +#define VP_MUL 2 +#define VP_DIV 3 + +static const unsigned t_vop_ops[] = { + 0xee300a00, // VADD + 0xee300a40, // VSUB + 0xee200a00, // VMUL + 0xee800a00, // VDIV +}; + +#define VP_REG(op) t_vop_ops[op] + +#define T1_LS_OP(op) t_ls_ops[(op)*2] +#define T2_LS_OP(op) t_ls_ops[(op)*2+1] + +#define SHIFT_LSL 0 +#define SHIFT_LSR 1 +#define SHIFT_ASR 2 +#define SHIFT_ROR 3 +#define SHIFT_RRX 3 + +//------------------------------------------------------------------------------------ + +#define E_STR_IMM6(src, imm6) (0xce00 | ((imm6)<<3) | (src)) +#define E_LDR_IMM6(dst, imm6) (0xcc00 | ((imm6)<<3) | (dst)) +#define E_LDR_IMM5(dst, imm5) (0xcb00 | ((imm5)<<3) | (dst)) +#define E_LDR_IMM3(dst, base, imm3) (0xc800 | ((imm3)<<6) | ((base) << 3) | (dst)) + +#define T_MOV_IMM8(r, imm8) (0x2000 | ((r)<<8) | (imm8)) +#define T_MOV_BYTELANE(r, typ, b) (0xf04f0000 | ((typ) << 12) | ((r) << 8) | (b)) +#define T_MOV_ROT_IMM(r, ror, imm) \ + (0xf04f0000 | (((ror) & 0x10) << (26-4)) | (((ror) & 0xe) << (12-1)) | \ + (((ror) & 1) << 7) | ((r) << 8) | ((imm) & 0x7f)) +#define T_MOVW_IMM16(r, imm) \ + (0xf2400000 | (((imm) & 0xf000) << (16-12)) | (((imm) & 0x800) << (26-11)) | \ + (((imm) & 0x700) << (12-8)) | ((imm) & 0xff) | ((r) << 8)) +#define T_MOVT_IMM16(r, imm) \ + (0xf2c00000 | (((imm) & 0xf000) << (16-12)) | (((imm) & 0x800) << (26-11)) | \ + (((imm) & 0x700) << (12-8)) | ((imm) & 0xff) | ((r) << 8)) +#define T_MVN_BYTELANE(r, typ, b) (0xf06f0000 | ((typ) << 12) | ((r) << 8) | (b)) +#define T_MVN_ROT_IMM(r, ror, imm) (0xf06f0000 | (((ror) & 0x10) << (26-4)) | \ + (((ror) & 0xe) << (12-1)) | (((ror) & 1) << 7) | ((r) << 8) | ((imm) & 0x7f)) + +#define T_ORR_ROT_IMM(dst, src, ror, imm) (0xf0400000 | (((ror) & 0x10) << (26-4)) | \ + (((ror) & 0xe) << (12-1)) | (((ror) & 1) << 7) | ((src) << 16) | \ + ((dst) << 8) | ((imm) & 0x7f)) +#define T_ORN_ROT_IMM(dst, src, ror, imm) (0xf0600000 | (((ror) & 0x10) << (26-4)) | \ + (((ror) & 0xe) << (12-1)) | (((ror) & 1) << 7) | ((src) << 16) | \ + ((dst) << 8) | ((imm) & 0x7f)) + +#define T_STR_IMM5(src, base, imm5) (0x6000 | ((imm5) << 6) | ((base) << 3) | (src)) +#define T_STR_SP_IMM8(src, imm8) (0x9000 | ((src) << 8) | (imm8)) +#define T_STR_IMM12(src, base, imm12) (0xf8c00000 | ((src)<<12) | ((base)<<16) | (imm12)) +#define T_STR_IMM8(src, base, imm8, pre, wb) (0xf8400800 | ((src)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_LDR_IMM5(dst, base, imm5) (0x6800 | ((imm5) << 6) | ((base) << 3) | (dst)) +#define T_LDR_SP_IMM8(src, imm8) (0x9800 | ((dst) << 8) | (imm8)) +#define T_LDR_IMM12(dst, base, imm12) (0xf8d00000 | ((dst)<<12) | ((base)<<16) | (imm12)) +#define T_LDR_IMM8(src, base, imm8, pre, wb) (0xf8500800 | ((dst)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_STRB_IMM5(src, base, imm5) (0x7000 | ((imm5) << 6) | ((base) << 3) | (src)) +#define T_STRB_IMM12(src, base, imm12) (0xf8800000 | ((src)<<12) | ((base)<<16) | (imm12)) +#define T_STRB_IMM8(src, base, imm8, pre, wb) (0xf8000800 | ((src)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_LDRB_IMM5(dst, base, imm5) (0x7800 | ((imm5) << 6) | ((base) << 3) | (dst)) +#define T_LDRB_IMM12(dst, base, imm12) (0xf8900000 | ((dst)<<12) | ((base)<<16) | (imm12)) +#define T_LDRB_IMM8(dst, base, imm8, pre, wb) (0xf8100800 | ((dst)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_STRH_IMM5(dst, base, imm5) (0x8000 | ((imm5) << 6) | ((base) << 3) | (dst)) +#define T_STRH_IMM12(dst, base, imm12) (0xf8a00000 | ((dst)<<12) | ((base)<<16) | (imm12)) +#define T_STRH_IMM8(dst, base, imm8, pre, wb) (0xf8200800 | ((dst)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_LDRH_IMM5(dst, base, imm5) (0x8800 | ((imm5) << 6) | ((base) << 3) | (dst)) +#define T_LDRH_IMM12(dst, base, imm12) (0xf8b00000 | ((dst)<<12) | ((base)<<16) | (imm12)) +#define T_LDRH_IMM8(dst, base, imm8, pre, wb) (0xf8300800 | ((dst)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_LDRSH_IMM12(dst, base, imm12) (0xf9b00000 | ((dst)<<12) | ((base)<<16) | (imm12)) +#define T_LDRSH_IMM8(dst, base, imm8, pre, wb) (0xf9300800 | ((dst)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_LDRSB_IMM12(dst, base, imm12) (0xf9900000 | ((dst)<<12) | ((base)<<16) | (imm12)) +#define T_LDRSB_IMM8(dst, base, imm8, pre, wb) (0xf9100800 | ((dst)<<12) | \ + ((base)<<16) | ((pre)<<10) | (U(imm8)<<9) | ((wb)<<8) | abs(imm8)) + +#define T_LDRD_IMM(lo, hi, base, imm8, pre, wb) (0xe8500000 | ((base)<<16) | \ + ((lo) << 12) | ((hi)<<8) | ((pre)<<24) | (U(imm8)<<23) | ((wb)<<21) | abs(imm8)) +#define T_STRD_IMM(lo, hi, base, imm8, pre, wb) (0xe8400000 | ((base)<<16) | \ + ((lo) << 12) | ((hi)<<8) | ((pre)<<24) | (U(imm8)<<23) | ((wb)<<21) | abs(imm8)) + +#define T_LDREX(dst, base, off) (0xe8500f00 | ((base) << 16) | ((dst) << 12) | ((off) >> 2)) +#define T_STREX(dst, src, base, off) (0xe8400000 | ((base) << 16) | \ + ((src) << 12) | ((dst) << 8) | ((off >> 2))) + +#define T_STM8(base, regset) (0xc000 | ((base) << 8) | (regset)) +#define T_STM16(base, regset, st, wb) (0xe8000000 | ((st) << 23) | ((wb) << 21) | \ + ((base) << 16) | (regset)) + +#define T_LDM8(base, regset) (0xc800 | ((base) << 8) | (regset)) +#define T_LDM16(base, regset, st, wb) (0xe8100000 | ((st) << 23) | ((wb) << 21) | \ + ((base) << 16) | (regset)) +#define T_POP(regset) (0xbc00 | (((regset & (1<<ARM_PC)) >> ARM_PC) << 8) | (regset & 0xff)) +#define T_PUSH(regset) (0xb400 | (((regset & (1<<ARM_LR)) >> ARM_LR) << 8) | (regset & 0xff)) + +#define T1_LDR_STR_REG(op, xfer, base, off) ((op) | ((off) << 6) | ((base) << 3) | (xfer)) +#define T2_LDR_STR_REG(op, xfer, base, off, sh) ((op) | ((base) << 16) | ((xfer) << 12) | \ + ((sh)<<4) | (off)) + +#define T_CHKA(size, idx) (0xca00 | (((size) & 8) << (7-3)) | ((idx) << 3) | ((size) & 7)) +#define T_HBL(handler) (0xc300 | (handler)) +#define T_ENTER_LEAVE(enter) (0xf3bf8f0f | ((enter)<<4)) + +#define T1_ADD_IMM(dst, src, imm3) (0x1c00 | ((imm3) << 6) | ((src) << 3) | (dst)) +#define T2_ADD_IMM(r, imm8) (0x3000 | ((r) << 8) | (imm8)) +#define T3_ADD_BYTELANE(dst, src, typ, b) (0xf1000000 | ((src) << 16) | ((typ) << 12) | \ + ((dst) << 8) | (b)) +#define T3_ADD_ROT_IMM(dst, src, ror, imm) (0xf1000000 | ((src) << 16) | ((dst) << 8) | \ + (((ror) & 0x10) << (26-4)) | (((ror) & 0x0e) << (12-1)) | (((ror) & 1) << 7) | \ + ((imm) & 0x7f)) +#define T4_ADD_IMM(dst, src, imm) (0xf2000000 | ((src) << 16) | ((dst) << 8) | \ + (((imm) & 0x800) << (26-11)) | (((imm) & 0x700) << (12-8)) | ((imm) & 0xff)) + +#define T1_SUB_IMM(dst, src, imm3) (0x1e00 | ((imm3) << 6) | ((src) << 3) | (dst)) +#define T2_SUB_IMM(r, imm8) (0x3800 | ((r) << 8) | (imm8)) +#define T3_SUB_BYTELANE(dst, src, typ, b) (0xf1a00000 | ((src) << 16) | ((typ) << 12) | \ + ((dst) << 8) | (b)) +#define T3_SUB_ROT_IMM(dst, src, ror, imm) (0xf1a00000 | ((src) << 16) | ((dst) << 8) | \ + (((ror) & 0x10) << (26-4)) | (((ror) & 0x0e) << (12-1)) | (((ror) & 1) << 7) | \ + ((imm) & 0x7f)) +#define T4_SUB_IMM(dst, src, imm) (0xf2a00000 | ((src) << 16) | ((dst) << 8) | \ + (((imm) & 0x800) << (26-11)) | (((imm) & 0x700) << (12-8)) | ((imm) & 0xff)) + +#define T_DOP_BYTELANE(op, dst, src, typ, b) ((op) | ((dst) << 8) | ((src) << 16) | \ + ((typ) << 12) | (b)) +#define T_DOP_ROT_IMM(op, dst, src, ror, imm) ((op) | ((dst) << 8) | ((src) << 16) | \ + (((ror) & 0x10) << (26-4)) | (((ror) & 0x0e) << (12-1)) | (((ror) & 1) << 7) | \ + ((imm) & 0x7f)) +#define T_SHIFT_IMM(op, dst, src, imm) ((op) | ((dst) << 8) | (src) | \ + (((imm) & 3) << 6) | (((imm) & 0x1c) << (12-2))) +#define T_DOP_REG(op, dst, lho, rho, st, sh) ((op) | ((dst) << 8) | ((lho) << 16) | (rho) | \ + ((st) << 4) | (((sh) & 0x1c) << (12-2)) | (((sh) & 3) << 6)) +#define T3_ADD_BYTELANE(dst, src, typ, b) (0xf1000000 | ((src) << 16) | ((typ) << 12) | \ + ((dst) << 8) | (b)) + +#define T_CMP_IMM(src, imm) (0x2800 | ((src) << 8) | (imm)) +#define T_CMP_REG(lho, rho) (0x4280 | ((rho) << 3) | (lho)) + +#define T_NEG(dst, src) (0x4240 | (dst) | ((src) << 3)) +#define T_MVN(dst, src) (0x43c0 | (dst) | ((src) << 3)) +#define T_MOV(dst, src) (0x4600 | (((dst) & 8) << (7-3)) | ((src) << 3) | ((dst) & 7)) + +#define T_VMOVS_TOARM(dst, src) \ + (0xee100a10 | ((dst) << 12) | (((src) & 1) << 7) | (((src) & 0x1e)<<(16-1))) +#define T_VMOVS_TOVFP(dst, src) \ + (0xee000a10 | ((src) << 12) | (((dst) & 1) << 7) | (((dst) & 0x1e)<<(16-1))) + +#define T_VMOVD_TOARM(dst_lo, dst_hi, src) \ + (0xec500b10 | ((dst_lo) << 12) | ((dst_hi) << 16) | (((src) & 0x10)<<(5-4)) | ((src) & 0x0f)) +#define T_VMOVD_TOVFP(dst, src_lo, src_hi) \ + (0xec400b10 | ((src_lo) << 12) | ((src_hi) << 16) | (((dst) & 0x10)<<(5-4)) | ((dst) & 0x0f)) + +#define T_VOP_REG_S(op, dst, lho, rho) ((op) | \ + (((dst) & 1) << 22) | (((dst) & 0x1e) << (12-1)) | \ + (((lho) & 1) << 7) | (((lho) & 0x1e) << (16-1)) | \ + (((rho) & 1) << 5) | (((rho) & 0x1e) >> 1)) +#define T_VOP_REG_D(op, dst, lho, rho) ((op) | (1 << 8) | \ + (((dst) & 0x10) << (22-4)) | (((dst) & 0xf) << 12) | \ + (((lho) & 0x10) << (7-4)) | (((lho) & 0xf) << 16) | \ + (((rho) & 0x10) << (5-4)) | ((rho) & 0xf)) + +#define T_VCMP_S(lho, rho, e) (0xeeb40a40 | ((e) << 7) | \ + (((lho) & 1) << 22) | (((lho) & 0x1e) << (12-1)) | \ + (((rho) & 1) << 5) | (((rho) & 0x1e) >>1)) +#define T_VCMP_D(lho, rho, e) (0xeeb40b40 | ((e) << 7) | \ + (((lho) & 0x10) << (22-4)) | (((lho) & 0x0f) << 12) | \ + (((rho) & 0x10) << (5-4)) | ((rho) & 0x0f)) +#define T_VMRS(dst) (0xeef10a10 | ((dst) << 12)) + +#define T_MLA(res, lho, rho, a) \ + (0xfb000000 | ((res) << 8) | ((lho) << 16) | (rho) | ((a) << 12)) +#define T_UMULL(res_lo, res_hi, lho, rho) \ + (0xfba00000 | ((res_lo) << 12) | ((res_hi) << 8) | ((lho) << 16) | (rho)) + +#define T_BX(src) (0x4700 | ((src) << 3)) +#define T_TBH(base, idx) (0xe8d0f010 | ((base) << 16) | (idx)) + +#define T_SXTB(dst, src) (0xb240 | ((src) << 3) | (dst)) +#define T_SXTH(dst, src) (0xb200 | ((src) << 3) | (dst)) +#define T2_SXTB(dst, src) (0xfa4ff080 | ((dst) << 8) | (src)) +#define T2_SXTH(dst, src) (0xfa0ff080 | ((dst) << 8) | (src)) +#define T_UXTH(dst, src) (0xb280 | ((src) << 3) | (dst)) +#define T2_UXTH(dst, src) (0xfa1ff080 | ((dst) << 8) | (src)) + +int out_16(CodeBuf *codebuf, u32 s) +{ + codebuf->codebuf[codebuf->idx++] = s; + return 0; +} + +int out_16x2(CodeBuf *codebuf, u32 sx2) +{ + unsigned s1 = sx2 >> 16; + unsigned s2 = sx2 & 0xffff; + + out_16(codebuf, s1); + return out_16(codebuf, s2); +} + +int out_32(CodeBuf *codebuf, u32 w) +{ + *(u32 *)&(codebuf->codebuf[codebuf->idx]) = w; + codebuf->idx += 2; + return 0; +} + +u32 out_pos(CodeBuf *codebuf) +{ + return (u32)&(codebuf->codebuf[codebuf->idx]); +} + +u32 out_loc(CodeBuf *codebuf) +{ + return codebuf->idx * 2; +} + +#define CODE_ALIGN 64 +#define CODE_ALIGN_SIZE 64 + +u32 out_align(CodeBuf *codebuf, unsigned align) +{ + codebuf->idx += (((out_pos(codebuf) + (align-1)) & ~(align-1)) - out_pos(codebuf)) / sizeof(short); + return out_pos(codebuf); +} + +int thumb_single_shift(unsigned imm) +{ + unsigned lsl; + + if (!imm) return -1; + lsl = 0; + while (!(imm & 0x80000000)) { + imm <<= 1; + lsl++; + } + if (lsl >= 24) return -1; + if ((imm & 0xff000000) == imm) return lsl+8; + return -1; +} + +int thumb_bytelane(u32 imm) +{ + unsigned b1 = imm & 0xff; + unsigned b2 = (imm >> 8) & 0xff; + unsigned b3 = (imm >> 16) & 0xff; + unsigned b4 = imm >> 24; + int mov_type = -1; + + if (b1 == b3 && b2 == 0 && b4 == 0) mov_type = 1; + if (b1 == b2 && b1 == b3 && b1 == b4) mov_type = 3; + if (b2 == b4 && b1 == 0 && b3 == 0) mov_type = 2; + if (imm < 256) mov_type = 0; + return mov_type; +} + +int mov_imm(CodeBuf *codebuf, Reg r, u32 imm) +{ + int mov_type, rol; + + if (Thumb2) { + if (r < ARM_R8 && imm < 256) + return out_16(codebuf, T_MOV_IMM8(r, imm)); + mov_type = thumb_bytelane(imm); + if (mov_type >= 0) { + if (mov_type == 2) imm >>= 8; + return out_16x2(codebuf, T_MOV_BYTELANE(r, mov_type, (imm & 0xff))); + } + mov_type = thumb_bytelane(~imm); + if (mov_type >= 0) { + imm = ~imm; + if (mov_type == 2) imm >>= 8; + return out_16x2(codebuf, T_MVN_BYTELANE(r, mov_type, (imm & 0xff))); + } + rol = thumb_single_shift(imm); + if (rol >= 0) + return out_16x2(codebuf, T_MOV_ROT_IMM(r, rol, ROL(imm, rol))); + rol = thumb_single_shift(~imm); + if (rol >= 0) + return out_16x2(codebuf, T_MVN_ROT_IMM(r, rol, ROL(~imm, rol))); + if ((imm & ~0xffff) == 0) + return out_16x2(codebuf, T_MOVW_IMM16(r, imm & 0xffff)); + if (r < ARM_R8) { + rol = thumb_single_shift(imm & ~0xff); + if (rol >= 0) { + out_16(codebuf, T_MOV_IMM8(r, imm & 0xff)); + return out_16x2(codebuf, T_ORR_ROT_IMM(r, r, rol, ROL(imm & ~0xff, rol))); + } + } + out_16x2(codebuf, T_MOVW_IMM16(r, imm & 0xffff)); + return out_16x2(codebuf, T_MOVT_IMM16(r, imm >> 16)); + } + J_Unimplemented(); +} + +int load_store_reg_no_wb(CodeBuf *codebuf, u32 op, Reg xfer, Reg base, Reg offset, + u32 shift, int pre) +{ + if (pre) { + if (xfer < ARM_R8 && base < ARM_R8 && offset < ARM_R8) { + if (ThumbEE) { + if ((shift == 0 && LS_IS_BYTE(op)) || (shift == 1 && LS_IS_HW(op)) || + (shift == 2 && LS_IS_WORD(op))) + return out_16(codebuf, T1_LDR_STR_REG(T1_LS_OP(op), xfer, base, offset)); + } else if (shift == 0) + return out_16(codebuf, T1_LDR_STR_REG(T1_LS_OP(op), xfer, base, offset)); + } + if (shift < 4) + return out_16x2(codebuf, T2_LDR_STR_REG(T2_LS_OP(op), xfer, base, offset, shift)); + } + J_Unimplemented(); +} + +static int add_reg(CodeBuf *codebuf, u32 dst, u32 lho, u32 rho); + +int load_store_reg(CodeBuf *codebuf, u32 op, Reg xfer, Reg base, Reg offset, + u32 shift, int pre, int wb) +{ + int rc = load_store_reg_no_wb(codebuf, op, xfer, base, offset, shift, pre); + if (wb) { + return add_reg(codebuf, base, base, offset); + } + return rc; +} + +int str_reg(CodeBuf *codebuf, Reg src, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_STR, src, base, offset, shift, pre, wb); +} + +int ldr_reg(CodeBuf *codebuf, Reg dst, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_LDR, dst, base, offset, shift, pre, wb); +} + +int strb_reg(CodeBuf *codebuf, Reg src, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_STRB, src, base, offset, shift, pre, wb); +} + +int ldrb_reg(CodeBuf *codebuf, Reg dst, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_LDRB, dst, base, offset, shift, pre, wb); +} + +int strh_reg(CodeBuf *codebuf, Reg src, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_STRH, src, base, offset, shift, pre, wb); +} + +int ldrh_reg(CodeBuf *codebuf, Reg dst, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_LDRH, dst, base, offset, shift, pre, wb); +} + +int ldrsh_reg(CodeBuf *codebuf, Reg dst, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_LDRSH, dst, base, offset, shift, pre, wb); +} + +int ldrsb_reg(CodeBuf *codebuf, Reg dst, Reg base, Reg offset, u32 shift, int pre, int wb) +{ + return load_store_reg(codebuf, LS_LDRSB, dst, base, offset, shift, pre, wb); +} + +int ldrex_imm(CodeBuf *codebuf, Reg dst, Reg base, unsigned offset) +{ + if (Thumb2) { + if ((offset & 3) == 0 && offset < 256 * 4) { + return out_16x2(codebuf, T_LDREX(dst, base, offset)); + } + } + J_Unimplemented(); +} + +int strex_imm(CodeBuf *codebuf, Reg dst, Reg src, Reg base, unsigned offset) +{ + if (Thumb2) { + if ((offset & 3) == 0 && offset < 256 * 4) { + return out_16x2(codebuf, T_STREX(dst, src, base, offset)); + } + } + J_Unimplemented(); +} + +int str_imm(CodeBuf *codebuf, Reg src, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (base < ARM_R8 && src < ARM_R8 && uoff < 128 && (uoff & 3) == 0) + return out_16(codebuf, T_STR_IMM5(src, base, uoff>>2)); + if (base == ARM_SP && src < ARM_R8 && uoff < 1024 && (uoff &3) ==0) + return out_16(codebuf, T_STR_SP_IMM8(src, uoff>>2)); + if (ThumbEE && base == ARM_R9 && src < ARM_R8 && uoff < 256 && (uoff & 3) == 0) + return out_16(codebuf, E_STR_IMM6(src, uoff>>2)); + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_STR_IMM12(src, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_STR_IMM8(src, base, offset, pre, wb)); + JASSERT(base != ARM_IP && src != ARM_IP, "src or base == IP in str_imm"); + mov_imm(codebuf, ARM_IP, offset); + return str_reg(codebuf, src, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int ldr_imm(CodeBuf *codebuf, Reg dst, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (base < ARM_R8 && dst < ARM_R8 && uoff < 128 && (uoff & 3) ==0) + return out_16(codebuf, T_LDR_IMM5(dst, base, uoff>>2)); + if (base == ARM_SP && dst < ARM_R8 && uoff < 1024 & (uoff & 3) == 0) + return out_16(codebuf, T_LDR_SP_IMM8(dst, uoff>>2)); + if (ThumbEE && base == ARM_R9 && dst < ARM_R8 && uoff < 256 && (uoff & 3) == 0) + return out_16(codebuf, E_LDR_IMM6(dst, uoff>>2)); + if (ThumbEE && base == ARM_R10 && dst < ARM_R8 && uoff < 128 && (uoff & 3) == 0) + return out_16(codebuf, E_LDR_IMM5(dst, uoff>>2)); + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_LDR_IMM12(dst, base, uoff)); + } else { + if (ThumbEE && pre && !wb && offset <= 0 && offset > -32 && (uoff & 3) == 0 && + base < ARM_R8 && dst < ARM_R8) + return out_16(codebuf, E_LDR_IMM3(dst, base, -offset >> 2)); + if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_LDR_IMM8(dst, base, offset, pre, wb)); + } + JASSERT(base != ARM_IP, "base == IP in ldr_imm"); + mov_imm(codebuf, ARM_IP, offset); + return ldr_reg(codebuf, dst, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int strb_imm(CodeBuf *codebuf, Reg src, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (base < ARM_R8 && src < ARM_R8 && uoff < 32) + return out_16(codebuf, T_STRB_IMM5(src, base, uoff)); + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_STRB_IMM12(src, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_STRB_IMM8(src, base, offset, pre, wb)); + JASSERT(base != ARM_IP && src != ARM_IP, "src or base == IP in str_imm"); + mov_imm(codebuf, ARM_IP, offset); + return strb_reg(codebuf, src, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int ldrb_imm(CodeBuf *codebuf, Reg dst, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (base < ARM_R8 && dst < ARM_R8 && uoff < 32) + return out_16(codebuf, T_LDRB_IMM5(dst, base, uoff)); + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_LDRB_IMM12(dst, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_LDRB_IMM8(dst, base, offset, pre, wb)); + JASSERT(base != ARM_IP, "base == IP in ldr_imm"); + mov_imm(codebuf, ARM_IP, offset); + return ldrb_reg(codebuf, dst, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int strh_imm(CodeBuf *codebuf, Reg src, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (base < ARM_R8 && src < ARM_R8 && uoff < 64 && (uoff & 1) == 0) + return out_16(codebuf, T_STRH_IMM5(src, base, uoff>>1)); + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_STRH_IMM12(src, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_STRH_IMM8(src, base, offset, pre, wb)); + JASSERT(base != ARM_IP && src != ARM_IP, "src or base == IP in str_imm"); + mov_imm(codebuf, ARM_IP, offset); + return strh_reg(codebuf, src, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int ldrh_imm(CodeBuf *codebuf, Reg dst, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (base < ARM_R8 && dst < ARM_R8 && uoff < 64 && (uoff & 1) == 0) + return out_16(codebuf, T_LDRH_IMM5(dst, base, uoff>>1)); + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_LDRH_IMM12(dst, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_LDRH_IMM8(dst, base, offset, pre, wb)); + JASSERT(base != ARM_IP, "base == IP in ldr_imm"); + mov_imm(codebuf, ARM_IP, offset); + return ldrh_reg(codebuf, dst, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int ldrsh_imm(CodeBuf *codebuf, Reg dst, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_LDRSH_IMM12(dst, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_LDRSH_IMM8(dst, base, offset, pre, wb)); + JASSERT(base != ARM_IP, "base == IP in ldr_imm"); + mov_imm(codebuf, ARM_IP, offset); + return ldrsh_reg(codebuf, dst, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int ldrsb_imm(CodeBuf *codebuf, Reg dst, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (pre && !wb && offset >= 0) { + if (uoff < (1 << 12)) + return out_16x2(codebuf, T_LDRSB_IMM12(dst, base, uoff)); + } else if (offset < 256 && offset > -256) + return out_16x2(codebuf, T_LDRSB_IMM8(dst, base, offset, pre, wb)); + JASSERT(base != ARM_IP, "base == IP in ldr_imm"); + mov_imm(codebuf, ARM_IP, offset); + return ldrsb_reg(codebuf, dst, base, ARM_IP, 0, pre, wb); + } + J_Unimplemented(); +} + +int add_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm); + +int ldrd_imm(CodeBuf *codebuf, Reg dst_lo, Reg dst_hi, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (offset < 256 * 4 && offset > -256 * 4 && (offset & 3) == 0) + return out_16x2(codebuf, T_LDRD_IMM(dst_lo, dst_hi, base, offset>>2, pre, wb)); + if (pre && !wb) { + add_imm(codebuf, ARM_IP, base, offset); + return out_16x2(codebuf, T_LDRD_IMM(dst_lo, dst_hi, ARM_IP, 0, 1, 0)); + } + } + J_Unimplemented(); +} + +int strd_imm(CodeBuf *codebuf, Reg src_lo, Reg src_hi, Reg base, int offset, int pre, int wb) +{ + unsigned uoff; + + if (!pre && !wb) pre = 1, offset = 0; + uoff = (unsigned)offset; + if (Thumb2) { + if (offset < 256 * 4 && offset > -256 * 4 && (offset & 3) == 0) + return out_16x2(codebuf, T_STRD_IMM(src_lo, src_hi, base, offset>>2, pre, wb)); + if (pre && !wb) { + add_imm(codebuf, ARM_IP, base, offset); + return out_16x2(codebuf, T_STRD_IMM(src_lo, src_hi, ARM_IP, 0, 1, 0)); + } + } + J_Unimplemented(); +} + +int stm(CodeBuf *codebuf, u32 regset, u32 base, u32 st, u32 wb) +{ + JASSERT(regset != 0, "regset != 0 in stm"); + if (Thumb2) { + if (!ThumbEE && base < ARM_R8 && (regset & ~0xff) == 0 && st == IA && wb) + return out_16(codebuf, T_STM8(base, regset)); + if (base == ARM_SP) { + if ((regset & ~0x40ff) == 0 && st == DB && wb) + return out_16(codebuf, T_PUSH(regset)); + } + if ((regset & -regset) == regset) + return str_imm(codebuf, LOG2(regset), base, (st & 1) ? 4 : -4, (st & 2) >> 1, wb); + if (st == PUSH_EA || st == PUSH_FD) + return out_16x2(codebuf, T_STM16(base, regset, st, wb)); + return out_16x2(codebuf, T_STM16(base, regset, st, wb)); + } + J_Unimplemented(); +} + +int ldm(CodeBuf *codebuf, u32 regset, u32 base, u32 st, u32 wb) +{ + JASSERT(regset != 0, "regset != 0 in stm"); + if (Thumb2) { + if (!ThumbEE && base < ARM_R8 && (regset & ~0xff) == 0 && st == IA && wb) + return out_16(codebuf, T_LDM8(base, regset)); + if (base == ARM_SP) { + if ((regset & ~0x80ff) == 0 && st == IA && wb) + return out_16(codebuf, T_POP(regset)); + } + if ((regset & -regset) == regset) + return ldr_imm(codebuf, LOG2(regset), base, (st & 1) ? 4 : -4, (st & 2) >> 1, wb); + if (st == POP_EA || st == POP_FD) + return out_16x2(codebuf, T_LDM16(base, regset, st, wb)); + } + J_Unimplemented(); +} + +int dop_reg(CodeBuf *codebuf, u32 op, u32 dst, u32 lho, u32 rho, u32 sh_typ, u32 shift) +{ + unsigned s = 0; + if (op != DP_MUL) s = 1 << 20; +// JASSERT(dst != ARM_PC, "Terrible things happen if dst == PC && S bit set"); + return out_16x2(codebuf, T_DOP_REG(DP_REG(op)|s, dst, lho, rho, sh_typ, shift)); +} + +int dop_reg_preserve(CodeBuf *codebuf, u32 op, u32 dst, u32 lho, u32 rho, u32 sh_typ, u32 shift) +{ + return out_16x2(codebuf, T_DOP_REG(DP_REG(op), dst, lho, rho, sh_typ, shift)); +} + +int sxtb(CodeBuf *codebuf, u32 dst, u32 src) +{ + if (dst < ARM_R8 && src < ARM_R8) + return out_16(codebuf, T_SXTB(dst, src)); + return out_16x2(codebuf, T2_SXTB(dst, src)); +} + +int sxth(CodeBuf *codebuf, u32 dst, u32 src) +{ + if (dst < ARM_R8 && src < ARM_R8) + return out_16(codebuf, T_SXTH(dst, src)); + return out_16x2(codebuf, T2_SXTH(dst, src)); +} + +int uxth(CodeBuf *codebuf, u32 dst, u32 src) +{ + if (dst < ARM_R8 && src < ARM_R8) + return out_16(codebuf, T_UXTH(dst, src)); + return out_16x2(codebuf, T2_UXTH(dst, src)); +} + +int mov_reg(CodeBuf *codebuf, u32 dst, u32 src) +{ + if (dst == src) return 0; + if (dst == ARM_PC) return out_16(codebuf, T_BX(src)); + return out_16(codebuf, T_MOV(dst, src)); +// return dop_reg(codebuf, DP_MOV, dst, 0, src, SHIFT_LSL, 0); +} + +int mvn_reg(CodeBuf *codebuf, u32 dst, u32 src) +{ + if (dst < ARM_R8 && src < ARM_R8) + return out_16(codebuf, T_MVN(dst, src)); + return dop_reg(codebuf, DP_MVN, dst, 0, src, SHIFT_LSL, 0); +} + +int vmov_reg_s_toVFP(CodeBuf *codebuf, u32 dst, u32 src) +{ + return out_16x2(codebuf, T_VMOVS_TOVFP(dst, src)); +} + +int vmov_reg_s_toARM(CodeBuf *codebuf, u32 dst, u32 src) +{ + return out_16x2(codebuf, T_VMOVS_TOARM(dst, src)); +} + +int vmov_reg_d_toVFP(CodeBuf *codebuf, u32 dst, u32 src_lo, u32 src_hi) +{ + return out_16x2(codebuf, T_VMOVD_TOVFP(dst, src_lo, src_hi)); +} + +int vmov_reg_d_toARM(CodeBuf *codebuf, u32 dst_lo, u32 dst_hi, u32 src) +{ + return out_16x2(codebuf, T_VMOVD_TOARM(dst_lo, dst_hi, src)); +} + +int vop_reg_s(CodeBuf *codebuf, u32 op, u32 dst, u32 lho, u32 rho) +{ + return out_16x2(codebuf, T_VOP_REG_S(VP_REG(op), dst, lho, rho)); +} + +int vop_reg_d(CodeBuf *codebuf, u32 op, u32 dst, u32 lho, u32 rho) +{ + return out_16x2(codebuf, T_VOP_REG_D(VP_REG(op), dst, lho, rho)); +} + +int vcmp_reg_s(CodeBuf *codebuf, u32 lho, u32 rho, unsigned e) +{ + return out_16x2(codebuf, T_VCMP_S(lho, rho, e)); +} + +int vcmp_reg_d(CodeBuf *codebuf, u32 lho, u32 rho, unsigned e) +{ + return out_16x2(codebuf, T_VCMP_D(lho, rho, e)); +} + +int vmrs(CodeBuf *codebuf, u32 dst) +{ + return out_16x2(codebuf, T_VMRS(dst)); +} + +int add_reg(CodeBuf *codebuf, u32 dst, u32 lho, u32 rho) +{ + return dop_reg(codebuf, DP_ADD, dst, lho, rho, SHIFT_LSL, 0); +} + +int cmp_reg(CodeBuf *codebuf, Reg lho, Reg rho) +{ + if (lho < ARM_R8 && rho < ARM_R8) + return out_16(codebuf, T_CMP_REG(lho, rho)); + return dop_reg(codebuf, DP_CMP, 0x0f, lho, rho, SHIFT_LSL, 0); +} + +int add_reg_shift(CodeBuf *codebuf, u32 dst, u32 lho, u32 rho, u2 sh_typ, u32 shift) +{ + return dop_reg(codebuf, DP_ADD, dst, lho, rho, sh_typ, shift); +} + +int add_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + int imm_type, rol; + + if (imm == 0) return mov_reg(codebuf, dst, src); + if (Thumb2) { + if (dst < ARM_R8 && src < ARM_R8) { + if (imm < 8) + return out_16(codebuf, T1_ADD_IMM(dst, src, imm)); + if (-imm < 8) + return out_16(codebuf, T1_SUB_IMM(dst, src, -imm)); + if (src == dst) { + if (imm < 256) + return out_16(codebuf, T2_ADD_IMM(src, imm)); + if (-imm < 256) + return out_16(codebuf, T2_SUB_IMM(src, -imm)); + } + } + imm_type = thumb_bytelane(imm); + if (imm_type >= 0) { + if (imm_type == 2) imm >>= 8; + return out_16x2(codebuf, T3_ADD_BYTELANE(dst, src, imm_type, (imm & 0xff))); + } + imm_type = thumb_bytelane(-imm); + if (imm_type >= 0) { + imm = -imm; + if (imm_type == 2) imm >>= 8; + return out_16x2(codebuf, T3_SUB_BYTELANE(dst, src, imm_type, (imm & 0xff))); + } + rol = thumb_single_shift(imm); + if (rol >= 0) + return out_16x2(codebuf, T3_ADD_ROT_IMM(dst, src, rol, ROL(imm, rol))); + rol = thumb_single_shift(-imm); + if (rol >= 0) + return out_16x2(codebuf, T3_SUB_ROT_IMM(dst, src, rol, ROL(-imm, rol))); + if (imm < (1 << 12)) + return out_16x2(codebuf, T4_ADD_IMM(dst, src, imm)); + if (-imm < (1 << 12)) + return out_16x2(codebuf, T4_SUB_IMM(dst, src, -imm)); + mov_imm(codebuf, ARM_IP, imm); + return add_reg(codebuf, dst, src, ARM_IP); + } + J_Unimplemented(); +} + +int sub_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + return add_imm(codebuf, dst, src, -imm); +} + +int dop_imm_s(CodeBuf *codebuf, u32 op, u32 dst, u32 src, u32 imm, unsigned s) +{ + int imm_type, rol; + unsigned n_op, n_imm; + + JASSERT(op == DP_ADC || op == DP_ADD || op == DP_AND || op == DP_BIC || op == DP_CMN || + op == DP_CMP || op == DP_EOR || op == DP_MOV || op == DP_MVN || + op == DP_ORN || op == DP_ORR || op == DP_RSB || op == DP_SBC || + op == DP_SUB || op == DP_TEQ || op == DP_TST, "bad op"); + if (op == DP_CMP || op == DP_CMN || op == DP_TEQ || op == DP_TST) dst = 0x0f; + if (op == DP_MOV || op == DP_MVN) src = 0x0f; + imm_type = thumb_bytelane(imm); + if (imm_type >= 0) { + if (imm_type == 2) imm >>= 8; + return out_16x2(codebuf, T_DOP_BYTELANE(DP_IMM(op)|s, dst, src, imm_type, (imm & 0xff))); + } + rol = thumb_single_shift(imm); + if (rol >= 0) + return out_16x2(codebuf, T_DOP_ROT_IMM(DP_IMM(op)|s, dst, src, rol, ROL(imm, rol))); + n_op = N_OP(op); + if (n_op != (unsigned)-1) { + n_imm = ~imm; + if (op == DP_ADD || op == DP_SUB || op == DP_CMP || op == DP_CMN) n_imm = -imm; + imm_type = thumb_bytelane(n_imm); + if (imm_type >= 0) { + if (imm_type == 2) n_imm >>= 8; + return out_16x2(codebuf, T_DOP_BYTELANE(DP_IMM(n_op)|s, dst, src, imm_type, (n_imm & 0xff))); + } + rol = thumb_single_shift(n_imm); + if (rol >= 0) + return out_16x2(codebuf, T_DOP_ROT_IMM(DP_IMM(n_op)|s, dst, src, rol, ROL(n_imm, rol))); + } + mov_imm(codebuf, ARM_IP, imm); + return out_16x2(codebuf, T_DOP_REG(DP_REG(op)|s, dst, src, ARM_IP, SHIFT_LSL, 0)); +} + +int dop_imm(CodeBuf *codebuf, u32 op, u32 dst, u32 src, u32 imm) +{ + return dop_imm_s(codebuf, op, dst, src, imm, 1<<20); +} + +int dop_imm_preserve(CodeBuf *codebuf, u32 op, u32 dst, u32 src, u32 imm) +{ + return dop_imm_s(codebuf, op, dst, src, imm, 0); +} + +int shift_imm(CodeBuf *codebuf, u32 op, u32 dst, u32 src, u32 imm) +{ + imm &= 31; + if (imm == 0) + return mov_reg(codebuf, dst, src); + else + return out_16x2(codebuf, T_SHIFT_IMM(DP_IMM(op), dst, src, imm)); +} + +int rsb_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + if (dst < ARM_R8 && src < ARM_R8 && imm == 0) + return out_16(codebuf, T_NEG(dst, src)); + return dop_imm(codebuf, DP_RSB, dst, src, imm); +} + +int adc_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + return dop_imm(codebuf, DP_ADC, dst, src, imm); +} + +int asr_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + return shift_imm(codebuf, DP_ASR, dst, src, imm); +} + +int eor_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + return dop_imm(codebuf, DP_EOR, dst, src, imm); +} + +int and_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + return dop_imm(codebuf, DP_AND, dst, src, imm); +} + +int orr_imm(CodeBuf *codebuf, u32 dst, u32 src, u32 imm) +{ + return dop_imm(codebuf, DP_ORR, dst, src, imm); +} + +int cmp_imm(CodeBuf *codebuf, Reg src, u32 imm) +{ + if (src <= ARM_R8 && imm < 256) return out_16(codebuf, T_CMP_IMM(src, imm)); + return dop_imm(codebuf, DP_CMP, 0x0f, src, imm); +} + +int tst_imm(CodeBuf *codebuf, Reg src, u32 imm) +{ + return dop_imm(codebuf, DP_TST, 0x0f, src, imm); +} + +int hbl(CodeBuf *codebuf, unsigned handler) +{ + mov_imm(codebuf, ARM_IP, 0); + str_imm(codebuf, ARM_IP, ARM_IP, 0, 1, 0); +#if 0 + if ((Thumb2 && ThumbEE)) + return out_16(codebuf, T_HBL(handler)); + if (TESTING) + return mov_imm(codebuf, ARM_R8, handler); + J_Unimplemented(); +#endif +} + +#if 0 +int enter_leave(CodeBuf *codebuf, unsigned enter) +{ + if ((Thumb2 && ThumbEE)) + return out_16x2(codebuf, T_ENTER_LEAVE(enter)); + J_Unimplemented(); +} +#endif + +int tbh(CodeBuf *codebuf, Reg base, Reg idx) +{ + out_16x2(codebuf, T_TBH(base, idx)); +} + +int umull(CodeBuf *codebuf, u32 res_lo, u32 res_hi, u32 lho, u32 rho) +{ + return out_16x2(codebuf, T_UMULL(res_lo, res_hi, lho, rho)); +} + +int mla(CodeBuf *codebuf, u32 res, u32 lho, u32 rho, u32 a) +{ + return out_16x2(codebuf, T_MLA(res, lho, rho, a)); +} + +#define COND_EQ 0 +#define COND_NE 1 +#define COND_LT 2 +#define COND_GE 3 +#define COND_GT 4 +#define COND_LE 5 +#define COND_CS 6 +#define COND_CC 7 +#define COND_MI 8 +#define COND_PL 9 + +static unsigned conds[] = { + 0x0, + 0x1, + 0xb, + 0xa, + 0xc, + 0xd, + 0x2, + 0x3, + 0x4, + 0x5, +}; + +#define NEG_COND(cond) ((cond) ^ 1) + +#define T_B(uoff) (0xe000 | ((uoff) & 0x7ff)) +#define T_BW(uoff) (0xf0009000 | \ + (((uoff) & (1<<23)) << (26-23)) | \ + (((~(uoff) & (1<<22)) >> 22) ^ (((uoff) & (1<<23)) >> 23)) << 13 | \ + (((~(uoff) & (1<<21)) >> 21) ^ (((uoff) & (1<<23)) >> 23)) << 11 | \ + (((uoff) & 0x1ff800) << (16-11)) | \ + ((uoff) & 0x7ff)) +#define T_BL(uoff) (0xf000d000 | \ + (((uoff) & (1<<23)) << (26-23)) | \ + (((~(uoff) & (1<<22)) >> 22) ^ (((uoff) & (1<<23)) >> 23)) << 13 | \ + (((~(uoff) & (1<<21)) >> 21) ^ (((uoff) & (1<<23)) >> 23)) << 11 | \ + (((uoff) & 0x1ff800) << (16-11)) | \ + ((uoff) & 0x7ff)) +#define T_BLX(uoff) (0xf000c000 | \ + (((uoff) & (1<<23)) << (26-23)) | \ + (((~(uoff) & (1<<22)) >> 22) ^ (((uoff) & (1<<23)) >> 23)) << 13 | \ + (((~(uoff) & (1<<21)) >> 21) ^ (((uoff) & (1<<23)) >> 23)) << 11 | \ + (((uoff) & 0x1ff800) << (16-11)) | \ + ((uoff) & 0x7ff)) +#define T_BCC(cond, uoff) (0xd000 | (conds[cond] << 8) | ((uoff) & 0xff)) +#define T_BCCW(cond, uoff) (0xf0008000 | \ + (conds[cond] << 22) | \ + (((uoff) & (1<<19)) << (26-19)) | \ + (((uoff) & (1<<18)) >> (18-11)) | \ + (((uoff) & (1<<17)) >> (17-13)) | \ + (((uoff) & 0x1f800) << (16-11)) | \ + ((uoff) & 0x7ff)) +#define T_BLX_REG(r) (0x4780 | ((r) << 3)) +#define T_CBZ(r, uoff) (0xb100 | (((uoff) & 0x1f) << 3) | (((uoff) & 0x20) << (8-5)) | ((r) & 7)) +#define T_CBNZ(r, uoff) (0xb900 | (((uoff) & 0x1f) << 3) | (((uoff) & 0x20) << (8-5)) | ((r) & 7)) + +#define T_IT(cond, mask) (0xbf00 | (conds[cond] << 4) | (mask)) + +#define IT_MASK_T 8 + +#define PATCH(loc) do { \ + unsigned oldidx = codebuf->idx; \ + codebuf->idx = (loc) >> 1; \ + +#define HCTAP \ + codebuf->idx = oldidx; \ + } while (0) + +int forward_16(CodeBuf *codebuf) +{ + int loc = out_loc(codebuf); + out_16(codebuf, T_UNDEFINED_16); + return loc; +} + +int forward_32(CodeBuf *codebuf) +{ + int loc = out_loc(codebuf); + out_32(codebuf, T_UNDEFINED_32); + return loc; +} + +int it(CodeBuf *codebuf, unsigned cond, unsigned mask) +{ + return out_16(codebuf, T_IT(cond, mask)); +} + +void t2_bug_align(CodeBuf *codebuf) +{ + unsigned pc = (unsigned)&codebuf->codebuf[codebuf->idx]; + if ((pc & 0xffe) != 0xffe) return; + mov_reg(codebuf, ARM_R0, ARM_R0); +} + +void t2_bug_fix(CodeBuf *codebuf, int offset) +{ + unsigned pc = (unsigned)&codebuf->codebuf[codebuf->idx]; + if ((pc & 0xffe) != 0xffe) return; + if (offset >= 0 || offset < -(4096+4)) return; + mov_reg(codebuf, ARM_R0, ARM_R0); +} + +int branch_uncond(CodeBuf *codebuf, unsigned dest) +{ + unsigned loc = (codebuf->idx * 2) + 4; + int offset; + unsigned uoff; + + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest - loc; + if (offset >= -(1<<10) && offset < (1<<10)) { + uoff = offset; + return out_16(codebuf, T_B(uoff)); + } + t2_bug_fix(codebuf, offset); + if (offset >= -(1<<23) && offset < (1<<23)) { + uoff = offset; + return out_16x2(codebuf, T_BW(uoff)); + } + J_Unimplemented(); +} + +int branch_uncond_patch(CodeBuf *codebuf, unsigned loc, unsigned dest) +{ + int offset; + unsigned uoff; + unsigned oldidx; + int rc; + + oldidx = codebuf->idx; + codebuf->idx = loc >> 1; + loc += 4; + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest - loc; + t2_bug_fix(codebuf, offset); + if (offset >= -(1<<23) && offset < (1<<23)) { + uoff = offset & ((1<<24)-1); + rc = out_16x2(codebuf, T_BW(uoff)); + codebuf->idx = oldidx; + return rc; + } + J_Unimplemented(); +} + +int branch_narrow_patch(CodeBuf *codebuf, unsigned loc) +{ + int offset; + unsigned uoff; + unsigned oldidx; + unsigned dest; + int rc; + + dest = codebuf->idx * 2; + oldidx = codebuf->idx; + codebuf->idx = loc >> 1; + loc += 4; + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest - loc; + if (offset >= -(1<<10) && offset < (1<<10)) { + uoff = offset & ((1<<11)-1); + rc = out_16(codebuf, T_B(uoff)); + codebuf->idx = oldidx; + return rc; + } + J_Unimplemented(); +} + +int branch(CodeBuf *codebuf, unsigned cond, unsigned dest) +{ + unsigned loc = (codebuf->idx * 2) + 4; + int offset; + unsigned uoff; + + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest - loc; + if (offset >= -(1<<7) && offset < (1<<7)) { + uoff = offset; + return out_16(codebuf, T_BCC(cond, uoff)); + } + t2_bug_fix(codebuf, offset); + if (offset >= -(1<<19) && offset < (1<<19)) { + uoff = offset; + return out_16x2(codebuf, T_BCCW(cond, uoff)); + } + J_Unimplemented(); +} + +int bcc_patch(CodeBuf *codebuf, unsigned cond, unsigned loc) +{ + int offset; + unsigned uoff; + unsigned oldidx; + unsigned dest; + int rc; + + dest = codebuf->idx * 2; + oldidx = codebuf->idx; + codebuf->idx = loc >> 1; + loc += 4; + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest-loc; + if (offset >= -(1<<7) && offset < (1<<7)) { + uoff = offset; + rc = out_16(codebuf, T_BCC(cond, uoff)); + codebuf->idx = oldidx; + return rc; + } + J_Unimplemented(); +} + +int bl(CodeBuf *codebuf, unsigned dest) +{ + unsigned loc = (unsigned)&codebuf->codebuf[codebuf->idx] + 4; + int offset; + unsigned uoff; + + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest - loc; + t2_bug_fix(codebuf, offset); + if (offset >= -(1<<23) && offset < (1<<23)) { + uoff = offset; + return out_16x2(codebuf, T_BL(uoff)); + } + J_Unimplemented(); +} + +int blx(CodeBuf *codebuf, unsigned dest) +{ + unsigned loc = (unsigned)&codebuf->codebuf[codebuf->idx] + 4; + int offset; + unsigned uoff; + + JASSERT((dest & 3) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + loc &= ~1; + offset = dest - loc; + t2_bug_fix(codebuf, offset); + if (offset >= -(1<<23) && offset < (1<<23)) { + uoff = offset; + return out_16x2(codebuf, T_BLX(uoff)); + } + J_Unimplemented(); +} + +int branch_patch(CodeBuf *codebuf, unsigned cond, unsigned loc, unsigned dest) +{ + int offset; + unsigned uoff; + unsigned oldidx; + int rc; + + oldidx = codebuf->idx; + codebuf->idx = loc >> 1; + loc += 4; + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest - loc; + t2_bug_fix(codebuf, offset); + if (offset >= -(1<<19) && offset < (1<<19)) { + uoff = offset & ((1<<20)-1); + rc = out_16x2(codebuf, T_BCCW(cond, uoff)); + codebuf->idx = oldidx; + return rc; + } + J_Unimplemented(); +} + +int blx_reg(CodeBuf *codebuf, Reg r) +{ + return out_16(codebuf, T_BLX_REG(r)); +} + +int cbz_patch(CodeBuf *codebuf, Reg r, unsigned loc) +{ + unsigned offset; + unsigned oldidx; + unsigned dest; + int rc; + + dest = codebuf->idx * 2; + oldidx = codebuf->idx; + codebuf->idx = loc >> 1; + loc += 4; + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest-loc; + if (r < ARM_R8 && offset < 64) { + rc = out_16(codebuf, T_CBZ(r, offset)); + codebuf->idx = oldidx; + return rc; + } + J_Unimplemented(); +} + +int cbnz_patch(CodeBuf *codebuf, Reg r, unsigned loc) +{ + unsigned offset; + unsigned oldidx; + unsigned dest; + int rc; + + dest = codebuf->idx * 2; + oldidx = codebuf->idx; + codebuf->idx = loc >> 1; + loc += 4; + JASSERT((dest & 1) == 0 && (loc & 1) == 0, "unaligned code"); + dest >>= 1; + loc >>= 1; + offset = dest-loc; + if (r < ARM_R8 && offset < 64) { + rc = out_16(codebuf, T_CBNZ(r, offset)); + codebuf->idx = oldidx; + return rc; + } + J_Unimplemented(); +} + +int chka(CodeBuf *codebuf, u32 size, u32 idx) +{ + cmp_reg(codebuf, idx, size); + it(codebuf, COND_CS, IT_MASK_T); + bl(codebuf, handlers[H_ARRAYBOUND]); +} + +//----------------------------------------------------------------------------------- + +void Thumb2_Push_Multiple(CodeBuf *codebuf, Reg *regs, unsigned nregs) +{ + unsigned regset = 0; + unsigned regmask; + unsigned i; + Reg r; + + JASSERT(nregs > 0, "nregs must be > 0"); + if (nregs == 1) { + str_imm(codebuf, regs[0], Rstack, -4, 1, 1); + return; + } + for (i = 0; i < nregs; i++) { + r = regs[i]; + if (!IS_ARM_INT_REG(r)) J_Unimplemented(); + regmask = 1<<r; + if (regset != 0 && regmask >= (regset & -regset)) { + stm(codebuf, regset, Rstack, PUSH_FD, 1); + regset = 0; + } + regset |= regmask; + } + stm(codebuf, regset, Rstack, PUSH_FD, 1); +} + +void Thumb2_Pop_Multiple(CodeBuf *codebuf, Reg *regs, unsigned nregs) +{ + unsigned regset = 0; + unsigned regmask; + unsigned i; + Reg r; + + JASSERT(nregs > 0, "nregs must be > 0"); + if (nregs == 1) { + ldr_imm(codebuf, regs[0], Rstack, 4, 0, 1); + return; + } + i = nregs; + do { + i--; + r = regs[i]; + if (!IS_ARM_INT_REG(r)) J_Unimplemented(); + regmask = 1<<r; + if (regmask <= (regset & -regset)) { + ldm(codebuf, regset, Rstack, POP_FD, 1); + regset = 0; + } + regset |= regmask; + } while (i > 0); + ldm(codebuf, regset, Rstack, POP_FD, 1); +} + +#if 0 +int load_multiple(CodeBuf *codebuf, Reg base, Reg *regs, u32 nregs, u32 st, u32 wb) +{ + unsigned regset = 0; + unsigned regmask; + unsigned pre = 0; + int dir = 1; + unsigned u; + Reg r; + + if (st == IB || st == DB) pre = 4; + if (st == DA || st == DB) dir = -4; + JASSERT(nregs > 0, "nregs must be > 0"); + if (nregs == 1) + return ldr_imm(codebuf, regs[0], base, dir, pre, wb); + if (dir > 0) { + u = 0; + do { + r = regs[u]; + regmask = 1<<r; + if (regset != 0 && regmask >= regset) { + if (!wb && base != ARM_IP) { + mov_reg(codebuf, ARM_IP, base); + base = ARM_IP; + } + ldm(codebuf, regset, base, st, 1); + regset = 0; + } + regset |= regmask; + } while (++u < nregs); + ldm(codebuf, regset, base, st, wb); + } else { + u = nregs; + do { + u--; + r = regs[u]; + regmask = 1<<r; + if (regmask <= (regset & -regset)) { + if (!wb && base != ARM_IP) { + mov_reg(codebuf, ARM_IP, base); + base = ARM_IP; + } + ldm(codebuf, regset, base, st, 1); + regset = 0; + } + regset |= regmask; + } while (u > 0); + ldm(codebuf, regset, base, st, wb); + } +} +#endif + +int mov_multiple(CodeBuf *codebuf, Reg *dst, Reg *src, unsigned nregs) +{ + unsigned u, n, p; + unsigned smask = 0; + unsigned dmask = 0; + unsigned free_mask, free_reg; + + for (u = 0, n = 0; u < nregs; u++) { + JASSERT(dst[u] != ARM_IP, "mov_multiple cannot be used for ARM_IP"); + JASSERT(src[u] != ARM_IP, "mov_multiple cannot be used for ARM_IP"); + if (dst[u] != src[u]) { + dst[n] = dst[u]; + src[n++] = src[u]; + } + } + while (n) { + // Find a reg which is in the dst reg set but not the src reg set + smask = 0; + dmask = 0; + for (u = 0; u < n; u++) { + smask |= (1 << src[u]); + dmask |= (1 << dst[u]); + } + free_mask = dmask & ~smask; + if (!free_mask) { + // No such reg => must use IP + Reg r = dst[0]; + mov_reg(codebuf, ARM_IP, r); + for (u = 0; u < n; u++) { + if (src[u] == r) src[u] = ARM_IP; + } + smask ^= (1<<r) | (1<<ARM_IP); + free_mask = dmask & ~smask; + JASSERT(free_mask, "still no free reg after using ARM_IP?"); + } + free_reg = LOG2(free_mask); + for (u = 0, p = 0; u < n; u++) { + if (dst[u] == free_reg) { + mov_reg(codebuf, dst[u], src[u]); + } else { + dst[p] = dst[u]; + src[p++] = src[u]; + } + } + n--; + } + return 0; +} + +#define TOS(jstack) ((jstack)->stack[(jstack)->depth-1]) +#define TOSM1(jstack) ((jstack)->stack[(jstack)->depth-2]) +#define TOSM2(jstack) ((jstack)->stack[(jstack)->depth-3]) +#define TOSM3(jstack) ((jstack)->stack[(jstack)->depth-4]) + +#define POP(jstack) ((jstack)->stack[--(jstack)->depth]) +#define PUSH(jstack, r) ((jstack)->stack[(jstack)->depth++] = (r)) +#define SWAP(jstack) do { \ + Reg r = (jstack)->stack[(jstack)->depth-1]; \ + (jstack)->stack[(jstack)->depth-1] = (jstack)->stack[(jstack)->depth-2]; \ + (jstack)->stack[(jstack)->depth-2] = r; \ + } while (0) + +#define JSTACK_REG(jstack) jstack_reg(jstack) +#define JSTACK_PREFER(jstack, prefer) jstack_prefer(jstack, prefer) + +static const unsigned last_clear_bit[] = { + 3, // 0000 + 3, // 0001 + 3, // 0010 + 3, // 0011 + 3, // 0100 + 3, // 0101 + 3, // 0110 + 3, // 0111 + 2, // 1000 + 2, // 1001 + 2, // 1010 + 2, // 1011 + 1, // 1100 + 1, // 1101 + 0, // 1110 + 0, // 1111 +}; + +#define LAST_CLEAR_BIT(mask) last_clear_bit[mask] + +unsigned jstack_reg(Thumb2_Stack *jstack) +{ + unsigned *stack = jstack->stack; + unsigned depth = jstack->depth; + unsigned mask = 0; + unsigned r; + unsigned i; + + for (i = 0; i < depth; i++) mask |= 1 << stack[i]; + mask &= (1 << STACK_REGS) - 1; + JASSERT(mask != (1 << STACK_REGS) - 1, "No free reg in push"); + r = LAST_CLEAR_BIT(mask); + return r; +} + +unsigned jstack_prefer(Thumb2_Stack *jstack, Reg prefer) +{ + unsigned *stack = jstack->stack; + unsigned depth = jstack->depth; + unsigned mask = 0; + unsigned r; + unsigned i; + + for (i = 0; i < depth; i++) mask |= 1 << stack[i]; + mask &= (1 << STACK_REGS) - 1; + if ((prefer & ~mask) & 0x0f) mask |= (~prefer & ((1 << STACK_REGS) - 1)); + JASSERT(mask != (1 << STACK_REGS) - 1, "No free reg in push"); + r = LAST_CLEAR_BIT(mask); + return r; +} + +void Thumb2_Fill(Thumb2_Info *jinfo, unsigned required) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned *stack = jstack->stack; + unsigned depth = jstack->depth; + unsigned mask = 0; + unsigned tofill; + unsigned r, i; + + if (depth >= required) return; + tofill = required - depth; + for (i = depth; i > 0;) { + i--; + mask |= 1 << stack[i]; + stack[i+tofill] = stack[i]; + } + mask &= (1 << STACK_REGS) - 1; + for (i = 0; i < tofill; i++) { + JASSERT(mask != (1 << STACK_REGS) - 1, "Fill failed!!!"); + r = LAST_CLEAR_BIT(mask); + mask |= (1 << r); + stack[i] = r; + } + jstack->depth = depth + tofill; + Thumb2_Pop_Multiple(jinfo->codebuf, stack, tofill); +} + +static const unsigned bitcount[] = { + 0, // 0000 + 1, // 0001 + 1, // 0010 + 2, // 0011 + 1, // 0100 + 2, // 0101 + 2, // 0110 + 3, // 0111 + 1, // 1000 + 2, // 1001 + 2, // 1010 + 3, // 1011 + 2, // 1100 + 3, // 1101 + 3, // 1110 + 4, // 1111 +}; + +#define BITCOUNT(mask) bitcount[mask] + +// Thumb2_Spill:- +// required - ensure that at least this many registers are available +// exclude - bitmask, do not count these registers as available +// +// The no. of available regs (STACK_REGS) less the no. of registers in +// exclude must be >= the number required, otherwise this function loops! +// +// Typical usage is +// +// Thumb2_Spill(jinfo, 2, 0); // get 2 free regs +// r_res_lo = PUSH(jinfo->jstack, JSTACK_REG(jinfo->jstack)); +// r_res_hi = PUSH(jinfo->jstack, JSTACK_REG(jinfo->jstack)); +// +// Use the exclude mask when you do not want a subsequent call to +// JSTACK_REG to return a particular register or registers. This can +// be useful, for example, with long (64) bit operations. Eg. In the +// following we use it to ensure that the hi inputs are not clobbered +// by the lo result as part of the intermediate calculation. +// +// Thumb2_Fill(jinfo, 4); +// exclude = (1<<rho_hi)|(1<<lho_hi); +// rho_lo = POP(jstack); +// rho_hi = POP(jstack); +// lho_lo = POP(jstack); +// lho_hi = POP(jstack); +// Thumb2_Spill(jinfo, 2, exclude); +// res_hi = PUSH(jstack, JSTACK_PREFER(jstack, ~exclude)); // != rho_hi or lho_hi +// res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~exclude)); // != rho_hi or lho_hi +// dop_reg(jinfo->codebuf, DP_ADD, res_lo, lho_lo, rho_lo, SHIFT_LSL, 0); +// dop_reg(jinfo->codebuf, DP_ADC, res_hi, lho_hi, rho_hi, SHIFT_LSL, 0); +// +void Thumb2_Spill(Thumb2_Info *jinfo, unsigned required, unsigned exclude) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned *stack = jstack->stack; + unsigned depth = jstack->depth; + unsigned mask; + unsigned i; + unsigned tospill = 0; + + exclude &= (1 << STACK_REGS) - 1; + if (depth <= (STACK_REGS - required) && exclude == 0) return; + while (1) { + mask = 0; + for (i = tospill; i < depth; i++) mask |= 1 << stack[i]; + mask &= ((1 << STACK_REGS) - 1); + mask |= exclude; + if (STACK_REGS - BITCOUNT(mask) >= required) break; + tospill++; + } + if (tospill == 0) return; + Thumb2_Push_Multiple(jinfo->codebuf, stack, tospill); + for (i = tospill; i < depth; i++) + stack[i-tospill] = stack[i]; + jstack->depth = depth - tospill; + JASSERT((int)jstack->depth >= 0, "Stack underflow"); +} + +// Thumb2_Tmp:- +// Allocate a temp reg for use in local code generation. +// exclude is a bit mask of regs not to use. +// A max of 2 regs can be guaranteed (ARM_IP & ARM_LR) +// If allocating 2 regs you must include the reg you got the +// first time in the exclude list. Otherwise you just get +// the same reg again. +Reg Thumb2_Tmp(Thumb2_Info *jinfo, unsigned exclude) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned *stack = jstack->stack; + unsigned depth = jstack->depth; + unsigned mask; + unsigned i; + + mask = 0; + for (i = 0; i < depth; i++) mask |= 1 << stack[i]; + mask |= exclude; + for (i = 0; i < STACK_REGS; i++) + if ((mask & (1<<i)) == 0) return i; + if ((mask & (1<<ARM_IP)) == 0) return ARM_IP; + if ((mask & (1<<ARM_LR)) == 0) return ARM_LR; + JASSERT(0, "failed to allocate a tmp reg"); +} + +void Thumb2_Flush(Thumb2_Info *jinfo) +{ + Thumb2_Stack *jstack = jinfo->jstack; + + if (jstack->depth > 0) + Thumb2_Push_Multiple(jinfo->codebuf, jstack->stack, jstack->depth); + jstack->depth = 0; +} + +// Call this when we are about to corrupt a local +// The local may already be on the stack +// For example +// iload 0 +// iconst 2 +// istore 0 +// istore 1 +// Without this check the code generated would be (r4 is local 0, r5 is local 1) +// mov r4, #2 +// mov r5, r4 +// With this check the code should be +// mov r3, r4 +// mov r4, #2 +// mov r5, r3 +// This is not ideal, but is better than the previous:-) +// +void Thumb2_Corrupt(Thumb2_Info *jinfo, unsigned r, unsigned ignore) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned *stack = jstack->stack; + unsigned depth = jstack->depth; + unsigned r_new, mask; + unsigned i; + + if (ignore >= depth) return; +// JASSERT(depth >= ignore, "Cant ignore more than the whole stack!!"); + if (IS_SREG(r)) return; + depth -= ignore; + for (i = 0; i < depth; i++) { + if (r == stack[i]) { + Thumb2_Spill(jinfo, 1, 0); + depth = jstack->depth - ignore; + r_new = JSTACK_REG(jstack); + mov_reg(jinfo->codebuf, r_new, r); + for (i = 0; i < depth; i++) if (r == stack[i]) stack[i] = r_new; + break; + } + } +} + +unsigned Thumb2_ResultLocal(Thumb2_Info *jinfo, unsigned bci) +{ + unsigned opc = jinfo->code_base[bci]; + if (jinfo->bc_stackinfo[bci] & BC_BRANCH_TARGET) return 0; + if (opc < opc_istore || opc > opc_astore_3) return 0; + if (opc == opc_istore || opc == opc_fstore || opc == opc_astore) + return jinfo->jregs->r_local[jinfo->code_base[bci+1]]; + if ((opc >= opc_istore_0 && opc <= opc_istore_3) || + (opc >= opc_fstore_0 && opc <= opc_fstore_3) || + (opc >= opc_astore_0 && opc <= opc_astore_3)) + return jinfo->jregs->r_local[(opc-opc_istore_0)&3]; + return 0; +} + +static const unsigned char dOps[] = { + DP_ADD, DP_ADC, VP_ADD, VP_ADD, + DP_SUB, DP_SBC, VP_SUB, VP_SUB, + DP_MUL, 0, VP_MUL, VP_MUL, + 0, 0, VP_DIV, VP_DIV, + 0, 0, 0, 0, + 0, 0, 0, 0, + DP_LSL, 0, + DP_ASR, 0, + DP_LSR, 0, + DP_AND, DP_AND, DP_ORR, DP_ORR, DP_EOR, DP_EOR, +}; + +unsigned Thumb2_Imm(Thumb2_Info *jinfo, unsigned imm, unsigned next_bci) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r; + unsigned next_op; + + if (!(jinfo->bc_stackinfo[next_bci] & BC_BRANCH_TARGET)) { + next_op = jinfo->code_base[next_bci]; + if (next_op > OPC_LAST_JAVA_OP) { + if (Bytecodes::is_defined((Bytecodes::Code)next_op)) + next_op = (unsigned)Bytecodes::java_code((Bytecodes::Code)next_op); + } + switch (next_op) { + case opc_istore: + case opc_fstore: + case opc_astore: { + unsigned local = jinfo->code_base[next_bci+1]; + r = jinfo->jregs->r_local[local]; + if (r) { + Thumb2_Corrupt(jinfo, r, 0); + mov_imm(jinfo->codebuf, r, imm); + return 2; + } + break; + } + case opc_istore_0: + case opc_istore_1: + case opc_istore_2: + case opc_istore_3: + case opc_fstore_0: + case opc_fstore_1: + case opc_fstore_2: + case opc_fstore_3: + case opc_astore_0: + case opc_astore_1: + case opc_astore_2: + case opc_astore_3: { + unsigned local = (jinfo->code_base[next_bci]-opc_istore_0) & 3; + r = jinfo->jregs->r_local[local]; + if (r) { + Thumb2_Corrupt(jinfo, r, 0); + mov_imm(jinfo->codebuf, r, imm); + return 1; + } + break; + } + case opc_iadd: + case opc_isub: + case opc_ishl: + case opc_ishr: + case opc_iushr: + case opc_iand: + case opc_ior: + case opc_ixor: { + unsigned len = 0; + unsigned r_lho; + + Thumb2_Fill(jinfo, 1); + r_lho = POP(jstack); + + r = Thumb2_ResultLocal(jinfo, next_bci+1); + if (r) { + Thumb2_Corrupt(jinfo, r, 0); + len = Bytecodes::length_for((Bytecodes::Code)jinfo->code_base[next_bci+1]); + } else { + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + } + if (next_op == opc_ishl || next_op == opc_ishr || next_op == opc_iushr) + shift_imm(jinfo->codebuf, dOps[next_op-opc_iadd], r, r_lho, imm); + else + dop_imm(jinfo->codebuf, dOps[next_op-opc_iadd], r, r_lho, imm); + return 1+len; + } + + case opc_idiv: { + unsigned len = 0; + unsigned r_lho; + unsigned abs_imm = abs((int)imm); + + if ((imm & -imm) == abs_imm) { + unsigned l2_imm = LOG2(abs_imm); + unsigned r_lho; + + if (imm == 0) break; + if (imm == 1) return 1; + + Thumb2_Fill(jinfo, 1); + r_lho = POP(jstack); + + r = Thumb2_ResultLocal(jinfo, next_bci+1); + if (r) { + Thumb2_Corrupt(jinfo, r, 0); + len = Bytecodes::length_for((Bytecodes::Code)jinfo->code_base[next_bci+1]); + } else { + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + } + + if (abs_imm != 1) { + unsigned r_tmp = r_lho; + if (abs_imm != 2) { + r_tmp = Thumb2_Tmp(jinfo, (1<<r_lho)); + asr_imm(jinfo->codebuf, r_tmp, r_lho, 31); + } + add_reg_shift(jinfo->codebuf, r, r_lho, r_tmp, SHIFT_LSR, 32-l2_imm); + asr_imm(jinfo->codebuf, r, r, l2_imm); + } + if ((int)imm < 0) + rsb_imm(jinfo->codebuf, r, r, 0); + return 1+len; + } + break; + } + } + } + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + mov_imm(jinfo->codebuf, r, imm); + return 0; +} + +void Thumb2_ImmX2(Thumb2_Info *jinfo, unsigned lo, unsigned hi) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lo, r_hi; + + Thumb2_Spill(jinfo, 2, 0); + r_hi = PUSH(jstack, JSTACK_REG(jstack)); + r_lo = PUSH(jstack, JSTACK_REG(jstack)); + mov_imm(jinfo->codebuf, r_lo, lo); + mov_imm(jinfo->codebuf, r_hi, hi); +} + +#define LOCAL_OFFSET(local, stackdepth, nlocals) ((stackdepth)*4 + FRAME_SIZE + ((nlocals)-1-(local))*4) + +void load_local(Thumb2_Info *jinfo, Reg r, unsigned local, unsigned stackdepth) +{ +#ifdef USE_RLOCAL + ldr_imm(jinfo->codebuf, r, Rlocals, -local * 4, 1, 0); +#else + int nlocals = jinfo->method->max_locals(); + ldr_imm(jinfo->codebuf, r, Rstack, LOCAL_OFFSET(local, stackdepth, nlocals), 1, 0); +#endif +} + +void store_local(Thumb2_Info *jinfo, Reg r, unsigned local, unsigned stackdepth) +{ +#ifdef USE_RLOCAL + str_imm(jinfo->codebuf, r, Rlocals, -local << 2, 1, 0); +#else + int nlocals = jinfo->method->max_locals(); + str_imm(jinfo->codebuf, r, Rstack, LOCAL_OFFSET(local, stackdepth, nlocals), 1, 0); +#endif +} + +void Thumb2_Load(Thumb2_Info *jinfo, int local, unsigned stackdepth) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r; + + r = jinfo->jregs->r_local[local]; + if (r) { + PUSH(jstack, r); + } else { + int nlocals = jinfo->method->max_locals(); + + Thumb2_Spill(jinfo, 1, 0); + JASSERT(stackdepth >= jstack->depth, "negative stack offset?"); + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + load_local(jinfo, r, local, stackdepth); + } +} + +void Thumb2_LoadX2(Thumb2_Info *jinfo, int local, unsigned stackdepth) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lo, r_hi; + int nlocals = jinfo->method->max_locals(); + + r_hi = jinfo->jregs->r_local[local]; + if (r_hi) { + r_lo = jinfo->jregs->r_local[local+1]; + if (r_lo) { + PUSH(jstack, r_hi); + PUSH(jstack, r_lo); + } else { + Thumb2_Spill(jinfo, 1, 0); + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + PUSH(jstack, r_hi); + r_lo = PUSH(jstack, JSTACK_REG(jstack)); + load_local(jinfo, r_lo, local+1, stackdepth); + } + } else { + r_lo = jinfo->jregs->r_local[local+1]; + if (r_lo) { + Thumb2_Spill(jinfo, 1, 0); + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + r_hi = PUSH(jstack, JSTACK_REG(jstack)); + load_local(jinfo, r_hi, local, stackdepth); + PUSH(jstack, r_lo); + } else { + Thumb2_Spill(jinfo, 2, 0); + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + r_hi = PUSH(jstack, JSTACK_REG(jstack)); + r_lo = PUSH(jstack, JSTACK_REG(jstack)); + load_local(jinfo, r_hi, local, stackdepth); + load_local(jinfo, r_lo, local+1, stackdepth); + } + } +} + +void Thumb2_Store(Thumb2_Info *jinfo, int local, unsigned stackdepth) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r, r_local; + int nlocals = jinfo->method->max_locals(); + + Thumb2_Fill(jinfo, 1); + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + r = POP(jstack); + r_local = jinfo->jregs->r_local[local]; + if (r_local) { + Thumb2_Corrupt(jinfo, r_local, 0); + mov_reg(jinfo->codebuf, r_local, r); + } else { + store_local(jinfo, r, local, stackdepth); + } +} + +void Thumb2_StoreX2(Thumb2_Info *jinfo, int local, unsigned stackdepth) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lo, r_hi; + unsigned r_local_lo, r_local_hi; + int nlocals = jinfo->method->max_locals(); + + Thumb2_Fill(jinfo, 2); + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + r_lo = POP(jstack); + r_hi = POP(jstack); + stackdepth -= 2; + + r_local_hi = jinfo->jregs->r_local[local]; + if (r_local_hi) { + Thumb2_Corrupt(jinfo, r_local_hi, 0); + mov_reg(jinfo->codebuf, r_local_hi, r_hi); + } else { + store_local(jinfo, r_hi, local, stackdepth-jstack->depth); + } + + r_local_lo = jinfo->jregs->r_local[local+1]; + if (r_local_lo) { + Thumb2_Corrupt(jinfo, r_local_lo, 0); + mov_reg(jinfo->codebuf, r_local_lo, r_lo); + } else { + store_local(jinfo, r_lo, local+1, stackdepth-jstack->depth); + } +} + +void Thumb2_Xaload(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_index, r_array, r_value; + unsigned op = opc - (unsigned)opc_iaload; + unsigned r_tmp; + + Thumb2_Fill(jinfo, 2); + r_index = POP(jstack); + r_array = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_tmp = Thumb2_Tmp(jinfo, (1<<r_array)|(1<<r_index)); + r_value = JSTACK_REG(jstack); + PUSH(jstack, r_value); + ldr_imm(jinfo->codebuf, r_tmp, r_array, 8, 1, 0); + chka(jinfo->codebuf, r_tmp, r_index); + if (opc == opc_baload) { + add_reg(jinfo->codebuf, r_tmp, r_array, r_index); + ldrsb_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } else if (opc == opc_caload) { + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 1); + ldrh_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } else if (opc == opc_saload) { + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 1); + ldrsh_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } else { + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 2); + ldr_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } +} + +void Thumb2_X2aload(Thumb2_Info *jinfo) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_index, r_array, r_lo, r_hi; + unsigned r_tmp; + + Thumb2_Fill(jinfo, 2); + r_index = POP(jstack); + r_array = POP(jstack); + Thumb2_Spill(jinfo, 2, 0); + r_tmp = Thumb2_Tmp(jinfo, (1<<r_array)|(1<<r_index)); + r_hi = PUSH(jstack, JSTACK_REG(jstack)); + r_lo = PUSH(jstack, JSTACK_REG(jstack)); + ldr_imm(jinfo->codebuf, r_tmp, r_array, 8, 1, 0); + chka(jinfo->codebuf, r_tmp, r_index); + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 3); + ldrd_imm(jinfo->codebuf, r_lo, r_hi, r_tmp, 16, 1, 0); +} + +void Thumb2_Xastore(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_value, r_index, r_array; + unsigned op = opc - (unsigned)opc_iastore; + unsigned r_tmp; + + Thumb2_Fill(jinfo, 3); + r_value = POP(jstack); + r_index = POP(jstack); + r_array = POP(jstack); + r_tmp = Thumb2_Tmp(jinfo, (1<<r_array)|(1<<r_index)|(1<<r_value)); + ldr_imm(jinfo->codebuf, r_tmp, r_array, 8, 1, 0); + chka(jinfo->codebuf, r_tmp, r_index); + if (opc == opc_bastore) { + add_reg(jinfo->codebuf, r_tmp, r_array, r_index); + strb_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } else if (opc == opc_castore || opc == opc_sastore) { + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 1); + strh_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } else { + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 2); + str_imm(jinfo->codebuf, r_value, r_tmp, 12, 1, 0); + } +} + +void Thumb2_X2astore(Thumb2_Info *jinfo) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lo, r_hi, r_index, r_array; + unsigned r_tmp; + + Thumb2_Fill(jinfo, 4); + r_lo = POP(jstack); + r_hi = POP(jstack); + r_index = POP(jstack); + r_array = POP(jstack); + r_tmp = Thumb2_Tmp(jinfo, (1<<r_array)|(1<<r_index)|(1<<r_lo)|(1<<r_hi)); + ldr_imm(jinfo->codebuf, r_tmp, r_array, 8, 1, 0); + chka(jinfo->codebuf, r_tmp, r_index); + add_reg_shift(jinfo->codebuf, r_tmp, r_array, r_index, SHIFT_LSL, 3); + strd_imm(jinfo->codebuf, r_lo, r_hi, r_tmp, 16, 1, 0); +} + +void Thumb2_Pop(Thumb2_Info *jinfo, unsigned n) +{ + Thumb2_Stack *jstack = jinfo->jstack; + + while (n > 0 && jstack->depth > 0) { + POP(jstack); + n--; + } + if (n > 0) add_imm(jinfo->codebuf, Rstack, Rstack, n * 4); +} + +void Thumb2_Dup(Thumb2_Info *jinfo, unsigned n) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned *stack = jstack->stack; + unsigned depth; + unsigned i; + + Thumb2_Fill(jinfo, n+1); + depth = jstack->depth; + for (i = 0; i <= n; i++) + stack[depth-i] = stack[depth-i-1]; + stack[depth-n-1] = stack[depth]; + jstack->depth = depth + 1; +} + +void Thumb2_Dup2(Thumb2_Info *jinfo, unsigned n) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned *stack = jstack->stack; + unsigned depth; + unsigned i; + + Thumb2_Fill(jinfo, n+2); + depth = jstack->depth; + for (i = 0; i <= n+1; i++) + stack[depth-i+1] = stack[depth-i-1]; + stack[depth-n-1] = stack[depth+1]; + stack[depth-n-2] = stack[depth]; + jstack->depth = depth + 2; +} + +void Thumb2_Swap(Thumb2_Info *jinfo) +{ + Thumb2_Stack *jstack = jinfo->jstack; + + Thumb2_Fill(jinfo, 2); + SWAP(jstack); +} + +void Thumb2_iOp(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lho, r_rho, r; + + Thumb2_Fill(jinfo, 2); + r_rho = POP(jstack); + r_lho = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + dop_reg(jinfo->codebuf, dOps[opc-opc_iadd], r, r_lho, r_rho, 0, 0); +} + +void Thumb2_iNeg(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_src, r; + + Thumb2_Fill(jinfo, 1); + r_src = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + rsb_imm(jinfo->codebuf, r, r_src, 0); +} + +void Thumb2_lNeg(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lo, r_hi, r_res_lo, r_res_hi; + unsigned r_tmp; + + Thumb2_Fill(jinfo, 2); + r_lo = POP(jstack); + r_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_res_hi = PUSH(jstack, JSTACK_REG(jstack)); + Thumb2_Spill(jinfo, 1, (1<<r_hi)); + r_res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~(1<<r_hi))); + JASSERT(r_res_lo != r_res_hi, "oops"); + JASSERT(r_res_lo != r_hi, "r_res_lo != r_hi"); + rsb_imm(jinfo->codebuf, r_res_lo, r_lo, 0); + r_tmp = Thumb2_Tmp(jinfo, (1<<r_hi)|(1<<r_res_lo)); + mov_imm(jinfo->codebuf, r_tmp, 0); + dop_reg(jinfo->codebuf, DP_SBC, r_res_hi, r_tmp, r_hi, SHIFT_LSL, 0); +} + +void Thumb2_fNeg(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r, r_result; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_result = PUSH(jstack, JSTACK_REG(jstack)); + eor_imm(jinfo->codebuf, r_result, r, 0x80000000); +} + +void Thumb2_dNeg(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned r_lo, r_hi, r_res_lo, r_res_hi; + + Thumb2_Fill(jinfo, 2); + r_lo = POP(jstack); + r_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_res_hi = PUSH(jstack, JSTACK_REG(jstack)); + Thumb2_Spill(jinfo, 1, (1<<r_hi)); + r_res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~(1<<r_hi))); + JASSERT(r_res_lo != r_res_hi, "oops"); + JASSERT(r_res_lo != r_hi, "r_res_lo != r_hi"); + mov_reg(jinfo->codebuf, r_res_lo, r_lo); + eor_imm(jinfo->codebuf, r_res_hi, r_hi, 0x80000000); +} + +void Thumb2_lOp(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned res_lo, res_hi; + unsigned lho_lo, lho_hi; + unsigned rho_lo, rho_hi; + + Thumb2_Fill(jinfo, 4); + rho_lo = POP(jstack); + rho_hi = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + res_hi = PUSH(jstack, JSTACK_REG(jstack)); + Thumb2_Spill(jinfo, 1, (1<<lho_hi)|(1<<rho_hi)); + res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_hi)|(1<<rho_hi)))); + JASSERT(res_lo != rho_hi && res_lo != lho_hi, "res_lo != rho_hi && res_lo != lho_hi"); + dop_reg(jinfo->codebuf, dOps[opc-opc_ladd], res_lo, lho_lo, rho_lo, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, dOps[opc-opc_ladd+1], res_hi, lho_hi, rho_hi, SHIFT_LSL, 0); +} + +void Thumb2_lmul(Thumb2_Info *jinfo) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned res_lo, res_hi; + unsigned lho_lo, lho_hi; + unsigned rho_lo, rho_hi; + unsigned r_tmp_lo, r_tmp_hi; + unsigned op_mask; + + Thumb2_Fill(jinfo, 4); + rho_lo = POP(jstack); + rho_hi = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + op_mask = (1<<rho_lo)|(1<<rho_hi)|(1<<lho_lo)|(1<<lho_hi); + Thumb2_Spill(jinfo, 2, 0); + res_hi = PUSH(jstack, JSTACK_PREFER(jstack, ~op_mask)); + res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~op_mask)); + r_tmp_lo = res_lo; + r_tmp_hi = res_hi; + if (op_mask & (1<<r_tmp_lo)) r_tmp_lo = Thumb2_Tmp(jinfo, op_mask); + if (op_mask & (1<<r_tmp_hi)) r_tmp_hi = Thumb2_Tmp(jinfo, op_mask|(1<<r_tmp_lo)); + umull(jinfo->codebuf, r_tmp_lo, r_tmp_hi, rho_lo, lho_lo); + mla(jinfo->codebuf, r_tmp_hi, rho_lo, lho_hi, r_tmp_hi); + mla(jinfo->codebuf, res_hi, rho_hi, lho_lo, r_tmp_hi); + mov_reg(jinfo->codebuf, res_lo, r_tmp_lo); +} + +void Thumb2_fOp(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned rho, lho, res; + + Thumb2_Fill(jinfo, 2); + rho = POP(jstack); + lho = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + res = PUSH(jstack, JSTACK_REG(jstack)); + vmov_reg_s_toVFP(jinfo->codebuf, VFP_S0, lho); + vmov_reg_s_toVFP(jinfo->codebuf, VFP_S1, rho); + vop_reg_s(jinfo->codebuf, dOps[opc-opc_iadd], VFP_S0, VFP_S0, VFP_S1); + vmov_reg_s_toARM(jinfo->codebuf, res, VFP_S0); +} + +void Thumb2_dOp(Thumb2_Info *jinfo, u32 opc) +{ + Thumb2_Stack *jstack = jinfo->jstack; + unsigned rho_lo, rho_hi, lho_lo, lho_hi, res_lo, res_hi; + + Thumb2_Fill(jinfo, 4); + rho_lo = POP(jstack); + rho_hi = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 2, 0); + res_hi = PUSH(jstack, JSTACK_REG(jstack)); + res_lo = PUSH(jstack, JSTACK_REG(jstack)); + vmov_reg_d_toVFP(jinfo->codebuf, VFP_D0, lho_lo, lho_hi); + vmov_reg_d_toVFP(jinfo->codebuf, VFP_D1, rho_lo, rho_hi); + vop_reg_d(jinfo->codebuf, dOps[opc-opc_iadd], VFP_D0, VFP_D0, VFP_D1); + vmov_reg_d_toARM(jinfo->codebuf, res_lo, res_hi, VFP_D0); +} + +void Thumb2_Handler(Thumb2_Info *jinfo, unsigned handler, unsigned opcode, unsigned bci) +{ + mov_imm(jinfo->codebuf, ARM_R0, opcode); + mov_imm(jinfo->codebuf, ARM_R1, bci); + mov_imm(jinfo->codebuf, ARM_IP, 0); + str_imm(jinfo->codebuf, ARM_IP, ARM_IP, 0, 1, 0); +// hbl(jinfo->codebuf, handler); +} + +void Thumb2_Debug(Thumb2_Info *jinfo, unsigned handler) +{ +#if 0 + Thumb2_Flush(jinfo); + bl(jinfo->codebuf, handlers[handler]); +#endif +} + +void Thumb2_codegen(Thumb2_Info *jinfo, unsigned start); + +int Thumb2_Branch(Thumb2_Info *jinfo, unsigned bci, unsigned cond) +{ + int offset = GET_JAVA_S2(jinfo->code_base + bci + 1); + unsigned dest_taken = bci + offset; + unsigned dest_not_taken = bci + 3; + unsigned loc; + + if (jinfo->bc_stackinfo[dest_taken] & BC_COMPILED) { + branch(jinfo->codebuf, cond, jinfo->bc_stackinfo[dest_taken] & ~BC_FLAGS_MASK); + return dest_not_taken; + } + loc = forward_32(jinfo->codebuf); + Thumb2_codegen(jinfo, dest_not_taken); + JASSERT(jinfo->bc_stackinfo[dest_taken] & BC_COMPILED, "dest in branch not compiled!!!"); + branch_patch(jinfo->codebuf, cond, loc, jinfo->bc_stackinfo[dest_taken] & ~BC_FLAGS_MASK); + return -1; +} + +int Thumb2_Goto(Thumb2_Info *jinfo, unsigned bci, int offset, int len) +{ + unsigned dest_taken = bci + offset; + unsigned dest_not_taken = bci + len; + unsigned loc; + + if (jinfo->bc_stackinfo[dest_taken] & BC_COMPILED) { + branch_uncond(jinfo->codebuf, jinfo->bc_stackinfo[dest_taken] & ~BC_FLAGS_MASK); + return dest_not_taken; + } + loc = forward_32(jinfo->codebuf); + Thumb2_codegen(jinfo, dest_not_taken); + JASSERT(jinfo->bc_stackinfo[dest_taken] & BC_COMPILED, "dest in goto not compiled!!!"); + branch_uncond_patch(jinfo->codebuf, loc, jinfo->bc_stackinfo[dest_taken] & ~BC_FLAGS_MASK); + return -1; +} + +void Thumb2_Return(Thumb2_Info *jinfo, unsigned opcode) +{ + Reg r_lo, r; + Thumb2_Stack *jstack = jinfo->jstack; + + if (0 /*jinfo->compiled_return*/) { + unsigned bci = jinfo->compiled_return; + + JASSERT(jinfo->bc_stackinfo[bci] & BC_COMPILED, "return not compiled"); + JASSERT(jinfo->code_base[bci] == opcode, "type of return changed"); + branch_uncond(jinfo->codebuf, jinfo->bc_stackinfo[bci] & ~BC_FLAGS_MASK); + return; + } + + if (jinfo->method->is_synchronized()) { + unsigned loc_success1, loc_success2, loc_failed, loc_retry, loc_exception; + unsigned loc_illegal_monitor_state; + Thumb2_Flush(jinfo); +// Thumb2_save_locals(jinfo); + // Free the monitor + // + // sub r1, Ristate, #8 + // ldr r2, [r1, #4] + // cbz r2, throw_illegal_monitor_state + // ldr r0, [r1, #0] + // mov r3, #0 + // str r3, [r1, #4] + // cbz r0, success + // retry: + // ldrex r3, [r2, #0] + // cmp r1, r3 + // bne failed + // strex r3, r0, [r2, #0] + // cbz r3, success + // b retry + // failed: + // str r2, [r1, #4] + // ... + // success: + // + // JAZ_V1 == tmp2 + // JAZ_V2 == tmp1 + sub_imm(jinfo->codebuf, ARM_R1, Ristate, frame::interpreter_frame_monitor_size()*wordSize); + ldr_imm(jinfo->codebuf, ARM_R2, ARM_R1, 4, 1, 0); + loc_illegal_monitor_state = forward_16(jinfo->codebuf); + ldr_imm(jinfo->codebuf, ARM_R0, ARM_R1, 0, 1, 0); + mov_imm(jinfo->codebuf, ARM_R3, 0); + str_imm(jinfo->codebuf, ARM_R3, ARM_R1, 4, 1, 0); + loc_success1 = forward_16(jinfo->codebuf); + loc_retry = out_loc(jinfo->codebuf); + ldrex_imm(jinfo->codebuf, ARM_R3, ARM_R2, 0); + cmp_reg(jinfo->codebuf, ARM_R1, ARM_R3); + loc_failed = forward_16(jinfo->codebuf); + strex_imm(jinfo->codebuf, ARM_R3, ARM_R0, ARM_R2, 0); + loc_success2 = forward_16(jinfo->codebuf); + branch_uncond(jinfo->codebuf, loc_retry); + bcc_patch(jinfo->codebuf, COND_NE, loc_failed); + cbz_patch(jinfo->codebuf, ARM_R2, loc_illegal_monitor_state); + str_imm(jinfo->codebuf, ARM_R2, ARM_R1, 4, 1, 0); + mov_imm(jinfo->codebuf, ARM_R0, 0+CONSTMETHOD_CODEOFFSET); + bl(jinfo->codebuf, handlers[H_SYNCHRONIZED_EXIT]); + loc_exception = forward_16(jinfo->codebuf); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + cbz_patch(jinfo->codebuf, ARM_R0, loc_exception); + cbz_patch(jinfo->codebuf, ARM_R0, loc_success1); + cbz_patch(jinfo->codebuf, ARM_R3, loc_success2); + } + + if (opcode != opc_return) { + if (opcode == opc_lreturn || opcode == opc_dreturn) { + Thumb2_Fill(jinfo, 2); + r_lo = POP(jstack); + r = POP(jstack); + } else { + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + } + } + + mov_imm(jinfo->codebuf, ARM_LR, 0); + str_imm(jinfo->codebuf, ARM_LR, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, Rstack, Rthread, THREAD_TOP_ZERO_FRAME, 1, 0); + ldr_imm(jinfo->codebuf, ARM_LR, Rstack, 0, 1, 0); + + if (opcode == opc_return) { + add_imm(jinfo->codebuf, Rstack, Rstack, jinfo->method->max_locals() * sizeof(int) + 4); + } else { + if (opcode == opc_lreturn || opcode == opc_dreturn) { + str_imm(jinfo->codebuf, r, Rstack, jinfo->method->max_locals() * sizeof(int), 1, 0); + str_imm(jinfo->codebuf, r_lo, Rstack, jinfo->method->max_locals() * sizeof(int)-4, 1, 1); + } else + str_imm(jinfo->codebuf, r, Rstack, jinfo->method->max_locals() * sizeof(int), 1, 1); + } + +// sub_imm(jinfo->codebuf, Ristate, ARM_LR, ISTATE_NEXT_FRAME); + str_imm(jinfo->codebuf, ARM_LR, Rthread, THREAD_TOP_ZERO_FRAME, 1, 0); + str_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + Thumb2_Debug(jinfo, H_DEBUG_METHODEXIT); +// enter_leave(jinfo->codebuf, 0); + ldm(jinfo->codebuf, C_REGSET + (1<<ARM_PC), ARM_SP, POP_FD, 1); +} + +#if 0 +void Thumb2_save_all_locals(Thumb2_Info *jinfo, unsigned stackdepth) +{ + int nlocals = jinfo->method->max_locals(); + int i; + + JASSERT(jinfo->jstack->depth == 0, "stack not empty"); + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + store_local(jinfo, r, i, stackdepth); + } + } +} +#endif + +void Thumb2_save_locals(Thumb2_Info *jinfo, unsigned stackdepth) +{ + int nlocals = jinfo->method->max_locals(); + unsigned *locals_info = jinfo->locals_info; + int i; + + JASSERT(jinfo->jstack->depth == 0, "stack not empty"); + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + if ((locals_info[i] & (1 << LOCAL_REF)) && (locals_info[i] & (1 << LOCAL_MODIFIED))) { + store_local(jinfo, r, i, stackdepth); + } + } + } +} + +void Thumb2_restore_locals(Thumb2_Info *jinfo, unsigned stackdepth) +{ + int nlocals = jinfo->method->max_locals(); + unsigned *locals_info = jinfo->locals_info; + int i; + + JASSERT(jinfo->jstack->depth == 0, "stack not empty"); + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + if (locals_info[i] & (1<<LOCAL_REF)) { + load_local(jinfo, r, i, stackdepth); + } + } + } +} + +void Thumb2_invoke_save(Thumb2_Info *jinfo, unsigned stackdepth) +{ + int nlocals = jinfo->method->max_locals(); + unsigned *locals_info = jinfo->locals_info; + int i; + + JASSERT(jinfo->jstack->depth == 0, "stack not empty"); + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + if (locals_info[i] & (1 << LOCAL_MODIFIED)) { + store_local(jinfo, r, i, stackdepth); + } + } + } +} + +void Thumb2_invoke_restore(Thumb2_Info *jinfo, unsigned stackdepth) +{ + int nlocals = jinfo->method->max_locals(); + unsigned *locals_info = jinfo->locals_info; + int i; + + JASSERT(jinfo->jstack->depth == 0, "stack not empty"); + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + load_local(jinfo, r, i, stackdepth); + } + } +} + +void Thumb2_Exit(Thumb2_Info *jinfo, unsigned handler, unsigned bci, unsigned stackdepth) +{ + Thumb2_Flush(jinfo); + Thumb2_invoke_save(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + bl(jinfo->codebuf, handlers[handler]); +} + +void Thumb2_Jsr(Thumb2_Info *jinfo, unsigned bci, unsigned stackdepth) +{ + Thumb2_Exit(jinfo, H_JSR, bci, stackdepth); +} + +int Thumb2_Accessor(Thumb2_Info *jinfo) +{ + jubyte *code_base = jinfo->code_base; + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+2); + unsigned loc; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + + JASSERT(code_base[0] == opc_aload_0 || code_base[0] == opc_iaccess_0, "not an aload_0 in accessor"); + JASSERT(code_base[4] == opc_ireturn || code_base[4] == opc_areturn, "not an ireturn in accessor"); + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opc_getfield)) return 0; + + TosState tos_type = cache->flag_state(); + int field_offset = cache->f2(); + + // Slow entry point + loc = forward_32(jinfo->codebuf); + out_32(jinfo->codebuf, 0); + out_32(jinfo->codebuf, 0); + out_32(jinfo->codebuf, 0); + + // OSR entry point + mov_reg(jinfo->codebuf, ARM_PC, ARM_R0); + + out_align(jinfo->codebuf, CODE_ALIGN); + + // fast entry point + bc_stackinfo[0] = (bc_stackinfo[0] & BC_FLAGS_MASK) | (jinfo->codebuf->idx * 2) | BC_COMPILED; + branch_uncond_patch(jinfo->codebuf, loc, jinfo->codebuf->idx * 2); + ldr_imm(jinfo->codebuf, ARM_R1, ARM_R2, THREAD_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R0, ARM_R1, 0, 1, 0); + if (tos_type == btos) + ldrb_imm(jinfo->codebuf, ARM_R0, ARM_R0, field_offset, 1, 0); + else if (tos_type == ctos) + ldrh_imm(jinfo->codebuf, ARM_R0, ARM_R0, field_offset, 1, 0); + else if (tos_type == stos) + ldrsh_imm(jinfo->codebuf, ARM_R0, ARM_R0, field_offset, 1, 0); + else + ldr_imm(jinfo->codebuf, ARM_R0, ARM_R0, field_offset, 1, 0); + str_imm(jinfo->codebuf, ARM_R0, ARM_R1, 0, 1, 0); + mov_reg(jinfo->codebuf, ARM_PC, ARM_LR); + + return 1; +} + +void Thumb2_Enter(Thumb2_Info *jinfo) +{ + int parms = jinfo->method->size_of_parameters(); + int extra_locals = jinfo->method->max_locals() - parms; + unsigned *locals_info = jinfo->locals_info; + int i; + + // Slow entry point - callee save + // R0 = method + // R2 = thread + stm(jinfo->codebuf, I_REGSET + (1<<ARM_LR), ARM_SP, PUSH_FD, 1); + bl(jinfo->codebuf, out_pos(jinfo->codebuf) + CODE_ALIGN - 4); + ldm(jinfo->codebuf, I_REGSET + (1<<ARM_PC), ARM_SP, POP_FD, 1); + + out_32(jinfo->codebuf, 0); + + // OSR entry point == Slow entry + 16 - caller save + // R0 = entry point within compiled method + // R1 = locals + // R2 = thread + { + int nlocals = jinfo->method->max_locals(); + + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + ldr_imm(jinfo->codebuf, r, ARM_R1, -i * 4, 1, 0); + } + } + mov_reg(jinfo->codebuf, Rthread, ARM_R2); + mov_reg(jinfo->codebuf, ARM_PC, ARM_R0); + } + + out_align(jinfo->codebuf, CODE_ALIGN); + + // Fast entry point == Slow entry + 64 - caller save + // R0 = method + // R2 = thread + stm(jinfo->codebuf, C_REGSET + (1<<ARM_LR), ARM_SP, PUSH_FD, 1); +// enter_leave(jinfo->codebuf, 1); + ldr_imm(jinfo->codebuf, Rstack, ARM_R2, THREAD_JAVA_SP, 1, 0); + Thumb2_Debug(jinfo, H_DEBUG_METHODENTRY); + mov_imm(jinfo->codebuf, ARM_R1, 0); + + if (extra_locals > 0) { + sub_imm(jinfo->codebuf, Rstack, Rstack, extra_locals * 4); + + for (i = 0; i < extra_locals; i++) { + unsigned linfo = locals_info[parms+i]; + if (linfo & (1<< LOCAL_REF)) + str_imm(jinfo->codebuf, ARM_R1, Rstack, (extra_locals-1 - i) * 4, 1, 0); + } + } + + ldr_imm(jinfo->codebuf, ARM_IP, ARM_R0, METHOD_CONSTANTS, 1, 0); + + sub_imm(jinfo->codebuf, Ristate, Rstack, FRAME_SIZE); + + add_imm(jinfo->codebuf, Rlocals, Rstack, (jinfo->method->max_locals()-1) * sizeof(int)); + str_imm(jinfo->codebuf, Rlocals, Ristate, ISTATE_LOCALS, 1, 0); + + if (jinfo->method->is_synchronized()) { + sub_imm(jinfo->codebuf, Rstack, Ristate, frame::interpreter_frame_monitor_size()*wordSize); + if (jinfo->method->is_static()) { + ldr_imm(jinfo->codebuf, ARM_R3, ARM_IP, CONSTANTPOOL_POOL_HOLDER, 1, 0); + ldr_imm(jinfo->codebuf, JAZ_V1, ARM_R3, KLASS_PART+KLASS_JAVA_MIRROR, 1, 0); + } else { + ldr_imm(jinfo->codebuf, JAZ_V1, Rlocals, 0, 1, 0); + } + str_imm(jinfo->codebuf, JAZ_V1, Rstack, 4, 1, 0); + } else + mov_reg(jinfo->codebuf, Rstack, Ristate); + + str_imm(jinfo->codebuf, ARM_R1, Ristate, ISTATE_MSG, 1, 0); + str_imm(jinfo->codebuf, ARM_R1, Ristate, ISTATE_OOP_TEMP, 1, 0); + + sub_imm(jinfo->codebuf, ARM_R3, Rstack, jinfo->method->max_stack() * sizeof(int)); + str_imm(jinfo->codebuf, ARM_R3, ARM_R2, THREAD_JAVA_SP, 1, 0); + + str_imm(jinfo->codebuf, Rstack, Ristate, ISTATE_STACK_BASE, 1, 0); + + sub_imm(jinfo->codebuf, ARM_R3, ARM_R3, 4); + str_imm(jinfo->codebuf, ARM_R3, Ristate, ISTATE_STACK_LIMIT, 1, 0); + + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R2, THREAD_TOP_ZERO_FRAME, 1, 0); + str_imm(jinfo->codebuf, ARM_R3, Ristate, ISTATE_NEXT_FRAME, 1, 0); + + mov_imm(jinfo->codebuf, ARM_R3, INTERPRETER_FRAME); + str_imm(jinfo->codebuf, ARM_R3, Ristate, ISTATE_FRAME_TYPE, 1, 0); + + str_imm(jinfo->codebuf, Ristate, Ristate, ISTATE_MONITOR_BASE, 1, 0); + + add_imm(jinfo->codebuf, ARM_R3, Ristate, ISTATE_NEXT_FRAME); + str_imm(jinfo->codebuf, ARM_R3, ARM_R2, THREAD_TOP_ZERO_FRAME, 1, 0); + str_imm(jinfo->codebuf, ARM_R3, ARM_R2, THREAD_LAST_JAVA_SP, 1, 0); + + ldr_imm(jinfo->codebuf, ARM_R3, ARM_IP, CONSTANTPOOL_CACHE, 1, 0); + str_imm(jinfo->codebuf, ARM_R3, Ristate, ISTATE_CONSTANTS, 1, 0); + + str_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_THREAD, 1, 0); + str_imm(jinfo->codebuf, ARM_R0, Ristate, ISTATE_METHOD, 1, 0); + + mov_reg(jinfo->codebuf, Rthread, ARM_R2); + + if (jinfo->method->is_synchronized()) { + unsigned loc_retry, loc_failed, loc_success, loc_exception; + + // JAZ_V1 == monitor object + // + // Try to acquire the monitor. Seems very sub-optimal + // ldr r3, [JAZ_V1, #0] + // sub r1, Ristate, #8 + // orr r3, r3, #1 + // str r3, [r1, #0] + // retry: + // ldrex r0, [JAZ_V1, #0] + // cmp r3, r0 + // bne failed + // strex r0, r1, [JAZ_V1, #0] + // cbz r0, success + // b retry + // failed: + // <failed - someone else has the monitor - must yield> + // success: + // <success - acquired the monitor> + // + ldr_imm(jinfo->codebuf, ARM_R3, JAZ_V1, 0, 1, 0); + sub_imm(jinfo->codebuf, ARM_R1, Ristate, frame::interpreter_frame_monitor_size()*wordSize); + orr_imm(jinfo->codebuf, ARM_R3, ARM_R3, 1); + str_imm(jinfo->codebuf, ARM_R3, ARM_R1, 0, 1, 0); + loc_retry = out_loc(jinfo->codebuf); +// retry: + ldrex_imm(jinfo->codebuf, ARM_R0, JAZ_V1, 0); + cmp_reg(jinfo->codebuf, ARM_R3, ARM_R0); + loc_failed = forward_16(jinfo->codebuf); + strex_imm(jinfo->codebuf, ARM_R0, ARM_R1, JAZ_V1, 0); + loc_success = forward_16(jinfo->codebuf); + branch_uncond(jinfo->codebuf, loc_retry); + bcc_patch(jinfo->codebuf, COND_NE, loc_failed); +// failed: + mov_imm(jinfo->codebuf, ARM_R0, 0+CONSTMETHOD_CODEOFFSET); + bl(jinfo->codebuf, handlers[H_SYNCHRONIZED_ENTER]); + loc_exception = forward_16(jinfo->codebuf); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + cbz_patch(jinfo->codebuf, ARM_R0, loc_exception); + cbz_patch(jinfo->codebuf, ARM_R0, loc_success); +// mov_imm(jinfo->codebuf, ARM_R0, 0+CONSTMETHOD_CODEOFFSET); +// bl(jinfo->codebuf, handlers[H_MONITOR]); +// success: + + } + + { + int nlocals = jinfo->method->max_locals(); + + for (i = 0; i < nlocals; i++) { + Reg r = jinfo->jregs->r_local[i]; + if (r) { + unsigned stackdepth = 0; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + if (i < parms || (locals_info[i] & (1<<LOCAL_REF))) { + load_local(jinfo, r, i, stackdepth); + } + } + } + } +} + +unsigned opcode2handler[] = { + H_IDIV, + H_LDIV, + 0, 0, // fdiv, ddiv + H_IREM, + H_LREM, + H_FREM, + H_DREM, + 0, 0, 0, 0, // ineg, lneg, fneg, dneg + 0, 0, 0, 0, 0, 0, // shifts + 0, 0, 0, 0, 0, 0, // and, or, xor + 0, // iinc + 0, // i2l + H_I2F, + H_I2D, + 0, // l2i + H_L2F, + H_L2D, + H_F2I, + H_F2L, + H_F2D, + H_D2I, + H_D2L, + H_D2F, +}; + +#define OPCODE2HANDLER(opc) (handlers[opcode2handler[(opc)-opc_idiv]]) + +void Thumb2_codegen(Thumb2_Info *jinfo, unsigned start) +{ + unsigned code_size = jinfo->code_size; + jubyte *code_base = jinfo->code_base; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + CodeBuf *codebuf = jinfo->codebuf; + Thumb2_Stack *jstack = jinfo->jstack; + unsigned bci; + unsigned opcode; + unsigned stackinfo; + int len; + unsigned stackdepth; + + for (bci = start; bci < code_size; ) { +#ifdef T2EE_PRINT_DISASS + unsigned start_idx = jinfo->codebuf->idx; + if (start_bci[start_idx] == -1) start_bci[start_idx] = bci; +#endif + opcode = code_base[bci]; + stackinfo = bc_stackinfo[bci]; + + if (stackinfo & BC_BRANCH_TARGET) Thumb2_Flush(jinfo); + JASSERT(!(stackinfo & BC_COMPILED), "code already compiled for this bytecode?"); + stackdepth = stackinfo & ~BC_FLAGS_MASK; + bc_stackinfo[bci] = (stackinfo & BC_FLAGS_MASK) | (codebuf->idx * 2) | BC_COMPILED; + + if (opcode > OPC_LAST_JAVA_OP) { + if (Bytecodes::is_defined((Bytecodes::Code)opcode)) + opcode = (unsigned)Bytecodes::java_code((Bytecodes::Code)opcode); + } + + len = Bytecodes::length_for((Bytecodes::Code)opcode); + if (len <= 0) len = Bytecodes::special_length_at((address)(code_base+bci), (address)(code_base+code_size)); + + if (IS_DEAD(stackinfo) || IS_ZOMBIE(stackinfo)) { + unsigned zlen = 0; +#ifdef T2EE_PRINT_DISASS + unsigned start_bci = bci; +#endif + + Thumb2_Exit(jinfo, H_ZOMBIE, bci, stackdepth); + do { + zlen += len; + bci += len; + if (bci >= code_size) break; + opcode = code_base[bci]; + stackinfo = bc_stackinfo[bci]; + + if (stackinfo & BC_BRANCH_TARGET) break; + if (!(IS_DEAD(stackinfo) || IS_ZOMBIE(stackinfo))) break; + + if (opcode > OPC_LAST_JAVA_OP) { + if (Bytecodes::is_defined((Bytecodes::Code)opcode)) + opcode = (unsigned)Bytecodes::java_code((Bytecodes::Code)opcode); + } + + len = Bytecodes::length_for((Bytecodes::Code)opcode); + if (len <= 0) len = Bytecodes::special_length_at((address)(code_base+bci), (address)(code_base+code_size)); + + } while (1); +#ifdef T2EE_PRINT_DISASS + end_bci[start_idx] = start_bci + zlen; +#endif + jinfo->zombie_bytes += zlen; + continue; + } + +#if 0 + if (bci >= 2620) { + unsigned zlen = 0; +#ifdef T2EE_PRINT_DISASS + unsigned start_bci = bci; +#endif + + Thumb2_Exit(jinfo, H_ZOMBIE, bci, stackdepth); + do { + zlen += len; + bci += len; + if (bci >= code_size) break; + opcode = code_base[bci]; + stackinfo = bc_stackinfo[bci]; + + if (stackinfo & BC_BRANCH_TARGET) break; + + if (opcode > OPC_LAST_JAVA_OP) { + if (Bytecodes::is_defined((Bytecodes::Code)opcode)) + opcode = (unsigned)Bytecodes::java_code((Bytecodes::Code)opcode); + } + + len = Bytecodes::length_for((Bytecodes::Code)opcode); + if (len <= 0) len = Bytecodes::special_length_at((address)(code_base+bci), (address)(code_base+code_size)); + + } while (1); +#ifdef T2EE_PRINT_DISASS + end_bci[start_idx] = start_bci + zlen; +#endif + jinfo->zombie_bytes += zlen; + continue; + } +#endif + +#ifdef T2EE_PRINT_DISASS + end_bci[start_idx] = bci + len; +#endif + + switch (opcode) { + case opc_nop: + break; + case opc_aconst_null: + len += Thumb2_Imm(jinfo, 0, bci+1); + break; + case opc_iconst_m1: + case opc_iconst_0: + case opc_iconst_1: + case opc_iconst_2: + case opc_iconst_3: + case opc_iconst_4: + case opc_iconst_5: + len += Thumb2_Imm(jinfo, opcode - (unsigned)opc_iconst_0, bci+1); + break; + case opc_lconst_0: + case opc_lconst_1: + Thumb2_ImmX2(jinfo, opcode - (unsigned)opc_lconst_0, 0); + break; + case opc_fconst_0: + case opc_fconst_1: + case opc_fconst_2: { + unsigned v = 0; + if (opcode == (unsigned)opc_fconst_1) v = 0x3f800000; + if (opcode == (unsigned)opc_fconst_2) v = 0x40000000; + len += Thumb2_Imm(jinfo, v, bci+1); + break; + } + case opc_dconst_0: + case opc_dconst_1: { + unsigned v_hi = 0; + if (opcode == (unsigned)opc_dconst_1) v_hi = 0x3ff00000; + Thumb2_ImmX2(jinfo, 0, v_hi); + break; + } + case opc_bipush: + len += Thumb2_Imm(jinfo, GET_JAVA_S1(code_base+bci+1), bci+2); + break; + case opc_sipush: + len += Thumb2_Imm(jinfo, GET_JAVA_S2(code_base+bci+1), bci+3); + break; + case opc_ldc: + case opc_ldc_w: + case opc_ldc2_w: { + unsigned index = (opcode == (unsigned)opc_ldc) ? + code_base[bci+1] : GET_JAVA_U2(code_base+bci+1); + constantPoolOop constants = jinfo->method->constants(); + unsigned v; + + switch (v = constants->tag_at(index).value()) { + case JVM_CONSTANT_Integer: + case JVM_CONSTANT_Float: + v = (unsigned)constants->int_at(index); + len += Thumb2_Imm(jinfo, v, bci+len); + break; +#if 0 + case JVM_CONSTANT_String: + v = (unsigned)constants->resolved_string_at(index); + len += Thumb2_Imm(jinfo, v, bci+len); + break; + case JVM_CONSTANT_Class: + v = (unsigned)constants->resolved_klass_at(index)->klass_part()->java_mirror(); + len += Thumb2_Imm(jinfo, v, bci+len); + break; +#endif + case JVM_CONSTANT_Long: + case JVM_CONSTANT_Double: { + unsigned long long v; + v = constants->long_at(index); + Thumb2_ImmX2(jinfo, v & 0xffffffff, v >> 32); + break; + } + case JVM_CONSTANT_Class: + case JVM_CONSTANT_String: { + Reg r; + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + ldr_imm(jinfo->codebuf, r, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(jinfo->codebuf, r, r, METHOD_CONSTANTS, 1, 0); + ldr_imm(jinfo->codebuf, r, r, CONSTANTPOOL_BASE + (index << 2), 1, 0); + if (v == JVM_CONSTANT_Class) + ldr_imm(jinfo->codebuf, r, r, KLASS_PART+KLASS_JAVA_MIRROR, 1, 0); + break; + } + default: + unsigned loc; + + JASSERT(opcode != opc_ldc2_w, "ldc2_w unresolved?"); + Thumb2_Flush(jinfo); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R1, opcode != opc_ldc); + bl(jinfo->codebuf, handlers[H_LDC]); + Thumb2_restore_locals(jinfo, stackdepth); + ldr_imm(jinfo->codebuf, ARM_R0, Rthread, THREAD_VM_RESULT, 1, 0); + mov_imm(jinfo->codebuf, ARM_R2, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_VM_RESULT, 1, 0); + loc = forward_16(jinfo->codebuf); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + cbnz_patch(jinfo->codebuf, ARM_R0, loc); + PUSH(jstack, ARM_R0); + break; + } + break; + } + + case opc_iload: + case opc_fload: + case opc_aload: + Thumb2_Load(jinfo, code_base[bci+1], stackdepth); + break; + case opc_lload: + case opc_dload: + Thumb2_LoadX2(jinfo, code_base[bci+1], stackdepth); + break; + case opc_iload_0: + case opc_iload_1: + case opc_iload_2: + case opc_iload_3: + case opc_fload_0: + case opc_fload_1: + case opc_fload_2: + case opc_fload_3: + case opc_aload_0: + case opc_aload_1: + case opc_aload_2: + case opc_aload_3: + Thumb2_Load(jinfo, (opcode - opc_iload_0) & 3, stackdepth); + break; + case opc_lload_0: + case opc_lload_1: + case opc_lload_2: + case opc_lload_3: + case opc_dload_0: + case opc_dload_1: + case opc_dload_2: + case opc_dload_3: + Thumb2_LoadX2(jinfo, (opcode - opc_iload_0) & 3, stackdepth); + break; + case opc_iaload: + case opc_faload: + case opc_aaload: + case opc_baload: + case opc_caload: + case opc_saload: + Thumb2_Xaload(jinfo, opcode); + break; + case opc_laload: + case opc_daload: + Thumb2_X2aload(jinfo); + break; + case opc_istore: + case opc_fstore: + case opc_astore: + Thumb2_Store(jinfo, code_base[bci+1], stackdepth); + break; + case opc_lstore: + case opc_dstore: + Thumb2_StoreX2(jinfo, code_base[bci+1], stackdepth); + break; + case opc_istore_0: + case opc_istore_1: + case opc_istore_2: + case opc_istore_3: + case opc_fstore_0: + case opc_fstore_1: + case opc_fstore_2: + case opc_fstore_3: + case opc_astore_0: + case opc_astore_1: + case opc_astore_2: + case opc_astore_3: + Thumb2_Store(jinfo, (opcode - opc_istore_0) & 3, stackdepth); + break; + case opc_lstore_0: + case opc_lstore_1: + case opc_lstore_2: + case opc_lstore_3: + case opc_dstore_0: + case opc_dstore_1: + case opc_dstore_2: + case opc_dstore_3: + Thumb2_StoreX2(jinfo, (opcode - opc_istore_0) & 3, stackdepth); + break; + case opc_iastore: + case opc_fastore: + case opc_bastore: + case opc_castore: + case opc_sastore: + Thumb2_Xastore(jinfo, opcode); + break; + case opc_lastore: + case opc_dastore: + Thumb2_X2astore(jinfo); + break; + + case opc_pop: + case opc_pop2: + Thumb2_Pop(jinfo, opcode - opc_pop + 1); + break; + + case opc_dup: + case opc_dup_x1: + case opc_dup_x2: + Thumb2_Dup(jinfo, opcode - opc_dup); + break; + + case opc_dup2: + case opc_dup2_x1: + case opc_dup2_x2: + Thumb2_Dup2(jinfo, opcode - opc_dup2); + break; + + case opc_swap: + Thumb2_Swap(jinfo); + break; + + case opc_iadd: + case opc_isub: + case opc_imul: + case opc_ishl: + case opc_ishr: + case opc_iushr: + case opc_iand: + case opc_ior: + case opc_ixor: + Thumb2_iOp(jinfo, opcode); + break; + + case opc_ladd: + case opc_lsub: + case opc_land: + case opc_lor: + case opc_lxor: + Thumb2_lOp(jinfo, opcode); + break; + + case opc_lshl: { + Reg lho_lo, lho_hi, res_lo, res_hi, shift; + unsigned loc1, loc2; + + Thumb2_Fill(jinfo, 3); + shift = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 2, (1<<lho_lo)|(1<<lho_hi)); + res_hi = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_lo)|(1<<lho_hi)))); + res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_lo)|(1<<lho_hi)))); + JASSERT(res_lo != lho_lo && res_lo != lho_hi, "Spill failed"); + JASSERT(res_hi != lho_lo && res_hi != lho_hi, "Spill failed"); + and_imm(jinfo->codebuf, ARM_IP, shift, 31); + tst_imm(jinfo->codebuf, shift, 32); + loc1 = forward_16(jinfo->codebuf); + mov_imm(jinfo->codebuf, res_lo, 0); + dop_reg(jinfo->codebuf, DP_LSL, res_hi, lho_lo, ARM_IP, SHIFT_LSL, 0); + loc2 = forward_16(jinfo->codebuf); + bcc_patch(jinfo->codebuf, COND_EQ, loc1); + dop_reg(jinfo->codebuf, DP_LSL, res_lo, lho_lo, ARM_IP, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_LSL, res_hi, lho_hi, ARM_IP, SHIFT_LSL, 0); + rsb_imm(jinfo->codebuf, ARM_IP, ARM_IP, 32); + dop_reg(jinfo->codebuf, DP_LSR, ARM_IP, lho_lo, ARM_IP, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_ORR, res_hi, res_hi, ARM_IP, SHIFT_LSL, 0); + branch_narrow_patch(jinfo->codebuf, loc2); + break; + } + + case opc_lushr: { + Reg lho_lo, lho_hi, res_lo, res_hi, shift; + unsigned loc1, loc2; + + Thumb2_Fill(jinfo, 3); + shift = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 2, (1<<lho_lo)|(1<<lho_hi)); + res_hi = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_lo)|(1<<lho_hi)))); + res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_lo)|(1<<lho_hi)))); + JASSERT(res_lo != lho_lo && res_lo != lho_hi, "Spill failed"); + JASSERT(res_hi != lho_lo && res_hi != lho_hi, "Spill failed"); + and_imm(jinfo->codebuf, ARM_IP, shift, 31); + tst_imm(jinfo->codebuf, shift, 32); + loc1 = forward_16(jinfo->codebuf); + mov_imm(jinfo->codebuf, res_hi, 0); + dop_reg(jinfo->codebuf, DP_LSR, res_lo, lho_hi, ARM_IP, SHIFT_LSL, 0); + loc2 = forward_16(jinfo->codebuf); + bcc_patch(jinfo->codebuf, COND_EQ, loc1); + dop_reg(jinfo->codebuf, DP_LSR, res_hi, lho_hi, ARM_IP, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_LSR, res_lo, lho_lo, ARM_IP, SHIFT_LSL, 0); + rsb_imm(jinfo->codebuf, ARM_IP, ARM_IP, 32); + dop_reg(jinfo->codebuf, DP_LSL, ARM_IP, lho_hi, ARM_IP, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_ORR, res_lo, res_lo, ARM_IP, SHIFT_LSL, 0); + branch_narrow_patch(jinfo->codebuf, loc2); + break; + } + + case opc_lshr: { + Reg lho_lo, lho_hi, res_lo, res_hi, shift; + unsigned loc1, loc2; + + Thumb2_Fill(jinfo, 3); + shift = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 2, (1<<lho_lo)|(1<<lho_hi)); + res_hi = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_lo)|(1<<lho_hi)))); + res_lo = PUSH(jstack, JSTACK_PREFER(jstack, ~((1<<lho_lo)|(1<<lho_hi)))); + JASSERT(res_lo != lho_lo && res_lo != lho_hi, "Spill failed"); + JASSERT(res_hi != lho_lo && res_hi != lho_hi, "Spill failed"); + and_imm(jinfo->codebuf, ARM_IP, shift, 31); + tst_imm(jinfo->codebuf, shift, 32); + loc1 = forward_16(jinfo->codebuf); + asr_imm(jinfo->codebuf, res_hi, lho_hi, 31); + dop_reg(jinfo->codebuf, DP_ASR, res_lo, lho_hi, ARM_IP, SHIFT_LSL, 0); + loc2 = forward_16(jinfo->codebuf); + bcc_patch(jinfo->codebuf, COND_EQ, loc1); + dop_reg(jinfo->codebuf, DP_ASR, res_hi, lho_hi, ARM_IP, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_LSR, res_lo, lho_lo, ARM_IP, SHIFT_LSL, 0); + rsb_imm(jinfo->codebuf, ARM_IP, ARM_IP, 32); + dop_reg(jinfo->codebuf, DP_LSL, ARM_IP, lho_hi, ARM_IP, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_ORR, res_lo, res_lo, ARM_IP, SHIFT_LSL, 0); + branch_narrow_patch(jinfo->codebuf, loc2); + break; + } + + case opc_lmul: + Thumb2_lmul(jinfo); + break; + + case opc_fadd: + case opc_fsub: + case opc_fmul: + case opc_fdiv: + Thumb2_fOp(jinfo, opcode); + break; + + case opc_dadd: + case opc_dsub: + case opc_dmul: + case opc_ddiv: + Thumb2_dOp(jinfo, opcode); + break; + + case opc_fcmpl: + case opc_fcmpg: { + Thumb2_Stack *jstack = jinfo->jstack; + unsigned rho, lho, res; + unsigned loc1, loc2, loc_ne; + + Thumb2_Fill(jinfo, 2); + rho = POP(jstack); + lho = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + res = PUSH(jstack, JSTACK_REG(jstack)); + vmov_reg_s_toVFP(jinfo->codebuf, VFP_S0, lho); + vmov_reg_s_toVFP(jinfo->codebuf, VFP_S1, rho); + vcmp_reg_s(jinfo->codebuf, VFP_S0, VFP_S1, 1); + mov_imm(jinfo->codebuf, res, opcode == opc_fcmpl ? 1 : -1); + vmrs(jinfo->codebuf, ARM_PC); + loc1 = forward_16(jinfo->codebuf); + dop_imm_preserve(jinfo->codebuf, DP_RSB, res, res, 0); + loc2 = forward_16(jinfo->codebuf); + vcmp_reg_s(jinfo->codebuf, VFP_S0, VFP_S1, 0); + loc_ne = forward_16(jinfo->codebuf); + mov_imm(jinfo->codebuf, res, 0); + bcc_patch(jinfo->codebuf, opcode == opc_fcmpl ? COND_GT : COND_MI, loc1); + bcc_patch(jinfo->codebuf, opcode == opc_fcmpl ? COND_MI : COND_GT, loc2); + bcc_patch(jinfo->codebuf, COND_NE, loc_ne); + break; + } + + case opc_dcmpl: + case opc_dcmpg: { + Thumb2_Stack *jstack = jinfo->jstack; + unsigned rho_lo, rho_hi, lho_lo, lho_hi, res; + unsigned loc1, loc2, loc_ne; + + Thumb2_Fill(jinfo, 4); + rho_lo = POP(jstack); + rho_hi = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + res = PUSH(jstack, JSTACK_REG(jstack)); + vmov_reg_d_toVFP(jinfo->codebuf, VFP_S0, lho_lo, lho_hi); + vmov_reg_d_toVFP(jinfo->codebuf, VFP_S1, rho_lo, rho_hi); + vcmp_reg_d(jinfo->codebuf, VFP_S0, VFP_S1, 1); + mov_imm(jinfo->codebuf, res, opcode == opc_dcmpl ? 1 : -1); + vmrs(jinfo->codebuf, ARM_PC); + loc1 = forward_16(jinfo->codebuf); + dop_imm_preserve(jinfo->codebuf, DP_RSB, res, res, 0); + loc2 = forward_16(jinfo->codebuf); + vcmp_reg_d(jinfo->codebuf, VFP_S0, VFP_S1, 0); + loc_ne = forward_16(jinfo->codebuf); + mov_imm(jinfo->codebuf, res, 0); + bcc_patch(jinfo->codebuf, opcode == opc_dcmpl ? COND_GT : COND_MI, loc1); + bcc_patch(jinfo->codebuf, opcode == opc_dcmpl ? COND_MI : COND_GT, loc2); + bcc_patch(jinfo->codebuf, COND_NE, loc_ne); + break; + } + + case opc_drem: + case opc_lrem: + case opc_ldiv: { + Reg src[4], dst[4]; + + Thumb2_Fill(jinfo, 4); + src[2] = POP(jstack); + src[3] = POP(jstack); + src[0] = POP(jstack); + src[1] = POP(jstack); + Thumb2_Flush(jinfo); + dst[0] = ARM_R0; + dst[1] = ARM_R1; + dst[2] = ARM_R2; + dst[3] = ARM_R3; + mov_multiple(jinfo->codebuf, dst, src, 4); + bl(jinfo->codebuf, OPCODE2HANDLER(opcode)); + if (opcode != opc_lrem) { + PUSH(jstack, ARM_R1); + PUSH(jstack, ARM_R0); + } else { + PUSH(jstack, ARM_R3); + PUSH(jstack, ARM_R2); + } + break; + } + + case opc_frem: + case opc_idiv: + case opc_irem: { + Reg r_rho, r_lho; + + Thumb2_Fill(jinfo, 2); + r_rho = POP(jstack); + r_lho = POP(jstack); + Thumb2_Flush(jinfo); + if (r_rho == ARM_R0) { + if (r_lho == ARM_R1) { + mov_reg(jinfo->codebuf, ARM_IP, r_rho); + mov_reg(jinfo->codebuf, ARM_R0, r_lho); + mov_reg(jinfo->codebuf, ARM_R1, ARM_IP); + } else { + mov_reg(jinfo->codebuf, ARM_R1, r_rho); + mov_reg(jinfo->codebuf, ARM_R0, r_lho); + } + } else { + mov_reg(jinfo->codebuf, ARM_R0, r_lho); + mov_reg(jinfo->codebuf, ARM_R1, r_rho); + } +#if 1 + if (opcode == opc_frem) + bl(jinfo->codebuf, OPCODE2HANDLER(opcode)); + else + blx(jinfo->codebuf, OPCODE2HANDLER(opcode)); +#else + bl(jinfo->codebuf, OPCODE2HANDLER(opcode)); +#endif + PUSH(jstack, ARM_R0); + break; + } + + case opc_f2i: + case opc_i2f: { + Reg r; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R0, r); + bl(jinfo->codebuf, OPCODE2HANDLER(opcode)); + PUSH(jstack, ARM_R0); + break; + } + + case opc_f2d: + case opc_f2l: + case opc_i2d: { + Reg r; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R0, r); + bl(jinfo->codebuf, OPCODE2HANDLER(opcode)); + PUSH(jstack, ARM_R1); + PUSH(jstack, ARM_R0); + break; + } + + case opc_d2f: + case opc_d2i: + case opc_l2d: + case opc_d2l: + case opc_l2f: { + Reg lo, hi; + + Thumb2_Fill(jinfo, 2); + lo = POP(jstack); + hi = POP(jstack); + Thumb2_Flush(jinfo); + if (hi == ARM_R0) { + if (lo == ARM_R1) { + mov_reg(jinfo->codebuf, ARM_IP, hi); + mov_reg(jinfo->codebuf, ARM_R0, lo); + mov_reg(jinfo->codebuf, ARM_R1, ARM_IP); + } else { + mov_reg(jinfo->codebuf, ARM_R1, hi); + mov_reg(jinfo->codebuf, ARM_R0, lo); + } + } else { + mov_reg(jinfo->codebuf, ARM_R0, lo); + mov_reg(jinfo->codebuf, ARM_R1, hi); + } + bl(jinfo->codebuf, OPCODE2HANDLER(opcode)); + if (opcode == opc_l2d || opcode == opc_d2l) PUSH(jstack, ARM_R1); + PUSH(jstack, ARM_R0); + break; + } + + case opc_ineg: + Thumb2_iNeg(jinfo, opcode); + break; + + case opc_lneg: + Thumb2_lNeg(jinfo, opcode); + break; + + case opc_fneg: + Thumb2_fNeg(jinfo, opcode); + break; + + case opc_dneg: + Thumb2_dNeg(jinfo, opcode); + break; + + case opc_i2l: { + unsigned r, r_res_lo, r_res_hi; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Spill(jinfo, 2, 0); + r_res_hi = PUSH(jstack, JSTACK_REG(jstack)); + r_res_lo = PUSH(jstack, JSTACK_REG(jstack)); + if (r == r_res_hi) { + SWAP(jstack); + r_res_hi = r_res_lo; + r_res_lo = r; + } + mov_reg(jinfo->codebuf, r_res_lo, r); + asr_imm(jinfo->codebuf, r_res_hi, r, 31); + break; + } + + case opc_l2i: { + unsigned r_lo, r_hi; + unsigned r; + + Thumb2_Fill(jinfo, 2); + r_lo = POP(jstack); + r_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r = PUSH(jstack, r_lo); + break; + } + + case opc_i2b: { + unsigned r_src, r_dst; + + Thumb2_Fill(jinfo, 1); + r_src = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_dst = PUSH(jstack, JSTACK_REG(jstack)); + sxtb(jinfo->codebuf, r_dst, r_src); + break; + } + + case opc_i2s: { + unsigned r_src, r_dst; + + Thumb2_Fill(jinfo, 1); + r_src = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_dst = PUSH(jstack, JSTACK_REG(jstack)); + sxth(jinfo->codebuf, r_dst, r_src); + break; + } + + case opc_i2c: { + unsigned r_src, r_dst; + + Thumb2_Fill(jinfo, 1); + r_src = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_dst = PUSH(jstack, JSTACK_REG(jstack)); + uxth(jinfo->codebuf, r_dst, r_src); + break; + } + + case opc_lcmp: { + unsigned lho_lo, lho_hi; + unsigned rho_lo, rho_hi; + unsigned r_tmp_lo, r_tmp_hi; + unsigned res; + unsigned loc_lt, loc_eq; + + Thumb2_Fill(jinfo, 4); + rho_lo = POP(jstack); + rho_hi = POP(jstack); + lho_lo = POP(jstack); + lho_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + res = JSTACK_REG(jstack); + PUSH(jstack, res); + r_tmp_lo = Thumb2_Tmp(jinfo, (1<<rho_lo)|(1<<rho_hi)|(1<<lho_lo)|(1<<lho_hi)); + r_tmp_hi = Thumb2_Tmp(jinfo, (1<<rho_lo)|(1<<rho_hi)|(1<<lho_lo)|(1<<lho_hi)|(1<<r_tmp_lo)); + dop_reg(jinfo->codebuf, DP_SUB, r_tmp_lo, lho_lo, rho_lo, SHIFT_LSL, 0); + dop_reg(jinfo->codebuf, DP_SBC, r_tmp_hi, lho_hi, rho_hi, SHIFT_LSL, 0); + mov_imm(jinfo->codebuf, res, (unsigned)-1); + loc_lt = forward_16(jinfo->codebuf); + dop_reg(jinfo->codebuf, DP_ORR, res, r_tmp_lo, r_tmp_hi, SHIFT_LSL, 0); + loc_eq = forward_16(jinfo->codebuf); + mov_imm(jinfo->codebuf, res, 1); + bcc_patch(jinfo->codebuf, COND_LT, loc_lt); + bcc_patch(jinfo->codebuf, COND_EQ, loc_eq); + break; + } + + case opc_iinc: { + unsigned local = code_base[bci+1]; + int constant = GET_JAVA_S1(code_base+bci+2); + unsigned r = jinfo->jregs->r_local[local]; + + if (!r) { + int nlocals = jinfo->method->max_locals(); + r = Thumb2_Tmp(jinfo, 0); + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + load_local(jinfo, r, local, stackdepth); + add_imm(jinfo->codebuf, r, r, constant); + store_local(jinfo, r, local, stackdepth); + } else { + Thumb2_Corrupt(jinfo, r, 0); + add_imm(jinfo->codebuf, r, r, constant); + } + break; + } + + case opc_getfield: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + Reg r_obj; + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) { + int java_index = GET_JAVA_U2(code_base+bci+1); + constantPoolOop pool = jinfo->method->constants(); + symbolOop sig = pool->signature_ref_at(java_index); + jbyte *base = sig->base(); + jbyte c = *base; + int handler = H_GETFIELD_WORD; + + if (c == 'J' || c == 'D') handler = H_GETFIELD_DW; + if (c == 'B' || c == 'Z') handler = H_GETFIELD_SB; + if (c == 'C') handler = H_GETFIELD_H; + if (c == 'S') handler = H_GETFIELD_SH; + Thumb2_Flush(jinfo); + Thumb2_save_locals(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, handlers[handler]); + Thumb2_restore_locals(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + TosState tos_type = cache->flag_state(); + int field_offset = cache->f2(); + + if (tos_type == ltos || tos_type == dtos) { + Reg r_lo, r_hi; + Thumb2_Fill(jinfo, 1); + r_obj = POP(jstack); + Thumb2_Spill(jinfo, 2, 0); + r_hi = PUSH(jstack, JSTACK_REG(jstack)); + r_lo = PUSH(jstack, JSTACK_REG(jstack)); + ldrd_imm(jinfo->codebuf, r_lo, r_hi, r_obj, field_offset, 1, 0); + } else { + Reg r; + + Thumb2_Fill(jinfo, 1); + r_obj = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + if (tos_type == btos) + ldrsb_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == ctos) + ldrh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == stos) + ldrsh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else + ldr_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + } + break; + } + + case opc_monitorexit: + case opc_monitorenter: + Thumb2_Exit(jinfo, H_MONITOR, bci, stackdepth); + break; + + case opc_getstatic: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) { + int java_index = GET_JAVA_U2(code_base+bci+1); + constantPoolOop pool = jinfo->method->constants(); + symbolOop sig = pool->signature_ref_at(java_index); + jbyte *base = sig->base(); + jbyte c = *base; + int handler = H_GETSTATIC_WORD; + + if (c == 'J' || c == 'D') handler = H_GETSTATIC_DW; + if (c == 'B' || c == 'Z') handler = H_GETSTATIC_SB; + if (c == 'C') handler = H_GETSTATIC_H; + if (c == 'S') handler = H_GETSTATIC_SH; + Thumb2_Flush(jinfo); + Thumb2_save_locals(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, handlers[handler]); + Thumb2_restore_locals(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + TosState tos_type = cache->flag_state(); + int field_offset = cache->f2(); + + if (tos_type == ltos || tos_type == dtos) { + Reg r_lo, r_hi; + Thumb2_Spill(jinfo, 2, 0); + r_hi = PUSH(jstack, JSTACK_REG(jstack)); + r_lo = PUSH(jstack, JSTACK_REG(jstack)); + ldr_imm(jinfo->codebuf, r_lo, Ristate, ISTATE_CONSTANTS, 1, 0); + ldr_imm(jinfo->codebuf, r_lo, r_lo, CP_OFFSET + (index << 4) + 4, 1, 0); + ldrd_imm(jinfo->codebuf, r_lo, r_hi, r_lo, field_offset, 1, 0); + } else { + Reg r; + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + ldr_imm(jinfo->codebuf, r, Ristate, ISTATE_CONSTANTS, 1, 0); + ldr_imm(jinfo->codebuf, r, r, CP_OFFSET + (index << 4) + 4, 1, 0); + if (tos_type == btos) + ldrsb_imm(jinfo->codebuf, r, r, field_offset, 1, 0); + else if (tos_type == ctos) + ldrh_imm(jinfo->codebuf, r, r, field_offset, 1, 0); + else if (tos_type == stos) + ldrsh_imm(jinfo->codebuf, r, r, field_offset, 1, 0); + else + ldr_imm(jinfo->codebuf, r, r, field_offset, 1, 0); + } + break; + } + + case opc_putfield: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + Reg r_obj; + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) { + int java_index = GET_JAVA_U2(code_base+bci+1); + constantPoolOop pool = jinfo->method->constants(); + symbolOop sig = pool->signature_ref_at(java_index); + jbyte *base = sig->base(); + jbyte c = *base; + int handler = H_PUTFIELD_WORD; + + if (c == 'J' || c == 'D') handler = H_PUTFIELD_DW; + if (c == 'B' || c == 'Z') handler = H_PUTFIELD_B; + if (c == 'C' || c == 'S') handler = H_PUTFIELD_H; + if (c == '[' || c == 'L') handler = H_PUTFIELD_A; + Thumb2_Flush(jinfo); + Thumb2_save_locals(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, handlers[handler]); + Thumb2_restore_locals(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + TosState tos_type = cache->flag_state(); + int field_offset = cache->f2(); + + if (tos_type == ltos || tos_type == dtos) { + Reg r_lo, r_hi; + Thumb2_Fill(jinfo, 3); + r_lo = POP(jstack); + r_hi = POP(jstack); + r_obj = POP(jstack); + strd_imm(jinfo->codebuf, r_lo, r_hi, r_obj, field_offset, 1, 0); + } else { + Reg r; + Thumb2_Fill(jinfo, 2); + r = POP(jstack); + r_obj = POP(jstack); + if (tos_type == btos) + strb_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == ctos | tos_type == stos) + strh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else { + str_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + if (tos_type == atos) { + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R0, r_obj); + bl(jinfo->codebuf, handlers[H_APUTFIELD]); + } + } + } + break; + } + + case opc_putstatic: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) { + int java_index = GET_JAVA_U2(code_base+bci+1); + constantPoolOop pool = jinfo->method->constants(); + symbolOop sig = pool->signature_ref_at(java_index); + jbyte *base = sig->base(); + jbyte c = *base; + int handler = H_PUTSTATIC_WORD; + + if (c == 'J' || c == 'D') handler = H_PUTSTATIC_DW; + if (c == 'B' || c == 'Z') handler = H_PUTSTATIC_B; + if (c == 'C' || c == 'S') handler = H_PUTSTATIC_H; + if (c == '[' || c == 'L') handler = H_PUTSTATIC_A; + Thumb2_Flush(jinfo); + Thumb2_save_locals(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, handlers[handler]); + Thumb2_restore_locals(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + TosState tos_type = cache->flag_state(); + int field_offset = cache->f2(); + Reg r_obj; + + if (tos_type == ltos || tos_type == dtos) { + Reg r_lo, r_hi; + Thumb2_Fill(jinfo, 2); + r_lo = POP(jstack); + r_hi = POP(jstack); + Thumb2_Spill(jinfo, 1, (1<<r_lo)|(1<<r_hi)); + r_obj = JSTACK_PREFER(jstack, ~((1<<r_lo)|(1<<r_hi))); + JASSERT(r_obj != r_lo && r_obj != r_hi, "corruption in putstatic"); + ldr_imm(jinfo->codebuf, r_obj, Ristate, ISTATE_CONSTANTS, 1, 0); + ldr_imm(jinfo->codebuf, r_obj, r_obj, CP_OFFSET + (index << 4) + 4, 1, 0); + strd_imm(jinfo->codebuf, r_lo, r_hi, r_obj, field_offset, 1, 0); + } else { + Reg r; + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Spill(jinfo, 1, (1<<r)); + r_obj = JSTACK_PREFER(jstack, ~(1<<r)); + JASSERT(r_obj != r, "corruption in putstatic"); + ldr_imm(jinfo->codebuf, r_obj, Ristate, ISTATE_CONSTANTS, 1, 0); + ldr_imm(jinfo->codebuf, r_obj, r_obj, CP_OFFSET + (index << 4) + 4, 1, 0); + if (tos_type == btos) + strb_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == ctos | tos_type == stos) + strh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else { + str_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + if (tos_type == atos) { + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R0, r_obj); + bl(jinfo->codebuf, handlers[H_APUTFIELD]); + } + } + } + break; + } + + case opc_invokestatic: + case opc_invokespecial: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + unsigned loc; + methodOop callee; + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) { + Thumb2_Flush(jinfo); + Thumb2_invoke_save(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, + handlers[opcode == opc_invokestatic ? H_INVOKESTATIC : H_INVOKESPECIAL]); + Thumb2_invoke_restore(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + callee = (methodOop)cache->f1(); + if (callee->is_accessor()) { + u1 *code = callee->code_base(); + int index = GET_NATIVE_U2(&code[2]); + constantPoolCacheOop callee_cache = callee->constants()->cache(); + ConstantPoolCacheEntry *entry = callee_cache->entry_at(index); + Reg r_obj, r; + + if (entry->is_resolved(Bytecodes::_getfield)) { +#if 0 + tty->print("Inlining accessor (opcode = %s) ", opcode == opc_invokestatic ? "invokestatic" : "invokespecial"); + callee->print_short_name(tty); + tty->print("\n"); +#endif + JASSERT(cache->parameter_size() == 1, "not 1 parameter to accessor"); + + TosState tos_type = entry->flag_state(); + int field_offset = entry->f2(); + + JASSERT(tos_type == btos || tos_type == ctos || tos_type == stos || tos_type == atos || tos_type == itos, "not itos or atos"); + + Thumb2_Fill(jinfo, 1); + r_obj = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + if (tos_type == btos) + ldrb_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == ctos) + ldrh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == stos) + ldrsh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else + ldr_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + break; + } + } + + Thumb2_Flush(jinfo); + ldr_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R0, Ristate, ISTATE_CONSTANTS, 1, 0); + mov_imm(jinfo->codebuf, ARM_R1, 0); + ldr_imm(jinfo->codebuf, ARM_R2, ARM_R2, METHOD_CONSTMETHOD, 1, 0); + if (opcode == opc_invokespecial) + ldr_imm(jinfo->codebuf, ARM_R3, Rstack, (cache->parameter_size()-1) * sizeof(int), 1, 0); + ldr_imm(jinfo->codebuf, ARM_R0, ARM_R0, CP_OFFSET + (index << 4) + 4, 1, 0); + add_imm(jinfo->codebuf, ARM_R2, ARM_R2, bci+CONSTMETHOD_CODEOFFSET); + if (opcode == opc_invokespecial) + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R3, 0, 1, 0); // Null pointer check - cbz better? + str_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R1, ARM_R0, METHOD_FROM_INTERPRETED, 1, 0); + str_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_BCP, 1, 0); + str_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + Thumb2_Debug(jinfo, H_DEBUG_METHODCALL); + Thumb2_invoke_save(jinfo, stackdepth); + sub_imm(jinfo->codebuf, Rstack, Rstack, 4); + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R1, 0, 1, 0); + mov_reg(jinfo->codebuf, ARM_R2, Rthread); + str_imm(jinfo->codebuf, Rstack, Ristate, ISTATE_STACK, 1, 0); +add_imm(jinfo->codebuf, ARM_R3, ARM_R3, CODE_ALIGN_SIZE); +// enter_leave(jinfo->codebuf, 0); + blx_reg(jinfo->codebuf, ARM_R3); +// enter_leave(jinfo->codebuf, 1); + ldr_imm(jinfo->codebuf, Rthread, Ristate, ISTATE_THREAD, 1, 0); +#ifdef USE_RLOCAL + ldr_imm(jinfo->codebuf, Rlocals, Ristate, ISTATE_LOCALS, 1, 0); +#endif + ldr_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_STACK_LIMIT, 1, 0); + JASSERT(!(bc_stackinfo[bci+len] & BC_COMPILED), "code already compiled for this bytecode?"); + Thumb2_invoke_restore(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + ldr_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_TOP_ZERO_FRAME, 1, 0); + add_imm(jinfo->codebuf, ARM_R2, ARM_R2, 4); + ldr_imm(jinfo->codebuf, ARM_R3, Rthread, THREAD_PENDING_EXC, 1, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_JAVA_SP, 1, 0); + str_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + cmp_imm(jinfo->codebuf, ARM_R3, 0); + it(jinfo->codebuf, COND_NE, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + break; + } + + case opc_invokeinterface: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + unsigned loc, loc_inc_ex; + +// Currently we just call the unresolved invokeinterface entry for resolved / +// unresolved alike! + Thumb2_Flush(jinfo); + Thumb2_invoke_save(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, handlers[H_INVOKEINTERFACE]); + Thumb2_invoke_restore(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + case opc_invokevirtual: { + constantPoolCacheOop cp = jinfo->method->constants()->cache(); + ConstantPoolCacheEntry* cache; + int index = GET_NATIVE_U2(code_base+bci+1); + unsigned loc; + + cache = cp->entry_at(index); + if (!cache->is_resolved((Bytecodes::Code)opcode)) { + Thumb2_Flush(jinfo); + Thumb2_invoke_save(jinfo, stackdepth); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, index); + blx(jinfo->codebuf, handlers[H_INVOKEVIRTUAL]); + Thumb2_invoke_restore(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + break; + } + + if (cache->is_vfinal()) { + methodOop callee = (methodOop)cache->f2(); + if (callee->is_accessor()) { + u1 *code = callee->code_base(); + int index = GET_NATIVE_U2(&code[2]); + constantPoolCacheOop callee_cache = callee->constants()->cache(); + ConstantPoolCacheEntry *entry = callee_cache->entry_at(index); + Reg r_obj, r; + + if (entry->is_resolved(Bytecodes::_getfield)) { +#if 0 + tty->print("Inlining accessor (opcode = invokevfinal) "); + callee->print_short_name(tty); + tty->print("\n"); +#endif + JASSERT(cache->parameter_size() == 1, "not 1 parameter to accessor"); + + TosState tos_type = entry->flag_state(); + int field_offset = entry->f2(); + + JASSERT(tos_type == btos || tos_type == ctos || tos_type == stos || tos_type == atos || tos_type == itos, "not itos or atos"); + + Thumb2_Fill(jinfo, 1); + r_obj = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r = JSTACK_REG(jstack); + PUSH(jstack, r); + if (tos_type == btos) + ldrb_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == ctos) + ldrh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else if (tos_type == stos) + ldrsh_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + else + ldr_imm(jinfo->codebuf, r, r_obj, field_offset, 1, 0); + break; + } + } + } + + Thumb2_Flush(jinfo); + if (cache->is_vfinal()) { + ldr_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R0, Ristate, ISTATE_CONSTANTS, 1, 0); + mov_imm(jinfo->codebuf, ARM_R1, 0); + ldr_imm(jinfo->codebuf, ARM_R3, Rstack, (cache->parameter_size()-1) * sizeof(int), 1, 0); + ldr_imm(jinfo->codebuf, ARM_R0, ARM_R0, CP_OFFSET + (index << 4) + 8, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R2, ARM_R2, METHOD_CONSTMETHOD, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R3, 0, 1, 0); // Null pointer check - cbz better? + str_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R1, ARM_R0, METHOD_FROM_INTERPRETED, 1, 0); + add_imm(jinfo->codebuf, ARM_R2, ARM_R2, bci+CONSTMETHOD_CODEOFFSET); + str_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + Thumb2_Debug(jinfo, H_DEBUG_METHODCALL); + Thumb2_invoke_save(jinfo, stackdepth); + sub_imm(jinfo->codebuf, Rstack, Rstack, 4); + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R1, 0, 1, 0); + str_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_BCP, 1, 0); + mov_reg(jinfo->codebuf, ARM_R2, Rthread); + str_imm(jinfo->codebuf, Rstack, Ristate, ISTATE_STACK, 1, 0); +add_imm(jinfo->codebuf, ARM_R3, ARM_R3, CODE_ALIGN_SIZE); +// enter_leave(jinfo->codebuf, 0); + blx_reg(jinfo->codebuf, ARM_R3); +// enter_leave(jinfo->codebuf, 1); + ldr_imm(jinfo->codebuf, Rthread, Ristate, ISTATE_THREAD, 1, 0); +#ifdef USE_RLOCAL + ldr_imm(jinfo->codebuf, Rlocals, Ristate, ISTATE_LOCALS, 1, 0); +#endif + ldr_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_STACK_LIMIT, 1, 0); + JASSERT(!(bc_stackinfo[bci+len] & BC_COMPILED), "code already compiled for this bytecode?"); + Thumb2_invoke_restore(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + ldr_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_TOP_ZERO_FRAME, 1, 0); + add_imm(jinfo->codebuf, ARM_R2, ARM_R2, 4); + ldr_imm(jinfo->codebuf, ARM_R3, Rthread, THREAD_PENDING_EXC, 1, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_JAVA_SP, 1, 0); + str_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + cmp_imm(jinfo->codebuf, ARM_R3, 0); + it(jinfo->codebuf, COND_NE, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + break; + } else { + ldr_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R3, Rstack, (cache->parameter_size()-1) * sizeof(int), 1, 0); + ldr_imm(jinfo->codebuf, ARM_R2, ARM_R2, METHOD_CONSTMETHOD, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R3, 4, 1, 0); + mov_imm(jinfo->codebuf, ARM_R1, 0); + ldr_imm(jinfo->codebuf, ARM_R0, ARM_R3, INSTANCEKLASS_VTABLE_OFFSET + cache->f2() * 4, 1, 0); + add_imm(jinfo->codebuf, ARM_R2, ARM_R2, bci+CONSTMETHOD_CODEOFFSET); + str_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R1, ARM_R0, METHOD_FROM_INTERPRETED, 1, 0); + str_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_BCP, 1, 0); + str_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + Thumb2_Debug(jinfo, H_DEBUG_METHODCALL); + Thumb2_invoke_save(jinfo, stackdepth); + sub_imm(jinfo->codebuf, Rstack, Rstack, 4); + ldr_imm(jinfo->codebuf, ARM_R3, ARM_R1, 0, 1, 0); + mov_reg(jinfo->codebuf, ARM_R2, Rthread); + str_imm(jinfo->codebuf, Rstack, Ristate, ISTATE_STACK, 1, 0); +add_imm(jinfo->codebuf, ARM_R3, ARM_R3, CODE_ALIGN_SIZE); +// enter_leave(jinfo->codebuf, 0); + blx_reg(jinfo->codebuf, ARM_R3); +// enter_leave(jinfo->codebuf, 1); + ldr_imm(jinfo->codebuf, Rthread, Ristate, ISTATE_THREAD, 1, 0); +#ifdef USE_RLOCAL + ldr_imm(jinfo->codebuf, Rlocals, Ristate, ISTATE_LOCALS, 1, 0); +#endif + ldr_imm(jinfo->codebuf, Rstack, Rthread, THREAD_JAVA_SP, 1, 0); + ldr_imm(jinfo->codebuf, ARM_R2, Ristate, ISTATE_STACK_LIMIT, 1, 0); + JASSERT(!(bc_stackinfo[bci+len] & BC_COMPILED), "code already compiled for this bytecode?"); + Thumb2_invoke_restore(jinfo, bc_stackinfo[bci+len] & ~BC_FLAGS_MASK); + ldr_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_TOP_ZERO_FRAME, 1, 0); + add_imm(jinfo->codebuf, ARM_R2, ARM_R2, 4); + ldr_imm(jinfo->codebuf, ARM_R3, Rthread, THREAD_PENDING_EXC, 1, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_JAVA_SP, 1, 0); + str_imm(jinfo->codebuf, ARM_R1, Rthread, THREAD_LAST_JAVA_SP, 1, 0); + cmp_imm(jinfo->codebuf, ARM_R3, 0); + it(jinfo->codebuf, COND_NE, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + } + break; + } + + case opc_jsr_w: + case opc_jsr: { + Thumb2_Jsr(jinfo , bci, stackdepth); + break; + } + + case opc_ret: { + Thumb2_Exit(jinfo, H_RET, bci, stackdepth); + break; + } + + case opc_athrow: + Thumb2_Exit(jinfo, H_ATHROW, bci, stackdepth); + break; + + case opc_goto: { + int offset = GET_JAVA_S2(jinfo->code_base + bci + 1); + Thumb2_Flush(jinfo); + bci = Thumb2_Goto(jinfo, bci, offset, len); + len = 0; + break; + } + + case opc_goto_w: { + int offset = GET_JAVA_U4(jinfo->code_base + bci + 1); + Thumb2_Flush(jinfo); + bci = Thumb2_Goto(jinfo, bci, offset, len); + len = 0; + break; + } + + case opc_ifeq: + case opc_ifne: + case opc_iflt: + case opc_ifge: + case opc_ifgt: + case opc_ifle: + case opc_ifnull: + case opc_ifnonnull: { + Reg r; + unsigned cond = opcode - opc_ifeq; + if (opcode >= opc_ifnull) cond = opcode - opc_ifnull; + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Flush(jinfo); + cmp_imm(jinfo->codebuf, r, 0); + bci = Thumb2_Branch(jinfo, bci, cond); + len = 0; + break; + } + + case opc_if_icmpeq: + case opc_if_icmpne: + case opc_if_icmplt: + case opc_if_icmpge: + case opc_if_icmpgt: + case opc_if_icmple: + case opc_if_acmpeq: + case opc_if_acmpne: { + Reg r_lho, r_rho; + unsigned cond = opcode - opc_if_icmpeq; + if (opcode >= opc_if_acmpeq) cond = opcode - opc_if_acmpeq; + Thumb2_Fill(jinfo, 2); + r_rho = POP(jstack); + r_lho = POP(jstack); + Thumb2_Flush(jinfo); + cmp_reg(jinfo->codebuf, r_lho, r_rho); + bci = Thumb2_Branch(jinfo, bci, cond); + len = 0; + break; + } + + case opc_return: + case opc_dreturn: + case opc_lreturn: + case opc_ireturn: + case opc_freturn: + case opc_areturn: + Thumb2_Return(jinfo, opcode); + if (!jinfo->compiled_return) jinfo->compiled_return = bci; + break; + + case opc_new: { + unsigned loc; + + Thumb2_Flush(jinfo); + mov_imm(jinfo->codebuf, ARM_R1, GET_JAVA_U2(code_base+bci+1)); + mov_imm(jinfo->codebuf, ARM_R3, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth); + bl(jinfo->codebuf, handlers[H_NEW]); + Thumb2_restore_locals(jinfo, stackdepth); + cmp_imm(jinfo->codebuf, ARM_R0, 0); + it(jinfo->codebuf, COND_EQ, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + PUSH(jstack, ARM_R0); + break; + } + + case opc_aastore: { + Reg src[3], dst[3]; + unsigned loc; + + Thumb2_Fill(jinfo, 3); + src[0] = POP(jstack); // value + src[1] = POP(jstack); // index + src[2] = POP(jstack); // arrayref + Thumb2_Flush(jinfo); + dst[0] = ARM_R1; + dst[1] = ARM_R2; + dst[2] = ARM_R3; + mov_multiple(jinfo->codebuf, dst, src, 3); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth - 3); // 3 args popped above + bl(jinfo->codebuf, handlers[H_AASTORE]); + Thumb2_restore_locals(jinfo, stackdepth - 3); + cmp_imm(jinfo->codebuf, ARM_R0, 0); + it(jinfo->codebuf, COND_NE, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + break; + } + + case opc_instanceof: { + unsigned loc; + Reg r; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R2, r); + mov_imm(jinfo->codebuf, ARM_R1, GET_JAVA_U2(code_base+bci+1)); + mov_imm(jinfo->codebuf, ARM_R3, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth - 1); + bl(jinfo->codebuf, handlers[H_INSTANCEOF]); + Thumb2_restore_locals(jinfo, stackdepth - 1); // 1 arg popped above + cmp_imm(jinfo->codebuf, ARM_R0, (unsigned)-1); + it(jinfo->codebuf, COND_EQ, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + PUSH(jstack, ARM_R0); + break; + } + + case opc_checkcast: { + unsigned loc; + Reg r; + + Thumb2_Fill(jinfo, 1); + r = TOS(jstack); + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R2, r); + mov_imm(jinfo->codebuf, ARM_R1, GET_JAVA_U2(code_base+bci+1)); + mov_imm(jinfo->codebuf, ARM_R3, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth); + bl(jinfo->codebuf, handlers[H_CHECKCAST]); + Thumb2_restore_locals(jinfo, stackdepth); + cmp_imm(jinfo->codebuf, ARM_R0, 0); + it(jinfo->codebuf, COND_NE, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + break; + } + + case opc_newarray: { + Reg r; + unsigned loc; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R2, r); + mov_imm(jinfo->codebuf, ARM_R1, code_base[bci+1]); + mov_imm(jinfo->codebuf, ARM_R3, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth-1); + bl(jinfo->codebuf, handlers[H_NEWARRAY]); + Thumb2_restore_locals(jinfo, stackdepth-1); + ldr_imm(jinfo->codebuf, ARM_R0, Rthread, THREAD_VM_RESULT, 1, 0); + mov_imm(jinfo->codebuf, ARM_R2, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_VM_RESULT, 1, 0); + cmp_imm(jinfo->codebuf, ARM_R0, 0); + it(jinfo->codebuf, COND_EQ, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + PUSH(jstack, ARM_R0); + break; + } + + case opc_anewarray: { + Reg r; + unsigned loc; + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + Thumb2_Flush(jinfo); + mov_reg(jinfo->codebuf, ARM_R3, r); + mov_imm(jinfo->codebuf, ARM_R2, GET_JAVA_U2(code_base+bci+1)); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + Thumb2_save_locals(jinfo, stackdepth-1); + bl(jinfo->codebuf, handlers[H_ANEWARRAY]); + Thumb2_restore_locals(jinfo, stackdepth-1); + ldr_imm(jinfo->codebuf, ARM_R0, Rthread, THREAD_VM_RESULT, 1, 0); + mov_imm(jinfo->codebuf, ARM_R2, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_VM_RESULT, 1, 0); + cmp_imm(jinfo->codebuf, ARM_R0, 0); + it(jinfo->codebuf, COND_EQ, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + PUSH(jstack, ARM_R0); + break; + } + + case opc_multianewarray: { + unsigned loc; + + Thumb2_Flush(jinfo); + mov_imm(jinfo->codebuf, ARM_R0, bci+CONSTMETHOD_CODEOFFSET); + mov_imm(jinfo->codebuf, ARM_R1, code_base[bci+3] * 4); + Thumb2_save_locals(jinfo, stackdepth); + bl(jinfo->codebuf, handlers[H_MULTIANEWARRAY]); + Thumb2_restore_locals(jinfo, stackdepth - code_base[bci+3]); + ldr_imm(jinfo->codebuf, ARM_R0, Rthread, THREAD_VM_RESULT, 1, 0); + mov_imm(jinfo->codebuf, ARM_R2, 0); + str_imm(jinfo->codebuf, ARM_R2, Rthread, THREAD_VM_RESULT, 1, 0); + cmp_imm(jinfo->codebuf, ARM_R0, 0); + it(jinfo->codebuf, COND_EQ, IT_MASK_T); + bl(jinfo->codebuf, handlers[H_HANDLE_EXCEPTION]); + PUSH(jstack, ARM_R0); + break; + } + + case opc_arraylength: { + Reg r_obj, r_len; + + Thumb2_Fill(jinfo, 1); + r_obj = POP(jstack); + Thumb2_Spill(jinfo, 1, 0); + r_len = JSTACK_REG(jstack); + PUSH(jstack, r_len); + ldr_imm(jinfo->codebuf, r_len, r_obj, 8, 1, 0); + break; + } + + case opc_lookupswitch: { + unsigned w; + unsigned nbci; + int def; + int npairs; // The Java spec says signed but must be >= 0?? + unsigned *table, *tablep; + unsigned r; + unsigned oldidx; + unsigned table_loc; + int i; + + nbci = bci & ~3; + w = *(unsigned int *)(code_base + nbci + 4); + def = bci + (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 8); + npairs = (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 12); + + Thumb2_Fill(jinfo, 1); + r = POP(jstack); + + table_loc = out_loc(jinfo->codebuf); + for (i = 0, tablep = table; i < npairs; i++) { + unsigned match; + + w = tablep[0]; + match = BYTESEX_REVERSE(w); + tablep += 2; + cmp_imm(jinfo->codebuf, r, match); + t2_bug_align(jinfo->codebuf); + forward_32(jinfo->codebuf); + } + t2_bug_align(jinfo->codebuf); + forward_32(jinfo->codebuf); + Thumb2_codegen(jinfo, bci+len); + + oldidx = codebuf->idx; + codebuf->idx = table_loc >> 1; + for (i = 0, tablep = table; i < npairs; i++) { + unsigned match; + unsigned dest; + unsigned loc; + + w = tablep[0]; + match = BYTESEX_REVERSE(w); + w = tablep[1]; + dest = bci + (int)BYTESEX_REVERSE(w); + tablep += 2; + cmp_imm(jinfo->codebuf, r, match); + JASSERT(jinfo->bc_stackinfo[dest] & BC_COMPILED, "code not compiled"); + t2_bug_align(jinfo->codebuf); + loc = forward_32(jinfo->codebuf); + branch_patch(jinfo->codebuf, COND_EQ, loc, jinfo->bc_stackinfo[dest] & ~BC_FLAGS_MASK); + } + JASSERT(jinfo->bc_stackinfo[def] & BC_COMPILED, "default in lookupswitch not compiled"); + t2_bug_align(jinfo->codebuf); + branch_uncond_patch(jinfo->codebuf, out_loc(jinfo->codebuf), jinfo->bc_stackinfo[def] & ~BC_FLAGS_MASK); + codebuf->idx = oldidx; + + bci = (unsigned)-1; + len = 0; + + break; + } + + case opc_tableswitch: { + int low, high, i; + unsigned w; + unsigned *table, *tablep; + unsigned nbci; + int def; + unsigned loc, table_loc; + unsigned r, rs; + unsigned oldidx; + unsigned negative_offsets, negative_branch_table; + + nbci = bci & ~3; + w = *(unsigned int *)(code_base + nbci + 8); + low = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 12); + high = (int)BYTESEX_REVERSE(w); + w = *(unsigned int *)(code_base + nbci + 4); + def = bci + (int)BYTESEX_REVERSE(w); + table = (unsigned int *)(code_base + nbci + 16); + + Thumb2_Fill(jinfo, 1); + rs = POP(jstack); + r = Thumb2_Tmp(jinfo, (1<<rs)); + sub_imm(jinfo->codebuf, r, rs, low); + cmp_imm(jinfo->codebuf, r, (high-low)+1); + loc = 0; + if (jinfo->bc_stackinfo[def] & BC_COMPILED) + branch(jinfo->codebuf, COND_CS, jinfo->bc_stackinfo[def] & ~BC_FLAGS_MASK); + else + loc = forward_32(jinfo->codebuf); + tbh(jinfo->codebuf, ARM_PC, r); + table_loc = out_loc(jinfo->codebuf); + negative_offsets = 0; + for (i = low, tablep = table; i <= high; i++) { + int offset; + w = *tablep++; + offset = (int)BYTESEX_REVERSE(w); + if (offset < 0) negative_offsets++; + out_16(jinfo->codebuf, 0); + } + negative_branch_table = out_loc(jinfo->codebuf); + for (i = 0; i < (int)negative_offsets; i++) { + t2_bug_align(jinfo->codebuf); + out_16x2(jinfo->codebuf, 0); + } + + Thumb2_codegen(jinfo, bci+len); + + if (loc) { + JASSERT(jinfo->bc_stackinfo[def] & BC_COMPILED, "def not compiled in tableswitch"); + branch_patch(jinfo->codebuf, COND_CS, loc, jinfo->bc_stackinfo[def] & ~BC_FLAGS_MASK); + } + + oldidx = codebuf->idx; + codebuf->idx = table_loc >> 1; + for (i = low, tablep = table; i <= high; i++) { + unsigned dest; + int offset; + + w = *tablep++; + offset = (int)BYTESEX_REVERSE(w); + dest = bci + offset; + JASSERT(jinfo->bc_stackinfo[dest] & BC_COMPILED, "code not compiled"); + dest = jinfo->bc_stackinfo[dest] & ~BC_FLAGS_MASK; + if (offset < 0) { + unsigned oldidx; + out_16(jinfo->codebuf, (negative_branch_table >> 1) - (table_loc >> 1)); + PATCH(negative_branch_table) { + t2_bug_align(jinfo->codebuf); + branch_uncond_patch(jinfo->codebuf, out_loc(jinfo->codebuf), dest); + negative_branch_table = out_loc(jinfo->codebuf); + } HCTAP; + } else { + JASSERT((dest & 1) == 0 && (table_loc & 1) == 0, "unaligned code"); + offset = (dest >> 1) - (table_loc >> 1); + JASSERT(offset < 65536, "offset too big in tableswitch"); + out_16(jinfo->codebuf, offset); + } + } + codebuf->idx = oldidx; + bci = (unsigned)-1; + len = 0; + break; + } + + case opc_wide: { + unsigned local = GET_JAVA_U2(code_base + bci + 2); + opcode = code_base[bci+1]; + if (opcode == opc_iinc) { + int constant = GET_JAVA_S2(code_base + bci + 4); + unsigned r = jinfo->jregs->r_local[local]; + + if (!r) { + int nlocals = jinfo->method->max_locals(); + r = ARM_IP; + stackdepth -= jstack->depth; + if (jinfo->method->is_synchronized()) stackdepth += frame::interpreter_frame_monitor_size(); + load_local(jinfo, r, local, stackdepth); + add_imm(jinfo->codebuf, r, r, constant); + store_local(jinfo, r, local, stackdepth); + } else { + Thumb2_Corrupt(jinfo, r, 0); + add_imm(jinfo->codebuf, r, r, constant); + } + } else if (opcode == opc_ret) { + Thumb2_Exit(jinfo, H_RET, bci, stackdepth); + } else { + if (opcode == opc_iload || + opcode == opc_fload || opcode == opc_aload) + Thumb2_Load(jinfo, local, stackdepth); + else if (opcode == opc_lload || opcode == opc_dload) + Thumb2_LoadX2(jinfo, local, stackdepth); + else if (opcode == opc_istore || + opcode == opc_fstore || opcode == opc_astore) + Thumb2_Store(jinfo, local, stackdepth); + else if (opcode == opc_lstore || opcode == opc_dstore) + Thumb2_StoreX2(jinfo, local, stackdepth); + else fatal1("Undefined wide opcode %d\n", opcode); + } + break; + } + + default: + printf("unknown bytecode = %d\n", opcode); + JASSERT(0, "unknown bytecode"); + break; + } + bci += len; +#ifdef T2EE_PRINT_DISASS + if (len == 0) { + if (start_idx == jinfo->codebuf->idx) start_bci[start_idx] = -1; + } else + end_bci[start_idx] = bci; +#endif + } +} + +void Thumb2_tablegen(Thumb2_Info *jinfo) +{ + unsigned code_size = jinfo->code_size; + jubyte *code_base = jinfo->code_base; + unsigned *bc_stackinfo = jinfo->bc_stackinfo; + unsigned bci; + unsigned *count_pos = (unsigned *)out_pos(jinfo->codebuf); + unsigned count = 0; + + out_32(jinfo->codebuf, 0); + bc_stackinfo[0] |= BC_BACK_TARGET; + for (bci = 0; bci < code_size;) { + unsigned stackinfo = bc_stackinfo[bci]; + unsigned bytecodeinfo; + unsigned opcode; + + if (stackinfo & BC_BACK_TARGET) { + unsigned code_offset = (stackinfo & ~BC_FLAGS_MASK) >> 1; + JASSERT(stackinfo & BC_COMPILED, "back branch target not compiled???"); + JASSERT(code_offset < (1<<16), "oops, codesize too big"); + out_32(jinfo->codebuf, (bci << 16) | code_offset); + count++; + } + + opcode = code_base[bci]; + bytecodeinfo = bcinfo[opcode]; + if (!BCI_SPECIAL(bytecodeinfo)) { + bci += BCI_LEN(bytecodeinfo); + continue; + } else { + int len = Bytecodes::length_for((Bytecodes::Code)opcode); + if (len <= 0) len = Bytecodes::special_length_at((address)(code_base+bci), (address)(code_base+code_size)); + bci += len; + } + } + *count_pos = count; +} + +unsigned Thumb2_osr_from_bci(unsigned slow_entry, unsigned bci) +{ + unsigned *osr_table; + unsigned count; + unsigned i; + + slow_entry &= ~1; + osr_table = *(unsigned **)(slow_entry+12); + if (!osr_table) return 0; + count = *osr_table++; + for (i = 0; i < count; i++) { + unsigned u = *osr_table++; + + if (bci == (u>>16)) return (u & 0xffff) << 1; + } + return 0; +} + +static int DebugSwitch = 1; + +extern "C" void Debug_Ignore_Safepoints(void) +{ + printf("Ignore Safepoints\n"); +} + +extern "C" void Debug_Notice_Safepoints(void) +{ + printf("Notice Safepoints\n"); +} + +extern "C" void Debug_ExceptionReturn(interpreterState istate, intptr_t *stack) +{ + JavaThread *thread = istate->thread(); + + if (thread->has_pending_exception()) { + Handle ex(thread, thread->pending_exception()); + tty->print_cr("Exception %s", Klass::cast(ex->klass())->external_name()); + } +} + +extern "C" void Debug_Stack(intptr_t *stack) +{ + int i; + char msg[16]; + + tty->print(" Stack:"); + for (i = 0; i < 6; i++) { + tty->print(" ["); + sprintf(msg, "%d", i); + tty->print(msg); + tty->print("] = "); + sprintf(msg, "%08x", (int)stack[i]); + tty->print(msg); + } + tty->cr(); +} + +extern "C" void Debug_MethodEntry(interpreterState istate, intptr_t *stack, methodOop callee) +{ +#if 0 + if (DebugSwitch) { + methodOop method = istate->method(); + tty->print("Entering "); + callee->print_short_name(tty); + tty->print(" from "); + method->print_short_name(tty); + tty->cr(); + Debug_Stack(stack); + tty->flush(); + } +#endif +} + +extern "C" void Debug_MethodExit(interpreterState istate, intptr_t *stack) +{ + if (DebugSwitch) { + methodOop method = istate->method(); + JavaThread *thread = istate->thread(); + oop exc = thread->pending_exception(); + + if (!exc) return; + tty->print("Leaving "); + method->print_short_name(tty); + tty->cr(); + Debug_Stack(stack); + tty->flush(); + if (exc) tty->print_cr("Exception %s", exc->print_value_string()); + } +} + +extern "C" void Debug_MethodCall(interpreterState istate, intptr_t *stack, methodOop callee) +{ +#if 0 + if (DebugSwitch) { + methodOop method = istate->method(); + tty->print("Calling "); + callee->print_short_name(tty); + tty->print(" from "); + method->print_short_name(tty); + tty->cr(); + Debug_Stack(stack); + tty->flush(); + } +#endif +} + +extern "C" int Debug_irem_Handler(int a, int b) +{ + printf("%d %% %d\n", a, b); + return a%b; +} + +extern "C" void Thumb2_Install(methodOop mh, u32 entry); + +#define IS_COMPILED(e, cb) ((e) >= (unsigned)(cb) && (e) < (unsigned)(cb) + (cb)->size) + +static unsigned compiling; +static unsigned CompileCount = 0; +static unsigned MaxCompile = 75; + +#define COMPILE_ONLY 0 +#define COMPILE_COUNT 0 +#define DISASS_AFTER 0 +//#define COMPILE_LIST 0 + +#ifdef COMPILE_LIST +static const char *compile_list[] = { + "java.util.concurrent.ConcurrentHashMap.<init>(IFI)V", + 0 +}; +#endif + +static unsigned compiled_methods = 0; + +#ifdef T2EE_PRINT_STATISTICS +static unsigned bytecodes_compiled = 0; +static unsigned arm_code_generated = 0; +static unsigned total_zombie_bytes = 0; +static clock_t total_compile_time = 0; +#endif + +extern "C" void Thumb2_Clear_Cache(char *base, char *limit); + +extern unsigned CPUInfo; + +extern "C" unsigned long long Thumb2_Compile(JavaThread *thread, unsigned branch_pc) +{ + frame fr = thread->last_frame(); + methodOop method = fr.interpreter_frame_method(); + symbolOop name = method->name(); + symbolOop sig = method->signature(); + jbyte *base = sig->base();; + + jubyte *code_base = (jubyte *)method->code_base(); + int code_size = method->code_size(); + InvocationCounter* ic = method->invocation_counter(); + InvocationCounter* bc = method->backedge_counter(); + Thumb2_Info jinfo_str; + CodeBuf codebuf_str; + Thumb2_Stack jstack_str; + Thumb2_Registers jregs_str; + int idx; + u32 code_handle, slow_entry; + u32 osr_entry; + Thumb2_CodeBuf *cb = thumb2_codebuf; + int compiled_accessor; + + if (!(CPUInfo & ARCH_THUMBEE)) { + ic->decay(); + bc->decay(); + return 0; + } + + slow_entry = *(unsigned *)method->from_interpreted_entry(); + if (IS_COMPILED(slow_entry, cb)) { + osr_entry = Thumb2_osr_from_bci(slow_entry, branch_pc); + if (osr_entry == 0) return 0; + return ((unsigned long long)(slow_entry + 16)) << 32 | (slow_entry+osr_entry); + } + + ic->decay(); + bc->decay(); + + // Dont compile anything with code size >= 32K. + // We rely on the bytecode index fitting in 16 bits + if (code_size >= 8000) + return 0; + + // Dont compile anything with max stack + maxlocal > 1K + // The range of an LDR in T2 is -4092..4092 + // Othersize we have difficulty access the locals from the stack pointer + if ((method->max_locals() + method->max_stack()) >= 1000) + return 0; + + if (COMPILE_COUNT && compiled_methods == COMPILE_COUNT) return 0; + + if (method->has_monitor_bytecodes()) return 0; + + if (method->has_exception_handler()) return 0; + + if (COMPILE_ONLY) { + if (strcmp(name->as_C_string(), COMPILE_ONLY) != 0) return 0; + } + +#ifdef COMPILE_LIST + { + const char **argv = compile_list; + const char *s; + while (s = *argv++) { + if (strcmp(s, method->name_and_sig_as_C_string()) == 0) + break; + } + if (!s) return 0; + } +#endif + + if (compiling) return 0; + compiling = 1; + +#ifdef T2EE_PRINT_STATISTICS + clock_t compile_time = clock(); +#endif + +#ifdef T2EE_PRINT_COMPILATION + if (t2ee_print_compilation) { + tty->print("Compiling (%d) ", compiled_methods); + tty->print_cr("%s", method->name_and_sig_as_C_string()); + } +#endif + + memset(bc_stackinfo, 0, code_size * sizeof(unsigned)); + memset(locals_info, 0, method->max_locals() * sizeof(unsigned)); +#ifdef T2EE_PRINT_DISASS + memset(start_bci, 0xff, sizeof(start_bci)); + memset(end_bci, 0xff, sizeof(end_bci)); +#endif + + jinfo_str.thread = thread; + jinfo_str.method = method; + jinfo_str.code_base = code_base; + jinfo_str.code_size = code_size; + jinfo_str.bc_stackinfo = bc_stackinfo; + jinfo_str.locals_info = locals_info; + jinfo_str.compiled_return = 0; + jinfo_str.zombie_bytes = 0; + + Thumb2_local_info_from_sig(&jinfo_str, method, base); + + Thumb2_pass1(&jinfo_str, 0); + Thumb2_pass2(&jinfo_str, 0, 0); + + codebuf_str.codebuf = (unsigned short *)cb->hp; + codebuf_str.idx = 0; + + jstack_str.stack = stack; + jstack_str.depth = 0; + + memset(r_local, 0, method->max_locals() * sizeof(unsigned)); + + jregs_str.r_local = r_local; + + jinfo_str.codebuf = &codebuf_str; + jinfo_str.jstack = &jstack_str; + jinfo_str.jregs = &jregs_str; + +#ifdef USE_RLOCAL + { + Reg pregs[4]; + pregs[0] = JAZ_V1; + pregs[1] = JAZ_V2; + pregs[2] = JAZ_V4; + pregs[3] = JAZ_V5; + Thumb2_RegAlloc(&jinfo_str, pregs, 4); + } +#else + { + Reg pregs[5]; + pregs[0] = JAZ_V1; + pregs[1] = JAZ_V2; + pregs[2] = JAZ_V3; + pregs[3] = JAZ_V4; + pregs[4] = JAZ_V5; + Thumb2_RegAlloc(&jinfo_str, pregs, 5); + } +#endif + + slow_entry = out_align(&codebuf_str, CODE_ALIGN); + + cb->hp += codebuf_str.idx * 2; + codebuf_str.codebuf = (unsigned short *)cb->hp; + codebuf_str.idx = 0; + + compiled_accessor = 0; + if (method->is_accessor() && Thumb2_Accessor(&jinfo_str)) { + compiled_accessor = 1; + } else { + Thumb2_Enter(&jinfo_str); + Thumb2_codegen(&jinfo_str, 0); + } + +#ifdef T2EE_PRINT_DISASS + if (DISASS_AFTER == 0 || compiled_methods >= DISASS_AFTER) + if (t2ee_print_disass) + Thumb2_disass(&jinfo_str); +#endif + + Thumb2_Clear_Cache(cb->hp, cb->hp + codebuf_str.idx * 2); + +#ifdef T2EE_PRINT_STATISTICS + compile_time = clock() - compile_time; + total_compile_time += compile_time; + + if (t2ee_print_statistics) { + unsigned codegen = codebuf_str.idx * 2; + bytecodes_compiled += code_size; + arm_code_generated += codegen; + total_zombie_bytes += jinfo_str.zombie_bytes; + tty->print("%d bytecodes => %d bytes code in %.2f sec, totals: %d => %d in %.2f sec\n", + code_size, codegen, (double)compile_time/(double)CLOCKS_PER_SEC, + bytecodes_compiled, arm_code_generated, (double)total_compile_time/(double)CLOCKS_PER_SEC); + } +#endif + + code_handle = out_align(&codebuf_str, sizeof(address)); + + out_32(&codebuf_str, slow_entry + 1); + + if (!compiled_accessor) { + unsigned osr_entry_table = out_pos(jinfo_str.codebuf); + + Thumb2_tablegen(&jinfo_str); + + *(unsigned *)(slow_entry + 12) = osr_entry_table; + } + + cb->hp += codebuf_str.idx * 2; + + Thumb2_Install(method, code_handle); + + compiled_methods++; + + compiling = 0; + + osr_entry = Thumb2_osr_from_bci(slow_entry, branch_pc); + + if (osr_entry == 0) return 0; + + return ((unsigned long long)(slow_entry + 16 + 1)) << 32 | (slow_entry+osr_entry+1); +} + +extern "C" void Thumb2_DivZero_Handler(void); +extern "C" void Thumb2_ArrayBounds_Handler(void); +extern "C" void Thumb2_Handle_Exception(void); +extern "C" void Thumb2_Exit_To_Interpreter(void); + +extern "C" void __divsi3(void); +extern "C" void __aeabi_ldivmod(void); +extern "C" void __aeabi_i2f(void); +extern "C" void __aeabi_i2d(void); +extern "C" void __aeabi_l2f(void); +extern "C" void __aeabi_l2d(void); +extern "C" void __aeabi_f2d(void); +extern "C" void __aeabi_d2f(void); +extern "C" void Helper_new(void); +extern "C" void Helper_instanceof(void); +extern "C" void Helper_checkcast(void); +extern "C" void Helper_aastore(void); +extern "C" void Helper_aputfield(void); +extern "C" void Helper_synchronized_enter(void); +extern "C" void Helper_synchronized_exit(void); + +extern "C" void _ZN13SharedRuntime3f2iEf(void); +extern "C" void _ZN13SharedRuntime3f2lEf(void); +extern "C" void _ZN13SharedRuntime3d2iEd(void); +extern "C" void _ZN13SharedRuntime3d2lEd(void); +extern "C" void _ZN18InterpreterRuntime8newarrayEP10JavaThread9BasicTypei(void); +extern "C" void _ZN18InterpreterRuntime9anewarrayEP10JavaThreadP19constantPoolOopDescii(void); +extern "C" void _ZN18InterpreterRuntime14multianewarrayEP10JavaThreadPi(void); +extern "C" void _ZN18InterpreterRuntime3ldcEP10JavaThreadb(void); + +extern char Thumb2_stubs[]; +extern char Thumb2_stubs_end[]; +extern char Thumb2_idiv_stub[]; +extern char Thumb2_irem_stub[]; +extern char Thumb2_invokeinterface_stub[]; +extern char Thumb2_invokevirtual_stub[]; +extern char Thumb2_invokestatic_stub[]; +extern char Thumb2_invokespecial_stub[]; +extern char Thumb2_getfield_word_stub[]; +extern char Thumb2_getfield_sh_stub[]; +extern char Thumb2_getfield_h_stub[]; +extern char Thumb2_getfield_sb_stub[]; +extern char Thumb2_getfield_dw_stub[]; +extern char Thumb2_putfield_word_stub[]; +extern char Thumb2_putfield_h_stub[]; +extern char Thumb2_putfield_b_stub[]; +extern char Thumb2_putfield_a_stub[]; +extern char Thumb2_putfield_dw_stub[]; +extern char Thumb2_getstatic_word_stub[]; +extern char Thumb2_getstatic_sh_stub[]; +extern char Thumb2_getstatic_h_stub[]; +extern char Thumb2_getstatic_sb_stub[]; +extern char Thumb2_getstatic_dw_stub[]; +extern char Thumb2_putstatic_word_stub[]; +extern char Thumb2_putstatic_h_stub[]; +extern char Thumb2_putstatic_b_stub[]; +extern char Thumb2_putstatic_a_stub[]; +extern char Thumb2_putstatic_dw_stub[]; + +#define STUBS_SIZE (Thumb2_stubs_end-Thumb2_stubs) +#define IDIV_STUB (Thumb2_idiv_stub-Thumb2_stubs) +#define IREM_STUB (Thumb2_irem_stub-Thumb2_stubs) +#define INVOKEINTERFACE_STUB (Thumb2_invokeinterface_stub-Thumb2_stubs) +#define INVOKEVIRTUAL_STUB (Thumb2_invokevirtual_stub-Thumb2_stubs) +#define INVOKESTATIC_STUB (Thumb2_invokestatic_stub-Thumb2_stubs) +#define INVOKESPECIAL_STUB (Thumb2_invokespecial_stub-Thumb2_stubs) +#define GETFIELD_WORD_STUB (Thumb2_getfield_word_stub-Thumb2_stubs) +#define GETFIELD_SH_STUB (Thumb2_getfield_sh_stub-Thumb2_stubs) +#define GETFIELD_H_STUB (Thumb2_getfield_h_stub-Thumb2_stubs) +#define GETFIELD_SB_STUB (Thumb2_getfield_sb_stub-Thumb2_stubs) +#define GETFIELD_DW_STUB (Thumb2_getfield_dw_stub-Thumb2_stubs) +#define PUTFIELD_WORD_STUB (Thumb2_putfield_word_stub-Thumb2_stubs) +#define PUTFIELD_H_STUB (Thumb2_putfield_h_stub-Thumb2_stubs) +#define PUTFIELD_B_STUB (Thumb2_putfield_b_stub-Thumb2_stubs) +#define PUTFIELD_A_STUB (Thumb2_putfield_a_stub-Thumb2_stubs) +#define PUTFIELD_DW_STUB (Thumb2_putfield_dw_stub-Thumb2_stubs) +#define GETSTATIC_WORD_STUB (Thumb2_getstatic_word_stub-Thumb2_stubs) +#define GETSTATIC_SH_STUB (Thumb2_getstatic_sh_stub-Thumb2_stubs) +#define GETSTATIC_H_STUB (Thumb2_getstatic_h_stub-Thumb2_stubs) +#define GETSTATIC_SB_STUB (Thumb2_getstatic_sb_stub-Thumb2_stubs) +#define GETSTATIC_DW_STUB (Thumb2_getstatic_dw_stub-Thumb2_stubs) +#define PUTSTATIC_WORD_STUB (Thumb2_putstatic_word_stub-Thumb2_stubs) +#define PUTSTATIC_H_STUB (Thumb2_putstatic_h_stub-Thumb2_stubs) +#define PUTSTATIC_B_STUB (Thumb2_putstatic_b_stub-Thumb2_stubs) +#define PUTSTATIC_A_STUB (Thumb2_putstatic_a_stub-Thumb2_stubs) +#define PUTSTATIC_DW_STUB (Thumb2_putstatic_dw_stub-Thumb2_stubs) + +extern "C" void Thumb2_NullPtr_Handler(void); + + +extern "C" int Thumb2_Check_Null(unsigned *regs, unsigned pc) +{ + Thumb2_CodeBuf *cb = thumb2_codebuf; + if (!(CPUInfo & ARCH_THUMBEE)) return 0; + if (IS_COMPILED(pc, cb)) { + regs[ARM_PC] = (unsigned)Thumb2_NullPtr_Handler; + regs[ARM_CPSR] &= ~CPSR_THUMB_BIT; + return 1; + } + return 0; +} + +extern "C" void Thumb2_Initialize(void) +{ + CodeBuf codebuf; + Thumb2_CodeBuf *cb; + u32 h_divzero; + u32 loc_irem, loc_idiv, loc_ldiv; + +#ifdef T2EE_PRINT_COMPILATION + t2ee_print_compilation = getenv("T2EE_PRINT_COMPILATION"); +#endif +#ifdef T2EE_PRINT_STATISTICS + t2ee_print_statistics = getenv("T2EE_PRINT_STATISTICS"); +#endif +#ifdef T2EE_PRINT_DISASS + t2ee_print_disass = getenv("T2EE_PRINT_DISASS"); +#endif +#ifdef T2EE_PRINT_REGUSAGE + t2ee_print_regusage = getenv("T2EE_PRINT_REGUSAGE"); +#endif + + cb = (Thumb2_CodeBuf *)mmap(0, THUMB2_CODEBUF_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + if (cb == MAP_FAILED) { + UseCompiler = 0; + return; + } + + cb->size = THUMB2_CODEBUF_SIZE; + cb->hp = (char *)cb + sizeof(Thumb2_CodeBuf); + cb->sp = (char *)cb + THUMB2_CODEBUF_SIZE; + + codebuf.codebuf = (unsigned short *)cb->hp; + codebuf.idx = 0; + +#if 1 + memcpy(cb->hp, Thumb2_stubs, STUBS_SIZE); + + handlers[H_IDIV] = (unsigned)(cb->hp + IDIV_STUB); + handlers[H_IREM] = (unsigned)(cb->hp + IREM_STUB); + handlers[H_INVOKEINTERFACE] = (unsigned)(cb->hp + INVOKEINTERFACE_STUB); + handlers[H_INVOKEVIRTUAL] = (unsigned)(cb->hp + INVOKEVIRTUAL_STUB); + handlers[H_INVOKESTATIC] = (unsigned)(cb->hp + INVOKESTATIC_STUB); + handlers[H_INVOKESPECIAL] = (unsigned)(cb->hp + INVOKESPECIAL_STUB); + + handlers[H_GETFIELD_WORD] = (unsigned)(cb->hp + GETFIELD_WORD_STUB); + handlers[H_GETFIELD_SH] = (unsigned)(cb->hp + GETFIELD_SH_STUB); + handlers[H_GETFIELD_H] = (unsigned)(cb->hp + GETFIELD_H_STUB); + handlers[H_GETFIELD_SB] = (unsigned)(cb->hp + GETFIELD_SB_STUB); + handlers[H_GETFIELD_DW] = (unsigned)(cb->hp + GETFIELD_DW_STUB); + + handlers[H_PUTFIELD_WORD] = (unsigned)(cb->hp + PUTFIELD_WORD_STUB); + handlers[H_PUTFIELD_H] = (unsigned)(cb->hp + PUTFIELD_H_STUB); + handlers[H_PUTFIELD_B] = (unsigned)(cb->hp + PUTFIELD_B_STUB); + handlers[H_PUTFIELD_A] = (unsigned)(cb->hp + PUTFIELD_A_STUB); + handlers[H_PUTFIELD_DW] = (unsigned)(cb->hp + PUTFIELD_DW_STUB); + + handlers[H_GETSTATIC_WORD] = (unsigned)(cb->hp + GETSTATIC_WORD_STUB); + handlers[H_GETSTATIC_SH] = (unsigned)(cb->hp + GETSTATIC_SH_STUB); + handlers[H_GETSTATIC_H] = (unsigned)(cb->hp + GETSTATIC_H_STUB); + handlers[H_GETSTATIC_SB] = (unsigned)(cb->hp + GETSTATIC_SB_STUB); + handlers[H_GETSTATIC_DW] = (unsigned)(cb->hp + GETSTATIC_DW_STUB); + + handlers[H_PUTSTATIC_WORD] = (unsigned)(cb->hp + PUTSTATIC_WORD_STUB); + handlers[H_PUTSTATIC_H] = (unsigned)(cb->hp + PUTSTATIC_H_STUB); + handlers[H_PUTSTATIC_B] = (unsigned)(cb->hp + PUTSTATIC_B_STUB); + handlers[H_PUTSTATIC_A] = (unsigned)(cb->hp + PUTSTATIC_A_STUB); + handlers[H_PUTSTATIC_DW] = (unsigned)(cb->hp + PUTSTATIC_DW_STUB); + + codebuf.idx += (Thumb2_stubs_end-Thumb2_stubs) >> 1; +#endif + + handlers[H_LDIV] = handlers[H_LREM] = out_pos(&codebuf); + dop_reg(&codebuf, DP_ORR, ARM_IP, ARM_R2, ARM_R3, 0, 0); + loc_ldiv = forward_16(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_ldivmod); + mov_reg(&codebuf, ARM_PC, ARM_IP); + bcc_patch(&codebuf, COND_EQ, loc_ldiv); + mov_imm(&codebuf, ARM_IP, (u32)Thumb2_DivZero_Handler); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_ARRAYBOUND] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_R3, (u32)Thumb2_ArrayBounds_Handler); + mov_reg(&codebuf, ARM_PC, ARM_R3); + + handlers[H_HANDLE_EXCEPTION] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_R3, (u32)Thumb2_Handle_Exception); + mov_reg(&codebuf, ARM_PC, ARM_R3); + + handlers[H_DREM] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)fmod); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_FREM] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_R3, (u32)fmodf); + mov_reg(&codebuf, ARM_PC, ARM_R3); + + handlers[H_I2F] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_i2f); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_I2D] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_i2d); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_L2F] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_l2f); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_L2D] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_l2d); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_F2I] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)_ZN13SharedRuntime3f2iEf); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_F2L] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)_ZN13SharedRuntime3f2lEf); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_F2D] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_f2d); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_D2I] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)_ZN13SharedRuntime3d2iEd); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_D2L] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)_ZN13SharedRuntime3d2lEd); + mov_reg(&codebuf, ARM_PC, ARM_IP); + + handlers[H_D2F] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_IP, (u32)__aeabi_d2f); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// NEW Stub +// r1 = index +// r3 = bci +// result -> R0, == 0 => exception + handlers[H_NEW] = out_pos(&codebuf); + mov_reg(&codebuf, ARM_R0, Ristate); + ldr_imm(&codebuf, ARM_R2, ARM_R0, ISTATE_METHOD, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)Helper_new); + ldr_imm(&codebuf, ARM_R2, ARM_R2, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_R2, ARM_R2, ARM_R3); +sub_imm(&codebuf, ARM_R3, Rstack, 4); + str_imm(&codebuf, ARM_R3, ARM_R0, ISTATE_STACK, 1, 0); + str_imm(&codebuf, ARM_R2, ARM_R0, ISTATE_BCP, 1, 0); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// NEWARRAY Stub +// r1 = atype +// r2 = tos +// r3 = bci +// result -> thread->vm_result + handlers[H_NEWARRAY] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_R0, Ristate, ISTATE_METHOD, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)_ZN18InterpreterRuntime8newarrayEP10JavaThread9BasicTypei); + ldr_imm(&codebuf, ARM_R0, ARM_R0, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_R3, ARM_R0, ARM_R3); + mov_reg(&codebuf, ARM_R0, Rthread); + str_imm(&codebuf, ARM_R3, Ristate, ISTATE_BCP, 1, 0); +sub_imm(&codebuf, ARM_R3, Rstack, 4); + str_imm(&codebuf, ARM_R3, Ristate, ISTATE_STACK, 1, 0); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// ANEWARRAY Stub +// r0 = bci +// r2 = index +// r3 = tos +// result -> thread->vm_result + handlers[H_ANEWARRAY] = out_pos(&codebuf); +sub_imm(&codebuf, ARM_R1, Rstack, 4); + str_imm(&codebuf, ARM_R1, Ristate, ISTATE_STACK, 1, 0); + ldr_imm(&codebuf, ARM_R1, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(&codebuf, ARM_IP, ARM_R1, METHOD_CONSTMETHOD, 1, 0); + ldr_imm(&codebuf, ARM_R1, ARM_R1, METHOD_CONSTANTS, 1, 0); + add_reg(&codebuf, ARM_R0, ARM_IP, ARM_R0); + mov_imm(&codebuf, ARM_IP, (u32)_ZN18InterpreterRuntime9anewarrayEP10JavaThreadP19constantPoolOopDescii); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_BCP, 1, 0); + mov_reg(&codebuf, ARM_R0, Rthread); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// MULTIANEWARRAY Stub +// r0 = bci +// r1 = dimensions (*4) + handlers[H_MULTIANEWARRAY] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_R2, Ristate, ISTATE_METHOD, 1, 0); + sub_imm(&codebuf, ARM_R3, Rstack, 4); + ldr_imm(&codebuf, ARM_R2, ARM_R2, METHOD_CONSTMETHOD, 1, 0); + str_imm(&codebuf, ARM_R3, Ristate, ISTATE_STACK, 1, 0); + add_reg(&codebuf, ARM_R0, ARM_R2, ARM_R0); + add_reg(&codebuf, Rstack, Rstack, ARM_R1); + mov_imm(&codebuf, ARM_R3, (u32)_ZN18InterpreterRuntime14multianewarrayEP10JavaThreadPi); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_BCP, 1, 0); + mov_reg(&codebuf, ARM_R0, Rthread); + sub_imm(&codebuf, ARM_R1, Rstack, 4); + mov_reg(&codebuf, ARM_PC, ARM_R3); + +// LDC Stub +// r0 = bci + handlers[H_LDC] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_R2, Ristate, ISTATE_METHOD, 1, 0); + sub_imm(&codebuf, ARM_R3, Rstack, 4); + ldr_imm(&codebuf, ARM_R2, ARM_R2, METHOD_CONSTMETHOD, 1, 0); + str_imm(&codebuf, ARM_R3, Ristate, ISTATE_STACK, 1, 0); + add_reg(&codebuf, ARM_R0, ARM_R2, ARM_R0); + mov_imm(&codebuf, ARM_R3, (u32)_ZN18InterpreterRuntime3ldcEP10JavaThreadb); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_BCP, 1, 0); + mov_reg(&codebuf, ARM_R0, Rthread); +// mov_imm(&codebuf, ARM_R1, 0); + mov_reg(&codebuf, ARM_PC, ARM_R3); + +// INSTANCEOF Stub +// r1 = index +// r3 = bci +// result -> R0, == -1 => exception + handlers[H_INSTANCEOF] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_R0, Ristate, ISTATE_METHOD, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)Helper_instanceof); + ldr_imm(&codebuf, ARM_R0, ARM_R0, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_R0, ARM_R0, ARM_R3); +sub_imm(&codebuf, ARM_R3, Rstack, 4); + str_imm(&codebuf, ARM_R3, Ristate, ISTATE_STACK, 1, 0); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_BCP, 1, 0); + mov_reg(&codebuf, ARM_R0, Ristate); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// CHECKCAST Stub +// r1 = index +// r3 = bci +// result -> R0, != 0 => exception + handlers[H_CHECKCAST] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_R0, Ristate, ISTATE_METHOD, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)Helper_checkcast); + ldr_imm(&codebuf, ARM_R0, ARM_R0, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_R0, ARM_R0, ARM_R3); +sub_imm(&codebuf, ARM_R3, Rstack, 4); + str_imm(&codebuf, ARM_R3, Ristate, ISTATE_STACK, 1, 0); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_BCP, 1, 0); + mov_reg(&codebuf, ARM_R0, Ristate); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// AASTORE Stub +// r0 = bci +// r1 = value +// r2 = index +// r3 = arrayref + handlers[H_AASTORE] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_IP, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(&codebuf, ARM_IP, ARM_IP, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_IP, ARM_IP, ARM_R0); +sub_imm(&codebuf, ARM_R0, Rstack, 4); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_STACK, 1, 0); + str_imm(&codebuf, ARM_IP, Ristate, ISTATE_BCP, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)Helper_aastore); + mov_reg(&codebuf, ARM_R0, Ristate); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// APUTFIELD Stub +// r0 = obj + handlers[H_APUTFIELD] = out_pos(&codebuf); + mov_imm(&codebuf, ARM_R3, (u32)Helper_aputfield); + mov_reg(&codebuf, ARM_PC, ARM_R3); + +// SYNCHRONIZED_ENTER Stub +// r0 = bci +// r1 = monitor + handlers[H_SYNCHRONIZED_ENTER] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_IP, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(&codebuf, ARM_IP, ARM_IP, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_IP, ARM_IP, ARM_R0); +sub_imm(&codebuf, ARM_R0, Rstack, 4); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_STACK, 1, 0); + str_imm(&codebuf, ARM_IP, Ristate, ISTATE_BCP, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)Helper_synchronized_enter); + mov_reg(&codebuf, ARM_R0, Rthread); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +// +// SYNCHRONIZED_EXIT Stub +// r0 = bci +// r1 = monitor + handlers[H_SYNCHRONIZED_EXIT] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_IP, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(&codebuf, ARM_IP, ARM_IP, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, ARM_IP, ARM_IP, ARM_R0); +sub_imm(&codebuf, ARM_R0, Rstack, 4); + str_imm(&codebuf, ARM_R0, Ristate, ISTATE_STACK, 1, 0); + str_imm(&codebuf, ARM_IP, Ristate, ISTATE_BCP, 1, 0); + mov_imm(&codebuf, ARM_IP, (u32)Helper_synchronized_exit); + mov_reg(&codebuf, ARM_R0, Rthread); + mov_reg(&codebuf, ARM_PC, ARM_IP); + +#define DEBUG_REGSET ((1<<ARM_R0)|(1<<ARM_R1)|(1<<ARM_R2)|(1<<ARM_R3)|(1<<ARM_IP)) + +// DEBUG_METHODENTRY + handlers[H_DEBUG_METHODENTRY] = out_pos(&codebuf); + stm(&codebuf, DEBUG_REGSET | (1<<ARM_LR), ARM_SP, PUSH_FD, 1); + mov_reg(&codebuf, ARM_R2, ARM_R0); + mov_reg(&codebuf, ARM_R0, ARM_R8); + mov_reg(&codebuf, ARM_R1, ARM_R4); + mov_imm(&codebuf, ARM_IP, (u32)Debug_MethodEntry); + blx_reg(&codebuf, ARM_IP); + ldm(&codebuf, DEBUG_REGSET | (1<<ARM_PC), ARM_SP, POP_FD, 1); + +// DEBUG_METHODEXIT + handlers[H_DEBUG_METHODEXIT] = out_pos(&codebuf); + stm(&codebuf, DEBUG_REGSET | (1<<ARM_LR), ARM_SP, PUSH_FD, 1); + mov_reg(&codebuf, ARM_R0, ARM_R8); + mov_reg(&codebuf, ARM_R1, ARM_R4); + mov_imm(&codebuf, ARM_IP, (u32)Debug_MethodExit); + blx_reg(&codebuf, ARM_IP); + ldm(&codebuf, DEBUG_REGSET | (1<<ARM_PC), ARM_SP, POP_FD, 1); + +// DEBUG_METHODCALL + handlers[H_DEBUG_METHODCALL] = out_pos(&codebuf); + stm(&codebuf, DEBUG_REGSET | (1<<ARM_LR), ARM_SP, PUSH_FD, 1); + mov_reg(&codebuf, ARM_R2, ARM_R0); + mov_reg(&codebuf, ARM_R0, ARM_R8); + mov_reg(&codebuf, ARM_R1, ARM_R4); + mov_imm(&codebuf, ARM_IP, (u32)Debug_MethodCall); + blx_reg(&codebuf, ARM_IP); + ldm(&codebuf, DEBUG_REGSET | (1<<ARM_PC), ARM_SP, POP_FD, 1); + +// EXIT_TO_INTERPRETER +// r0 = bci + handlers[H_EXIT_TO_INTERPRETER] = out_pos(&codebuf); + ldr_imm(&codebuf, ARM_R1, Ristate, ISTATE_METHOD, 1, 0); + ldr_imm(&codebuf, ARM_IP, ARM_R1, METHOD_CONSTMETHOD, 1, 0); + add_reg(&codebuf, Rint_jpc, ARM_IP, ARM_R0); + mov_imm(&codebuf, ARM_R3, (u32)Thumb2_Exit_To_Interpreter); + mov_reg(&codebuf, ARM_PC, ARM_R3); + + Thumb2_Clear_Cache(cb->hp, cb->hp + codebuf.idx * 2); + cb->hp += codebuf.idx * 2; + + thumb2_codebuf = cb; +} + +#endif // THUMB2EE