changeset 7673:0d63f295c3c2

8139303: aarch32: add support for ARM aarch32 Summary: Initial port of template interpreter to aarch32 Reviewed-by: duke Contributed-by: nikolay@azulsystems.com
author enevill
date Wed, 30 Dec 2015 09:24:57 +0000
parents e9e252c83b2b
children ad6e224490d8
files make/Makefile make/defs.make make/linux/makefiles/aarch32.make make/linux/makefiles/buildtree.make make/linux/makefiles/defs.make make/linux/makefiles/gcc.make make/linux/makefiles/rules.make make/linux/makefiles/saproc.make make/linux/platform_aarch32 src/cpu/aarch32/vm/aarch32Test.cpp src/cpu/aarch32/vm/assembler_aarch32.cpp src/cpu/aarch32/vm/assembler_aarch32.hpp src/cpu/aarch32/vm/assembler_aarch32.inline.hpp src/cpu/aarch32/vm/bytecodeInterpreter_aarch32.cpp src/cpu/aarch32/vm/bytecodeInterpreter_aarch32.hpp src/cpu/aarch32/vm/bytecodeInterpreter_aarch32.inline.hpp src/cpu/aarch32/vm/bytecodes_aarch32.cpp src/cpu/aarch32/vm/bytecodes_aarch32.hpp src/cpu/aarch32/vm/bytes_aarch32.hpp src/cpu/aarch32/vm/codeBuffer_aarch32.hpp src/cpu/aarch32/vm/compiledIC_aarch32.cpp src/cpu/aarch32/vm/copy_aarch32.hpp src/cpu/aarch32/vm/cppInterpreterGenerator_aarch32.hpp src/cpu/aarch32/vm/cpustate_aarch32.hpp src/cpu/aarch32/vm/debug_aarch32.cpp src/cpu/aarch32/vm/decode_aarch32.hpp src/cpu/aarch32/vm/depChecker_aarch32.cpp src/cpu/aarch32/vm/depChecker_aarch32.hpp src/cpu/aarch32/vm/disassembler_aarch32.hpp src/cpu/aarch32/vm/frame_aarch32.cpp src/cpu/aarch32/vm/frame_aarch32.hpp src/cpu/aarch32/vm/frame_aarch32.inline.hpp src/cpu/aarch32/vm/globalDefinitions_aarch32.hpp src/cpu/aarch32/vm/globals_aarch32.hpp src/cpu/aarch32/vm/icBuffer_aarch32.cpp src/cpu/aarch32/vm/icache_aarch32.cpp src/cpu/aarch32/vm/icache_aarch32.hpp src/cpu/aarch32/vm/immediate_aarch32.cpp src/cpu/aarch32/vm/immediate_aarch32.hpp src/cpu/aarch32/vm/interp_masm_aarch32.cpp src/cpu/aarch32/vm/interp_masm_aarch32.hpp src/cpu/aarch32/vm/interpreterGenerator_aarch32.hpp src/cpu/aarch32/vm/interpreterRT_aarch32.cpp src/cpu/aarch32/vm/interpreterRT_aarch32.hpp src/cpu/aarch32/vm/interpreter_aarch32.cpp src/cpu/aarch32/vm/interpreter_aarch32.hpp src/cpu/aarch32/vm/javaFrameAnchor_aarch32.hpp src/cpu/aarch32/vm/jniFastGetField_aarch32.cpp src/cpu/aarch32/vm/jniTypes_aarch32.hpp src/cpu/aarch32/vm/jni_aarch32.h src/cpu/aarch32/vm/macroAssembler_aarch32.cpp src/cpu/aarch32/vm/macroAssembler_aarch32.hpp src/cpu/aarch32/vm/macroAssembler_aarch32.inline.hpp src/cpu/aarch32/vm/metaspaceShared_aarch32.cpp src/cpu/aarch32/vm/methodHandles_aarch32.cpp src/cpu/aarch32/vm/methodHandles_aarch32.hpp src/cpu/aarch32/vm/nativeInst_aarch32.cpp src/cpu/aarch32/vm/nativeInst_aarch32.hpp src/cpu/aarch32/vm/registerMap_aarch32.hpp src/cpu/aarch32/vm/register_aarch32.cpp src/cpu/aarch32/vm/register_aarch32.hpp src/cpu/aarch32/vm/register_definitions_aarch32.cpp src/cpu/aarch32/vm/relocInfo_aarch32.cpp src/cpu/aarch32/vm/relocInfo_aarch32.hpp src/cpu/aarch32/vm/runtime_aarch32.cpp src/cpu/aarch32/vm/sharedRuntime_aarch32.cpp src/cpu/aarch32/vm/stubGenerator_aarch32.cpp src/cpu/aarch32/vm/stubRoutines_aarch32.cpp src/cpu/aarch32/vm/stubRoutines_aarch32.hpp src/cpu/aarch32/vm/templateInterpreterGenerator_aarch32.hpp src/cpu/aarch32/vm/templateInterpreter_aarch32.cpp src/cpu/aarch32/vm/templateInterpreter_aarch32.hpp src/cpu/aarch32/vm/templateTable_aarch32.cpp src/cpu/aarch32/vm/templateTable_aarch32.hpp src/cpu/aarch32/vm/vmStructs_aarch32.hpp src/cpu/aarch32/vm/vm_version_aarch32.cpp src/cpu/aarch32/vm/vm_version_aarch32.hpp src/cpu/aarch32/vm/vmreg_aarch32.cpp src/cpu/aarch32/vm/vmreg_aarch32.hpp src/cpu/aarch32/vm/vmreg_aarch32.inline.hpp src/cpu/aarch32/vm/vtableStubs_aarch32.cpp src/cpu/zero/vm/entry_zero.hpp src/cpu/zero/vm/nativeInst_zero.cpp src/os/linux/vm/os_linux.hpp src/os_cpu/linux_aarch32/vm/assembler_linux_aarch32.cpp src/os_cpu/linux_aarch32/vm/atomic_linux_aarch32.inline.hpp src/os_cpu/linux_aarch32/vm/bytes_linux_aarch32.inline.hpp src/os_cpu/linux_aarch32/vm/copy_linux_aarch32.inline.hpp src/os_cpu/linux_aarch32/vm/globals_linux_aarch32.hpp src/os_cpu/linux_aarch32/vm/linux_aarch32.S src/os_cpu/linux_aarch32/vm/linux_aarch32.ad src/os_cpu/linux_aarch32/vm/orderAccess_linux_aarch32.inline.hpp src/os_cpu/linux_aarch32/vm/os_linux_aarch32.cpp src/os_cpu/linux_aarch32/vm/os_linux_aarch32.hpp src/os_cpu/linux_aarch32/vm/os_linux_aarch32.inline.hpp src/os_cpu/linux_aarch32/vm/prefetch_linux_aarch32.inline.hpp src/os_cpu/linux_aarch32/vm/threadLS_linux_aarch32.cpp src/os_cpu/linux_aarch32/vm/threadLS_linux_aarch32.hpp src/os_cpu/linux_aarch32/vm/thread_linux_aarch32.cpp src/os_cpu/linux_aarch32/vm/thread_linux_aarch32.hpp src/os_cpu/linux_aarch32/vm/vmStructs_linux_aarch32.hpp src/os_cpu/linux_aarch32/vm/vm_version_linux_aarch32.cpp src/share/vm/adlc/main.cpp src/share/vm/asm/assembler.hpp src/share/vm/asm/assembler.inline.hpp src/share/vm/asm/codeBuffer.hpp src/share/vm/asm/macroAssembler.hpp src/share/vm/asm/macroAssembler.inline.hpp src/share/vm/asm/register.hpp src/share/vm/c1/c1_Defs.hpp src/share/vm/c1/c1_FpuStackSim.hpp src/share/vm/c1/c1_FrameMap.cpp src/share/vm/c1/c1_FrameMap.hpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/c1/c1_LIRAssembler.hpp src/share/vm/c1/c1_LinearScan.cpp src/share/vm/c1/c1_LinearScan.hpp src/share/vm/c1/c1_MacroAssembler.hpp src/share/vm/c1/c1_globals.hpp src/share/vm/classfile/bytecodeAssembler.cpp src/share/vm/classfile/classFileStream.hpp src/share/vm/classfile/stackMapTable.hpp src/share/vm/classfile/verifier.cpp src/share/vm/code/codeBlob.cpp src/share/vm/code/compiledIC.hpp src/share/vm/code/relocInfo.hpp src/share/vm/code/vmreg.hpp src/share/vm/compiler/disassembler.cpp src/share/vm/compiler/disassembler.hpp src/share/vm/interpreter/abstractInterpreter.hpp src/share/vm/interpreter/bytecode.hpp src/share/vm/interpreter/bytecodeInterpreter.hpp src/share/vm/interpreter/bytecodeInterpreter.inline.hpp src/share/vm/interpreter/bytecodeStream.hpp src/share/vm/interpreter/bytecodes.cpp src/share/vm/interpreter/bytecodes.hpp src/share/vm/interpreter/cppInterpreter.hpp src/share/vm/interpreter/cppInterpreterGenerator.hpp src/share/vm/interpreter/interpreter.hpp src/share/vm/interpreter/interpreterGenerator.hpp src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/interpreter/interpreterRuntime.hpp src/share/vm/interpreter/templateInterpreter.hpp src/share/vm/interpreter/templateInterpreterGenerator.hpp src/share/vm/interpreter/templateTable.hpp src/share/vm/oops/constantPool.hpp src/share/vm/oops/oop.inline.hpp src/share/vm/opto/buildOopMap.cpp src/share/vm/opto/c2_globals.hpp src/share/vm/opto/c2compiler.cpp src/share/vm/opto/compile.cpp src/share/vm/opto/gcm.cpp src/share/vm/opto/lcm.cpp src/share/vm/opto/locknode.hpp src/share/vm/opto/matcher.cpp src/share/vm/opto/output.hpp src/share/vm/opto/regmask.cpp src/share/vm/opto/regmask.hpp src/share/vm/opto/runtime.cpp src/share/vm/prims/jniCheck.cpp src/share/vm/prims/jni_md.h src/share/vm/prims/jvmtiClassFileReconstituter.cpp src/share/vm/prims/methodHandles.hpp src/share/vm/runtime/atomic.inline.hpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/dtraceJSDT.hpp src/share/vm/runtime/frame.cpp src/share/vm/runtime/frame.hpp src/share/vm/runtime/frame.inline.hpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/icache.hpp src/share/vm/runtime/java.cpp src/share/vm/runtime/javaCalls.hpp src/share/vm/runtime/javaFrameAnchor.hpp src/share/vm/runtime/orderAccess.inline.hpp src/share/vm/runtime/os.hpp src/share/vm/runtime/prefetch.inline.hpp src/share/vm/runtime/registerMap.hpp src/share/vm/runtime/relocator.hpp src/share/vm/runtime/safepoint.cpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/stackValueCollection.cpp src/share/vm/runtime/statSampler.cpp src/share/vm/runtime/stubRoutines.hpp src/share/vm/runtime/thread.hpp src/share/vm/runtime/threadLocalStorage.hpp src/share/vm/runtime/vmStructs.cpp src/share/vm/runtime/vm_version.cpp src/share/vm/utilities/copy.hpp src/share/vm/utilities/globalDefinitions.hpp
diffstat 190 files changed, 31245 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/make/Makefile	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/Makefile	Wed Dec 30 09:24:57 2015 +0000
@@ -243,8 +243,8 @@
 endif
 
 generic_buildcore: $(HOTSPOT_SCRIPT)
-ifeq ($(HS_ARCH),ppc)
-  ifeq ($(ARCH_DATA_MODEL),64)
+ifeq ($(HS_ARCH), ppc)
+  ifeq ($(ARCH_DATA_MODEL), 64)
 	$(MKDIR) -p $(OUTPUTDIR)
 	$(CD) $(OUTPUTDIR); \
 		$(MAKE) -f $(ABS_OS_MAKEFILE) \
@@ -253,7 +253,18 @@
 	@$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
   endif
 else
+  ifeq ($(HS_ARCH), aarch32)
+    ifeq ($(ARCH_DATA_MODEL), 32)
+	$(MKDIR) -p $(OUTPUTDIR)
+	$(CD) $(OUTPUTDIR); \
+		$(MAKE) -f $(ABS_OS_MAKEFILE) \
+			$(MAKE_ARGS) $(VM_TARGET)
+    else
+	@$(ECHO) "No ($(VM_TARGET)) for arm ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)"
+    endif
+  else
 	@$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)"
+  endif
 endif
 
 generic_buildzero: $(HOTSPOT_SCRIPT)
--- a/make/defs.make	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/defs.make	Wed Dec 30 09:24:57 2015 +0000
@@ -285,15 +285,16 @@
 
   # Use uname output for SRCARCH, but deal with platform differences. If ARCH
   # is not explicitly listed below, it is treated as x86.
-  SRCARCH    ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc64 zero,$(ARCH)))
-  ARCH/       = x86
-  ARCH/sparc  = sparc
-  ARCH/sparc64= sparc
-  ARCH/ia64   = ia64
-  ARCH/amd64  = x86
-  ARCH/x86_64 = x86
-  ARCH/ppc64  = ppc
-  ARCH/zero   = zero
+  SRCARCH     ?= $(ARCH/$(filter x86_64 amd64 ia64 sparc sparc64 zero ppc64 aarch32, $(ARCH)))
+  ARCH/        = x86
+  ARCH/x86_64  = x86
+  ARCH/amd64   = x86
+  ARCH/ia64    = ia64
+  ARCH/sparc   = sparc
+  ARCH/sparc64 = sparc
+  ARCH/zero    = zero
+  ARCH/ppc64   = ppc
+  ARCH/aarch32 = aarch32
 
   # BUILDARCH is usually the same as SRCARCH, except for sparcv9
   BUILDARCH ?= $(SRCARCH)
@@ -315,15 +316,16 @@
     endif
   endif
 
-  # LIBARCH is 1:1 mapping from BUILDARCH
+  # LIBARCH is 1:1 mapping from BUILDARCH.
   LIBARCH        ?= $(LIBARCH/$(BUILDARCH))
   LIBARCH/i486    = i386
   LIBARCH/amd64   = amd64
+  LIBARCH/ia64    = ia64
   LIBARCH/sparc   = sparc
   LIBARCH/sparcv9 = sparcv9
-  LIBARCH/ia64    = ia64
+  LIBARCH/zero    = $(ZERO_LIBARCH)
   LIBARCH/ppc64   = ppc64
-  LIBARCH/zero    = $(ZERO_LIBARCH)
+  LIBARCH/aarch32 = aarch32
 
   LP64_ARCH += sparcv9 amd64 ia64 ppc64 zero
 endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/linux/makefiles/aarch32.make	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,32 @@
+
+# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
+OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# Must also specify if CPU is little endian
+CFLAGS += -DVM_LITTLE_ENDIAN
+
+
--- a/make/linux/makefiles/buildtree.make	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/linux/makefiles/buildtree.make	Wed Dec 30 09:24:57 2015 +0000
@@ -192,10 +192,11 @@
 LP64_SETTING/64 = LP64 = 1
 
 DATA_MODE/i486 = 32
+DATA_MODE/amd64 = 64
 DATA_MODE/sparc = 32
 DATA_MODE/sparcv9 = 64
-DATA_MODE/amd64 = 64
 DATA_MODE/ppc64 = 64
+DATA_MODE/aarch32 = 32
 
 DATA_MODE = $(DATA_MODE/$(BUILDARCH))
 
--- a/make/linux/makefiles/defs.make	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/linux/makefiles/defs.make	Wed Dec 30 09:24:57 2015 +0000
@@ -118,6 +118,14 @@
   HS_ARCH          = ppc
 endif
 
+# AArch32
+ifeq ($(ARCH), aarch32)
+  ARCH_DATA_MODEL  = 32
+  PLATFORM         = linux-aarch32
+  VM_PLATFORM      = linux_aarch32
+  HS_ARCH          = aarch32
+endif
+
 # On 32 bit linux we build server and client, on 64 bit just server.
 ifeq ($(JVM_VARIANTS),)
   ifeq ($(ARCH_DATA_MODEL), 32)
--- a/make/linux/makefiles/gcc.make	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/linux/makefiles/gcc.make	Wed Dec 30 09:24:57 2015 +0000
@@ -177,7 +177,8 @@
 ARCHFLAG/sparc   = -m32 -mcpu=v9
 ARCHFLAG/sparcv9 = -m64 -mcpu=v9
 ARCHFLAG/zero    = $(ZERO_ARCHFLAG)
-ARCHFLAG/ppc64   =  -m64
+ARCHFLAG/ppc64   = -m64
+ARCHFLAG/aarch32 =
 
 CFLAGS     += $(ARCHFLAG)
 AOUT_FLAGS += $(ARCHFLAG)
@@ -338,6 +339,7 @@
   DEBUG_CFLAGS/ia64  = -g
   DEBUG_CFLAGS/amd64 = -g
   DEBUG_CFLAGS/ppc64 = -g
+  DEBUG_CFLAGS/aarch32 = -g
   DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
   ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
       ifeq ($(USE_CLANG), true)
@@ -352,6 +354,7 @@
     FASTDEBUG_CFLAGS/ia64  = -g
     FASTDEBUG_CFLAGS/amd64 = -g
     FASTDEBUG_CFLAGS/ppc64 = -g
+    FASTDEBUG_CFLAGS/aarch32 = -g
     FASTDEBUG_CFLAGS += $(FASTDEBUG_CFLAGS/$(BUILDARCH))
     ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),)
       ifeq ($(USE_CLANG), true)
@@ -365,6 +368,7 @@
     OPT_CFLAGS/ia64  = -g
     OPT_CFLAGS/amd64 = -g
     OPT_CFLAGS/ppc64 = -g
+    OPT_CFLAGS/aarch32 = -g
     OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH))
     ifeq ($(OPT_CFLAGS/$(BUILDARCH)),)
       ifeq ($(USE_CLANG), true)
--- a/make/linux/makefiles/rules.make	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/linux/makefiles/rules.make	Wed Dec 30 09:24:57 2015 +0000
@@ -136,6 +136,10 @@
 COMPILE_DONE    = && { echo Done with $<; }
 endif
 
+ifeq ($(BUILDARCH), aarch32)
+GENPIC = yes
+endif
+
 # Include $(NONPIC_OBJ_FILES) definition
 ifndef LP64
 include $(GAMMADIR)/make/pic.make
--- a/make/linux/makefiles/saproc.make	Tue Nov 17 08:59:21 2015 +0100
+++ b/make/linux/makefiles/saproc.make	Wed Dec 30 09:24:57 2015 +0000
@@ -63,7 +63,7 @@
 # also, we don't build SA on Itanium or zero.
 
 ifneq ($(wildcard $(AGENT_DIR)),)
-ifneq ($(filter-out ia64 zero,$(SRCARCH)),)
+ifneq ($(filter-out aarch32 ia64 zero,$(SRCARCH)),)
   BUILDLIBSAPROC = $(LIBSAPROC)
 endif
 endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/linux/platform_aarch32	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,20 @@
+os_family = linux
+
+arch = aarch32
+
+arch_model = aarch32
+
+os_arch = linux_aarch32
+
+os_arch_model = linux_aarch32
+
+lib_arch = arm
+
+compiler = gcc
+
+sysdefs = -DLINUX -D_GNU_SOURCE -DAARCH32 -DARM
+
+# NOTE!! The existing codebase contians some code which uses ARM32, I'm not sure about this and have left this off
+# ARM has been defined as this is also used in the shared code (but much more widely).
+# The zero interpreter also depends on ARM having been defined to include the relevant code.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/aarch32Test.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "precompiled.hpp"
+#include "code/codeBlob.hpp"
+#include "asm/macroAssembler.hpp"
+
+// hook routine called during JVM bootstrap to test AArch64 assembler
+
+extern "C" void entry(CodeBuffer*);
+
+void aarch32TestHook()
+{
+  BufferBlob* b = BufferBlob::create("aarch32Test", 500000);
+  CodeBuffer code(b);
+  MacroAssembler _masm(&code);
+  entry(&code);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/assembler_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,1806 @@
+/*
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * reserved.  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE
+ * HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "interpreter/interpreter.hpp"
+
+#ifndef PRODUCT
+// FIXME This has been changed to make it compile for arm 32
+//const unsigned long Assembler::asm_bp = 0x00007fffee09ac88;
+const unsigned long Assembler::asm_bp = 0x0;
+//FIXME END
+#endif
+
+#include "compiler/disassembler.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/sharedRuntime.hpp"
+
+// for the moment we reuse the logical/floating point immediate encode
+// and decode functiosn provided by the simulator. when we move to
+// real hardware we will need to pull taht code into here
+
+#include "immediate_aarch32.hpp"
+
+extern "C" void entry(CodeBuffer *cb);
+
+#define __ _masm.
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) block_comment(str)
+#endif
+
+#define BIND(label) bind(label); __ BLOCK_COMMENT(#label ":")
+
+void entry(CodeBuffer *cb) {
+
+  // {
+  //   for (int i = 0; i < 256; i+=16)
+  //     {
+  //    printf("\"%20.20g\", ", unpack(i));
+  //    printf("\"%20.20g\", ", unpack(i+1));
+  //     }
+  //   printf("\n");
+  // }
+
+  Assembler _masm(cb);
+  address entry = __ pc();
+
+  // Smoke test for assembler
+
+#ifdef ASSERT
+// BEGIN  Generated code -- do not edit
+// Generated by aarch32-asmtest.py
+    Label back, forth, near, near_post, near_flt, near_post_flt;
+    __ bind(back);
+
+// ThreeRegSft
+    __ add(r8, r2, r11, ::lsr(10));                    //       add r8, r2, r11, lsr #10
+    __ adds(r1, r3, r7, ::asr(1), Assembler::EQ);      //       addEQs r1, r3, r7, asr #1
+    __ eor(r0, r9, r4, ::lsl(5));                      //       eor r0, r9, r4, lsl #5
+    __ eors(r9, r2, r6, ::rrx(), Assembler::GT);       //       eorGTs r9, r2, r6, rrx
+    __ sub(r0, r12, lr, ::lsr(0), Assembler::GT);      //       subGT r0, r12, lr, lsr #0
+    __ subs(r8, r2, r4, ::ror(6), Assembler::EQ);      //       subEQs r8, r2, r4, ror #6
+    __ rsb(r8, r9, sp, ::lsl(3));                      //       rsb r8, r9, sp, lsl #3
+    __ rsbs(r8, r0, r4, ::ror(16), Assembler::VS);     //       rsbVSs r8, r0, r4, ror #16
+    __ add(r9, r5, r1, ::lsr(15), Assembler::LE);      //       addLE r9, r5, r1, lsr #15
+    __ adds(r1, sp, r6, ::asr(5));                     //       adds r1, sp, r6, asr #5
+    __ adc(r11, sp, r7, ::asr(1), Assembler::GT);      //       adcGT r11, sp, r7, asr #1
+    __ adcs(r0, r8, r9, ::lsr(6));                     //       adcs r0, r8, r9, lsr #6
+    __ sbc(r9, r3, r6, ::ror(5));                      //       sbc r9, r3, r6, ror #5
+    __ sbcs(r1, sp, r5, ::asr(16), Assembler::HI);     //       sbcHIs r1, sp, r5, asr #16
+    __ rsc(r8, r2, r6, ::lsl(9), Assembler::CC);       //       rscCC r8, r2, r6, lsl #9
+    __ rscs(r10, r4, sp, ::ror(14));                   //       rscs r10, r4, sp, ror #14
+    __ orr(r11, sp, r5, ::lsl(15), Assembler::NE);     //       orrNE r11, sp, r5, lsl #15
+    __ orrs(r9, r10, r4, ::ror(14));                   //       orrs r9, r10, r4, ror #14
+    __ bic(r9, sp, r5, ::ror(1));                      //       bic r9, sp, r5, ror #1
+    __ bics(r0, r2, r7, ::asr(10));                    //       bics r0, r2, r7, asr #10
+
+// ThreeRegRSR
+    __ add(sp, r6, r7, ::ror(r7));                     //       add sp, r6, r7, ror r7
+    __ adds(r4, r12, r6, ::ror(r7), Assembler::HI);    //       addHIs r4, r12, r6, ror r7
+    __ eor(r5, r6, r7, ::asr(r12), Assembler::LS);     //       eorLS r5, r6, r7, asr r12
+    __ eors(r8, r5, sp, ::lsl(r4), Assembler::AL);     //       eorALs r8, r5, sp, lsl r4
+    __ sub(r2, r12, r5, ::asr(r0));                    //       sub r2, r12, r5, asr r0
+    __ subs(r9, r3, r7, ::lsl(r12), Assembler::HS);    //       subHSs r9, r3, r7, lsl r12
+    __ rsb(r9, r12, r4, ::lsl(r6), Assembler::GT);     //       rsbGT r9, r12, r4, lsl r6
+    __ rsbs(r8, r2, r12, ::lsl(r1));                   //       rsbs r8, r2, r12, lsl r1
+    __ add(r4, r12, sp, ::lsl(sp));                    //       add r4, r12, sp, lsl sp
+    __ adds(r8, r11, r6, ::ror(sp));                   //       adds r8, r11, r6, ror sp
+    __ adc(r0, r2, r5, ::lsl(r4), Assembler::NE);      //       adcNE r0, r2, r5, lsl r4
+    __ adcs(r11, lr, r6, ::asr(r2));                   //       adcs r11, lr, r6, asr r2
+    __ sbc(r8, r10, lr, ::asr(r3), Assembler::HI);     //       sbcHI r8, r10, lr, asr r3
+    __ sbcs(r1, r12, r5, ::lsl(r6));                   //       sbcs r1, r12, r5, lsl r6
+    __ rsc(r4, r5, lr, ::ror(r10), Assembler::VS);     //       rscVS r4, r5, lr, ror r10
+    __ rscs(r1, r12, sp, ::lsl(r8));                   //       rscs r1, r12, sp, lsl r8
+    __ orr(r8, r1, r6, ::ror(r0), Assembler::VS);      //       orrVS r8, r1, r6, ror r0
+    __ orrs(r11, sp, r7, ::ror(r5));                   //       orrs r11, sp, r7, ror r5
+    __ bic(r4, lr, r6, ::lsl(r2), Assembler::AL);      //       bicAL r4, lr, r6, lsl r2
+    __ bics(r10, r11, sp, ::lsl(r3));                  //       bics r10, r11, sp, lsl r3
+
+// TwoRegImm
+    __ add(r8, sp, (unsigned)268435462U, Assembler::HI); //     addHI r8, sp, #268435462
+    __ adds(sp, lr, (unsigned)162529280U);             //       adds sp, lr, #162529280
+    __ eor(lr, r6, (unsigned)8192000U);                //       eor lr, r6, #8192000
+    __ eors(r2, r3, (unsigned)292U);                   //       eors r2, r3, #292
+    __ sub(r4, sp, (unsigned)227540992U);              //       sub r4, sp, #227540992
+    __ subs(r1, lr, (unsigned)33554432U, Assembler::LT); //     subLTs r1, lr, #33554432
+    __ rsb(r0, r5, (unsigned)2483027968U);             //       rsb r0, r5, #2483027968
+    __ rsbs(r8, r4, (unsigned)3080192U, Assembler::LO); //      rsbLOs r8, r4, #3080192
+    __ add(r9, r4, (unsigned)2147483648U, Assembler::LT); //    addLT r9, r4, #2147483648
+    __ adds(r8, r4, (unsigned)32768U, Assembler::AL);  //       addALs r8, r4, #32768
+    __ adc(r10, lr, (unsigned)10752U, Assembler::CS);  //       adcCS r10, lr, #10752
+    __ adcs(r10, r6, (unsigned)774144U);               //       adcs r10, r6, #774144
+    __ sbc(r2, r12, (unsigned)637534208U);             //       sbc r2, r12, #637534208
+    __ sbcs(r8, r10, (unsigned)692060160U);            //       sbcs r8, r10, #692060160
+    __ rsc(sp, r6, (unsigned)7405568U);                //       rsc sp, r6, #7405568
+    __ rscs(r10, r11, (unsigned)244318208U, Assembler::NE); //  rscNEs r10, r11, #244318208
+    __ orr(r3, r7, (unsigned)66846720U, Assembler::VS); //      orrVS r3, r7, #66846720
+    __ orrs(r2, r5, (unsigned)1327104U, Assembler::EQ); //      orrEQs r2, r5, #1327104
+    __ bic(r8, r1, (unsigned)3744U, Assembler::VS);    //       bicVS r8, r1, #3744
+    __ bics(r0, r2, (unsigned)2684354560U, Assembler::LO); //   bicLOs r0, r2, #2684354560
+
+// TwoRegSft
+    __ tst(r8, sp, ::lsl(5));                          //       tst r8, sp, lsl #5
+    __ teq(r6, r7, ::lsr(3));                          //       teq r6, r7, lsr #3
+    __ cmp(r12, r4, ::ror(2));                         //       cmp r12, r4, ror #2
+    __ cmn(r5, r7, ::lsl(16), Assembler::LT);          //       cmnLT r5, r7, lsl #16
+
+// TwoRegRSR
+    __ tst(r2, lr, ::lsr(r7));                         //       tst r2, lr, lsr r7
+    __ teq(r0, r2, ::ror(r5), Assembler::CC);          //       teqCC r0, r2, ror r5
+    __ cmp(lr, r7, ::lsr(r11), Assembler::LS);         //       cmpLS lr, r7, lsr r11
+    __ cmn(r10, r7, ::lsl(r11), Assembler::VS);        //       cmnVS r10, r7, lsl r11
+
+// OneRegImm
+    __ tst(r2, (unsigned)557842432U);                  //       tst r2, #557842432
+    __ teq(lr, (unsigned)7077888U, Assembler::MI);     //       teqMI lr, #7077888
+    __ cmp(r5, (unsigned)939524096U);                  //       cmp r5, #939524096
+    __ cmn(r7, (unsigned)2147483650U, Assembler::LO);  //       cmnLO r7, #2147483650
+
+// Shift op
+    __ lsl(r0, r4, (unsigned)23U);                     //       lsl r0, r4, #23
+    __ lsls(r1, r4, (unsigned)9U);                     //       lsls r1, r4, #9
+    __ lsr(r0, r10, (unsigned)3U);                     //       lsr r0, r10, #3
+    __ lsrs(r0, r10, (unsigned)20U);                   //       lsrs r0, r10, #20
+    __ asr(r1, r9, (unsigned)11U);                     //       asr r1, r9, #11
+    __ asrs(r2, r11, (unsigned)10U, Assembler::VS);    //       asrVSs r2, r11, #10
+
+// shift op
+    __ ror(r8, r2, (unsigned)31U, Assembler::CC);      //       rorCC r8, r2, #31
+    __ rors(r9, r12, (unsigned)8U);                    //       rors r9, r12, #8
+
+// ThreeRegNon
+    __ ror(r8, lr, r7);                                //       ror r8, lr, r7
+    __ rors(r12, r3, r4);                              //       rors r12, r3, r4
+    __ lsl(r12, sp, lr, Assembler::GT);                //       lslGT r12, sp, lr
+    __ lsls(r12, sp, r6, Assembler::AL);               //       lslALs r12, sp, r6
+    __ lsr(r0, r1, r9, Assembler::GT);                 //       lsrGT r0, r1, r9
+    __ lsrs(r11, r3, r12, Assembler::GT);              //       lsrGTs r11, r3, r12
+    __ asr(r2, r12, r6, Assembler::LE);                //       asrLE r2, r12, r6
+    __ asrs(r1, r10, r6, Assembler::LT);               //       asrLTs r1, r10, r6
+
+// TwoRegNon
+    __ mov(r10, r3);                                   //       mov r10, r3
+    __ movs(r0, r9);                                   //       movs r0, r9
+
+// OneRegImm
+    __ mov_i(r3, (unsigned)656U, Assembler::VC);         //     movVC r3, #656
+    __ movs_i(r4, (unsigned)2064384U);                   //     movs r4, #2064384
+
+// TwoRegSft
+    __ mov(r12, r6, ::lsr(3));                         //       mov r12, r6, lsr #3
+    __ movs(r5, sp, ::asr(10), Assembler::VC);         //       movVCs r5, sp, asr #10
+
+// TwoRegRSR
+    __ mov(r1, lr, ::ror(r3));                         //       mov r1, lr, ror r3
+    __ movs(r8, r12, ::ror(r9), Assembler::EQ);        //       movEQs r8, r12, ror r9
+
+// OneRegImm16
+    __ movw_i(r11, (unsigned)53041U, Assembler::LO);     //     movwLO r11, #53041
+    __ movt_i(r9, (unsigned)11255U, Assembler::LO);      //     movtLO r9, #11255
+
+// ThreeRegNon
+    __ mul(r1, sp, r5, Assembler::LE);                 //       mulLE r1, sp, r5
+    __ muls(r0, r10, r11);                             //       muls r0, r10, r11
+
+// FourRegNon
+    __ mla(r0, r3, r12, r7);                           //       mla r0, r3, r12, r7
+    __ mlas(r8, r11, r3, r6, Assembler::EQ);           //       mlaEQs r8, r11, r3, r6
+    __ umull(lr, r4, r5, r6);                          //       umull lr, r4, r5, r6
+    __ umulls(r0, r4, r6, r7);                         //       umulls r0, r4, r6, r7
+    __ umlal(r8, r0, r11, lr);                         //       umlal r8, r0, r11, lr
+    __ umlals(r11, r4, lr, r7);                        //       umlals r11, r4, lr, r7
+    __ smull(r1, r5, r6, r7, Assembler::HS);           //       smullHS r1, r5, r6, r7
+    __ smulls(r0, r11, r12, r5, Assembler::MI);        //       smullMIs r0, r11, r12, r5
+
+// FourRegNon
+    __ umaal(r8, r9, r2, r5);                          //       umaal r8, r9, r2, r5
+    __ mls(r0, r4, sp, lr, Assembler::EQ);             //       mlsEQ r0, r4, sp, lr
+
+// ThreeRegNon
+    __ qadd(r9, r4, sp, Assembler::PL);                //       qaddPL r9, r4, sp
+    __ qsub(r0, r12, r5, Assembler::MI);               //       qsubMI r0, r12, r5
+    __ qdadd(r3, r5, r7);                              //       qdadd r3, r5, r7
+    __ qdsub(r9, r2, r4);                              //       qdsub r9, r2, r4
+
+// FourRegNon
+    __ smlabb(r1, r12, r5, r6);                        //       smlabb r1, r12, r5, r6
+    __ smlabt(r0, r10, r12, r6);                       //       smlabt r0, r10, r12, r6
+    __ smlatb(r8, r1, r3, lr);                         //       smlatb r8, r1, r3, lr
+    __ smlatt(r1, sp, r6, r7);                         //       smlatt r1, sp, r6, r7
+    __ smlawb(r0, r3, r4, r6);                         //       smlawb r0, r3, r4, r6
+    __ smlawt(r11, r4, lr, r7);                        //       smlawt r11, r4, lr, r7
+    __ smlalbb(r0, r10, r6, r7);                       //       smlalbb r0, r10, r6, r7
+    __ smlalbt(r3, r11, r4, lr, Assembler::LS);        //       smlalbtLS r3, r11, r4, lr
+    __ smlaltb(r8, r11, r3, r12);                      //       smlaltb r8, r11, r3, r12
+    __ smlaltt(r8, r1, r3, r5);                        //       smlaltt r8, r1, r3, r5
+
+// ThreeRegNon
+    __ smulwb(r2, r12, sp, Assembler::HS);             //       smulwbHS r2, r12, sp
+    __ smulwt(r8, r12, r6);                            //       smulwt r8, r12, r6
+    __ smulbb(r2, r6, lr, Assembler::GE);              //       smulbbGE r2, r6, lr
+    __ smulbt(r8, r12, r7);                            //       smulbt r8, r12, r7
+    __ smultb(r10, r3, lr, Assembler::EQ);             //       smultbEQ r10, r3, lr
+    __ smultt(r0, r3, sp);                             //       smultt r0, r3, sp
+
+// MemoryOp
+    __ ldr(r10, Address(r7, r9, lsl(), Address::ADD, Address::post)); //        ldr r10, [r7], r9
+    __ ldrb(r0, Address(r9, 196));                     //       ldrb r0, [r9, #196]
+    __ ldrh(lr, Address(r4, r6, lsl(), Address::ADD, Address::pre)); // ldrh lr, [r4, r6]!
+    __ ldrsb(r6, Address(__ pre(r9, 232)));            //       ldrsb r6, [r9, #232]!
+    __ ldrsh(r2, Address(r1, r1, lsl(), Address::ADD, Address::post)); //       ldrsh r2, [r1], r1
+    __ str(r0, Address(r9, r4, lsl(), Address::ADD, Address::post)); // str r0, [r9], r4
+    __ strb(r3, Address(__ pre(r5, 92)));              //       strb r3, [r5, #92]!
+    __ strh(r2, Address(r8, 160));                     //       strh r2, [r8, #160]
+
+// MemoryOp
+    __ ldr(r8, Address(r12, r8, lsl(), Address::ADD, Address::off)); // ldr r8, [r12, r8]
+    __ ldrb(r11, Address(__ post(r10, 16)));           //       ldrb r11, [r10], #16
+    __ ldrh(r11, Address(r10, r6, lsl(), Address::ADD, Address::off)); //       ldrh r11, [r10, r6]
+    __ ldrsb(r5, Address(r11, r10, lsl(), Address::ADD, Address::pre)); //      ldrsb r5, [r11, r10]!
+    __ ldrsh(r6, Address(r3, r7, lsl(), Address::ADD, Address::off)); //        ldrsh r6, [r3, r7]
+    __ str(r7, Address(sp, r5, lsl(), Address::ADD, Address::pre)); //  str r7, [sp, r5]!
+    __ strb(r2, Address(r10));                         //       strb r2, [r10]
+    __ strh(r6, Address(r4, r3, lsl(), Address::ADD, Address::post)); //        strh r6, [r4], r3
+
+// MemoryOp
+    __ ldr(r10, Address(r12));                         //       ldr r10, [r12]
+    __ ldrb(r4, Address(__ post(r11, 132)));           //       ldrb r4, [r11], #132
+    __ ldrh(r9, Address(r9, r12, lsl(), Address::ADD, Address::post)); //       ldrh r9, [r9], r12
+    __ ldrsb(r9, Address(__ post(r3, 148)));           //       ldrsb r9, [r3], #148
+    __ ldrsh(r11, Address(__ pre(r2, 148)));           //       ldrsh r11, [r2, #148]!
+    __ str(r11, Address(sp, r11, lsl(), Address::ADD, Address::off)); //        str r11, [sp, r11]
+    __ strb(r1, Address(sp, r10, lsl(), Address::ADD, Address::off)); //        strb r1, [sp, r10]
+    __ strh(r10, Address(lr, r9, lsl(), Address::ADD, Address::post)); //       strh r10, [lr], r9
+
+// MemoryOp
+    __ ldr(r6, Address(r3, r4, lsl(), Address::ADD, Address::pre)); //  ldr r6, [r3, r4]!
+    __ ldrb(r4, Address(r6, sp, lsl(), Address::ADD, Address::pre)); // ldrb r4, [r6, sp]!
+    __ ldrh(r6, Address(r7, r10, lsl(), Address::ADD, Address::post)); //       ldrh r6, [r7], r10
+    __ ldrsb(r0, Address(r6, r11, lsl(), Address::ADD, Address::pre)); //       ldrsb r0, [r6, r11]!
+    __ ldrsh(r10, Address(r6, sp, lsl(), Address::ADD, Address::post)); //      ldrsh r10, [r6], sp
+    __ str(r7, Address(r3, r12, lsl(), Address::ADD, Address::off)); // str r7, [r3, r12]
+    __ strb(r3, Address(r8, r1, lsl(), Address::ADD, Address::pre)); // strb r3, [r8, r1]!
+    __ strh(r4, Address(r12, 64));                     //       strh r4, [r12, #64]
+
+    __ bind(near);
+
+// LitMemoryOp
+    __ ldr(r1, near);                                  //       ldr r1, near
+    __ ldrb(r7, __ pc());                              //       ldrb r7, .
+    __ ldrh(r2, near);                                 //       ldrh r2, near
+    __ ldrsb(r10, __ pc());                            //       ldrsb r10, .
+    __ ldrsh(lr, near_post);                           //       ldrsh lr, near_post
+
+// LitMemoryOp
+    __ ldr(r2, __ pc());                               //       ldr r2, .
+    __ ldrb(r3, __ pc());                              //       ldrb r3, .
+    __ ldrh(r7, near_post);                            //       ldrh r7, near_post
+    __ ldrsb(sp, __ pc());                             //       ldrsb sp, .
+    __ ldrsh(r10, near);                               //       ldrsh r10, near
+
+// LitMemoryOp
+    __ ldr(r5, __ pc());                               //       ldr r5, .
+    __ ldrb(lr, near_post);                            //       ldrb lr, near_post
+    __ ldrh(r5, near_post);                            //       ldrh r5, near_post
+    __ ldrsb(r6, near);                                //       ldrsb r6, near
+    __ ldrsh(r11, near);                               //       ldrsh r11, near
+
+// LitMemoryOp
+    __ ldr(r7, near_post);                             //       ldr r7, near_post
+    __ ldrb(r5, near_post);                            //       ldrb r5, near_post
+    __ ldrh(r10, near);                                //       ldrh r10, near
+    __ ldrsb(r6, near_post);                           //       ldrsb r6, near_post
+    __ ldrsh(r9, __ pc());                             //       ldrsh r9, .
+
+    __ bind(near_post);
+
+// MemoryRegRegSftOp
+    __ ldr(r0, Address(r0, r10, ::ror(6), Address::ADD, Address::post)); //     ldr r0, [r0], r10, ror #6
+    __ ldrb(r3, Address(r8, lr, ::lsl(9), Address::ADD, Address::off)); //      ldrb r3, [r8, lr, lsl #9]
+    __ str(r5, Address(sp, r3, ::lsl(15), Address::ADD, Address::off)); //      str r5, [sp, r3, lsl #15]
+    __ strb(r9, Address(r9, r5, ::asr(2), Address::ADD, Address::post)); //     strb r9, [r9], r5, asr #2
+
+// MemoryRegRegSftOp
+    __ ldr(r5, Address(r4, r0, ::ror(6), Address::ADD, Address::off)); //       ldr r5, [r4, r0, ror #6]
+    __ ldrb(lr, Address(r0, r4, ::lsr(9), Address::ADD, Address::off)); //      ldrb lr, [r0, r4, lsr #9]
+    __ str(r5, Address(r12, r12, ::asr(5), Address::ADD, Address::post)); //    str r5, [r12], r12, asr #5
+    __ strb(r3, Address(r1, r7, ::ror(12), Address::ADD, Address::pre)); //     strb r3, [r1, r7, ror #12]!
+
+// MemoryRegRegSftOp
+    __ ldr(r6, Address(r2, r3, ::rrx(), Address::ADD, Address::pre)); //        ldr r6, [r2, r3, rrx]!
+    __ ldrb(r8, Address(lr, r2, ::asr(16), Address::ADD, Address::pre)); //     ldrb r8, [lr, r2, asr #16]!
+    __ str(r6, Address(r3, r6, ::ror(7), Address::ADD, Address::pre)); //       str r6, [r3, r6, ror #7]!
+    __ strb(r3, Address(r8, r2, ::lsl(10), Address::ADD, Address::off)); //     strb r3, [r8, r2, lsl #10]
+
+// MemoryRegRegSftOp
+    __ ldr(r11, Address(sp, lr, ::lsl(8), Address::ADD, Address::off)); //      ldr r11, [sp, lr, lsl #8]
+    __ ldrb(r10, Address(sp, r12, ::lsl(4), Address::ADD, Address::pre)); //    ldrb r10, [sp, r12, lsl #4]!
+    __ str(sp, Address(r9, r2, ::asr(2), Address::ADD, Address::off)); //       str sp, [r9, r2, asr #2]
+    __ strb(r7, Address(r11, lr, ::asr(14), Address::ADD, Address::pre)); //    strb r7, [r11, lr, asr #14]!
+
+// LdStOne
+    __ ldrex(r12, r11);                                //       ldrex r12, [r11]
+    __ ldrexb(r4, r12);                                //       ldrexb r4, [r12]
+    __ ldrexh(r11, r11);                               //       ldrexh r11, [r11]
+
+// LdStTwo
+    __ strex(r1, r7, lr);                              //       strex r1, r7, [lr]
+    __ strexb(r12, r6, r4);                            //       strexb r12, r6, [r4]
+    __ strexh(r4, r6, r7, Assembler::HS);              //       strexhHS r4, r6, [r7]
+
+// ThreeRegNon
+    __ sadd16(r3, r4, r7);                             //       sadd16 r3, r4, r7
+    __ sasx(r9, r10, r3, Assembler::AL);               //       sasxAL r9, r10, r3
+    __ ssax(r12, r5, r6);                              //       ssax r12, r5, r6
+    __ ssub16(r12, r5, lr);                            //       ssub16 r12, r5, lr
+    __ sadd8(r0, r10, r7);                             //       sadd8 r0, r10, r7
+    __ ssub8(r0, r8, r2, Assembler::VS);               //       ssub8VS r0, r8, r2
+    __ qadd16(r11, r4, r5, Assembler::PL);             //       qadd16PL r11, r4, r5
+    __ qasx(r11, r3, r12, Assembler::VS);              //       qasxVS r11, r3, r12
+    __ qsax(r0, r3, r5);                               //       qsax r0, r3, r5
+    __ ssub16(r10, r12, r5, Assembler::AL);            //       ssub16AL r10, r12, r5
+    __ qadd8(r10, r6, lr, Assembler::CC);              //       qadd8CC r10, r6, lr
+    __ qsub8(r10, r11, r7);                            //       qsub8 r10, r11, r7
+    __ shadd16(r9, r4, lr, Assembler::PL);             //       shadd16PL r9, r4, lr
+    __ shasx(r1, lr, r7);                              //       shasx r1, lr, r7
+    __ shsax(r9, r11, r5, Assembler::LO);              //       shsaxLO r9, r11, r5
+    __ shsub16(r3, r1, r11, Assembler::GE);            //       shsub16GE r3, r1, r11
+    __ shadd8(sp, r5, r7, Assembler::GT);              //       shadd8GT sp, r5, r7
+    __ shsub8(r1, r5, r7);                             //       shsub8 r1, r5, r7
+
+// ThreeRegNon
+    __ uadd16(r10, r4, r7);                            //       uadd16 r10, r4, r7
+    __ uasx(r1, r9, r7, Assembler::HS);                //       uasxHS r1, r9, r7
+    __ usax(r11, sp, r7);                              //       usax r11, sp, r7
+    __ usub16(r11, r4, lr);                            //       usub16 r11, r4, lr
+    __ uadd8(r2, sp, r7, Assembler::LO);               //       uadd8LO r2, sp, r7
+    __ usub8(r8, r10, lr, Assembler::GT);              //       usub8GT r8, r10, lr
+    __ uqadd16(r3, r12, sp);                           //       uqadd16 r3, r12, sp
+    __ uqasx(r4, sp, r6);                              //       uqasx r4, sp, r6
+    __ uqsax(r1, r10, lr);                             //       uqsax r1, r10, lr
+    __ uqsub16(r2, sp, lr, Assembler::LE);             //       uqsub16LE r2, sp, lr
+    __ uqadd8(r1, r12, r5);                            //       uqadd8 r1, r12, r5
+    __ uqsub8(r0, r4, sp, Assembler::GT);              //       uqsub8GT r0, r4, sp
+    __ uhadd16(r0, r10, r5, Assembler::HI);            //       uhadd16HI r0, r10, r5
+    __ uhasx(r11, r4, r7, Assembler::LE);              //       uhasxLE r11, r4, r7
+    __ uhsax(r1, lr, r9, Assembler::GE);               //       uhsaxGE r1, lr, r9
+    __ uhsub16(r2, r11, lr);                           //       uhsub16 r2, r11, lr
+    __ uhadd8(r9, r4, r5, Assembler::GE);              //       uhadd8GE r9, r4, r5
+    __ uhsub8(r2, sp, lr, Assembler::HI);              //       uhsub8HI r2, sp, lr
+
+// PKUPSATREV
+    __ sxtab16(r10, r3, r7, ::ror(16));                //       sxtab16 r10, r3, r7, ROR #16
+    __ sxtab(r9, r5, r7, ::ror(24), Assembler::CS);    //       sxtabCS r9, r5, r7, ROR #24
+    __ sxtah(r3, r5, r7, ::ror(8));                    //       sxtah r3, r5, r7, ROR #8
+    __ uxtab16(r8, r4, r6, ::ror(8), Assembler::AL);   //       uxtab16AL r8, r4, r6, ROR #8
+    __ uxtab(r0, r11, sp, ::rrx(), Assembler::EQ);     //       uxtabEQ r0, r11, sp, ROR #0
+    __ uxtah(r9, r12, r5, ::rrx());                    //       uxtah r9, r12, r5, ROR #0
+
+// PKUPSATREV
+    __ sxtb16(r3, r11, ::ror(16), Assembler::GE);      //       sxtb16GE r3, r11, ROR #16
+    __ sxtb(r2, r6, ::rrx(), Assembler::HI);           //       sxtbHI r2, r6, ROR #0
+    __ sxth(r3, sp, ::ror(24), Assembler::GT);         //       sxthGT r3, sp, ROR #24
+    __ uxtb16(r12, r5, ::ror(16));                     //       uxtb16 r12, r5, ROR #16
+    __ uxtb(r12, r5, ::ror(16));                       //       uxtb r12, r5, ROR #16
+    __ uxth(r8, r5, ::ror(16));                        //       uxth r8, r5, ROR #16
+
+// TwoRegNon
+    __ rev(r10, r4, Assembler::EQ);                    //       revEQ r10, r4
+    __ rev16(r8, r12, Assembler::GE);                  //       rev16GE r8, r12
+    __ rbit(lr, r7);                                   //       rbit lr, r7
+    __ revsh(sp, r7, Assembler::GT);                   //       revshGT sp, r7
+
+// ThreeRegNon
+    __ sdiv(r9, sp, lr);                               //       sdiv r9, sp, lr
+    __ udiv(r2, r12, r6);                              //       udiv r2, r12, r6
+
+// TwoRegTwoImm
+    __ sbfx(r0, r1, (unsigned)20U, (unsigned)3U, Assembler::MI); //     sbfxMI r0, r1, #20, #3
+    __ ubfx(r9, r2, (unsigned)16U, (unsigned)15U);     //       ubfx r9, r2, #16, #15
+    __ bfi(r1, r11, (unsigned)27U, (unsigned)3U, Assembler::HI); //     bfiHI r1, r11, #27, #3
+
+// TwoRegTwoImm
+    __ bfc(r3, (unsigned)7U, (unsigned)10U);           //       bfc r3, #7, #10
+
+// MultipleMemOp
+    __ stmda(r6, 3435U, false);                        //       stmda r6, {r0, r1, r3, r5, r6, r8, r10, r11}
+    __ stmed(r4, 14559U, false);                       //       stmed r4, {r0, r1, r2, r3, r4, r6, r7, r11, r12, sp}
+    __ ldmda(r0, 57812U, false);                       //       ldmda r0, {r2, r4, r6, r7, r8, sp, lr, pc}
+    __ ldmfa(r12, 39027U, true);                       //       ldmfa r12!, {r0, r1, r4, r5, r6, r11, r12, pc}
+    __ stmia(r9, 12733U, true);                        //       stmia r9!, {r0, r2, r3, r4, r5, r7, r8, r12, sp}
+    __ stmea(r11, 21955U, false);                      //       stmea r11, {r0, r1, r6, r7, r8, r10, r12, lr}
+    __ ldmia(r12, 48418U, true);                       //       ldmia r12!, {r1, r5, r8, r10, r11, r12, sp, pc}
+    __ ldmfd(sp, 41226U, true);                        //       ldmfd sp!, {r1, r3, r8, sp, pc}
+    __ stmdb(r11, 8729U, true);                        //       stmdb r11!, {r0, r3, r4, r9, sp}
+    __ stmfd(r9, 36309U, true);                        //       stmfd r9!, {r0, r2, r4, r6, r7, r8, r10, r11, pc}
+    __ ldmdb(r5, 24667U, true);                        //       ldmdb r5!, {r0, r1, r3, r4, r6, sp, lr}
+    __ ldmea(r1, 37287U, false);                       //       ldmea r1, {r0, r1, r2, r5, r7, r8, r12, pc}
+    __ stmib(r11, 28266U, true);                       //       stmib r11!, {r1, r3, r5, r6, r9, r10, r11, sp, lr}
+    __ stmfa(r11, 17671U, false);                      //       stmfa r11, {r0, r1, r2, r8, r10, lr}
+    __ ldmib(r0, 21452U, true);                        //       ldmib r0!, {r2, r3, r6, r7, r8, r9, r12, lr}
+    __ ldmed(r1, 11751U, false);                       //       ldmed r1, {r0, r1, r2, r5, r6, r7, r8, r10, r11, sp}
+
+// BranchLabel
+    __ b(forth, Assembler::CS);                        //       bCS forth
+    __ bl(__ pc(), Assembler::MI);                     //       blMI .
+
+// OneRegNon
+    __ b(r0, Assembler::VS);                           //       bxVS r0
+    __ bl(r3);                                         //       blx r3
+
+// BranchLabel
+    __ b(__ pc(), Assembler::AL);                      //       bAL .
+    __ bl(__ pc());                                    //       bl .
+
+// OneRegNon
+    __ b(r0, Assembler::VS);                           //       bxVS r0
+    __ bl(r5);                                         //       blx r5
+
+// BranchLabel
+    __ b(forth, Assembler::LE);                        //       bLE forth
+    __ bl(__ pc(), Assembler::MI);                     //       blMI .
+
+// OneRegNon
+    __ b(r9, Assembler::NE);                           //       bxNE r9
+    __ bl(r12);                                        //       blx r12
+
+// BranchLabel
+    __ b(back);                                        //       b back
+    __ bl(__ pc(), Assembler::HI);                     //       blHI .
+
+// OneRegNon
+    __ b(r1, Assembler::VC);                           //       bxVC r1
+    __ bl(r7, Assembler::GT);                          //       blxGT r7
+
+// BranchLabel
+    __ b(back, Assembler::GE);                         //       bGE back
+    __ bl(__ pc(), Assembler::HI);                     //       blHI .
+
+// OneRegNon
+    __ b(r12);                                         //       bx r12
+    __ bl(r7, Assembler::CC);                          //       blxCC r7
+
+// BranchLabel
+    __ b(__ pc());                                     //       b .
+    __ bl(back, Assembler::GT);                        //       blGT back
+
+// OneRegNon
+    __ b(r1, Assembler::GE);                           //       bxGE r1
+    __ bl(r0);                                         //       blx r0
+
+// BranchLabel
+    __ b(__ pc());                                     //       b .
+    __ bl(forth);                                      //       bl forth
+
+// OneRegNon
+    __ b(lr, Assembler::GT);                           //       bxGT lr
+    __ bl(r11, Assembler::NE);                         //       blxNE r11
+
+// BranchLabel
+    __ b(__ pc(), Assembler::CS);                      //       bCS .
+    __ bl(__ pc());                                    //       bl .
+
+// OneRegNon
+    __ b(r10, Assembler::HS);                          //       bxHS r10
+    __ bl(r4);                                         //       blx r4
+
+// BranchLabel
+    __ b(back, Assembler::AL);                         //       bAL back
+    __ bl(__ pc());                                    //       bl .
+
+// OneRegNon
+    __ b(r12, Assembler::LO);                          //       bxLO r12
+    __ bl(r8);                                         //       blx r8
+
+// BranchLabel
+    __ b(forth);                                       //       b forth
+    __ bl(__ pc());                                    //       bl .
+
+// OneRegNon
+    __ b(r10);                                         //       bx r10
+    __ bl(r1);                                         //       blx r1
+
+// ThreeFltNon
+    __ vmla_f32(d2, d4, d6, Assembler::MI);            //       vmlaMI.f32 s4, s8, s12
+    __ vmls_f32(d2, d5, d5);                           //       vmls.f32 s4, s10, s10
+    __ vnmla_f32(d1, d5, d6);                          //       vnmla.f32 s2, s10, s12
+    __ vnmls_f32(d4, d3, d4, Assembler::LT);           //       vnmlsLT.f32 s8, s6, s8
+    __ vnmul_f32(d3, d6, d7, Assembler::MI);           //       vnmulMI.f32 s6, s12, s14
+    __ vadd_f32(d0, d1, d0);                           //       vadd.f32 s0, s2, s0
+    __ vsub_f32(d1, d2, d5, Assembler::AL);            //       vsubAL.f32 s2, s4, s10
+    __ vdiv_f32(d0, d1, d6, Assembler::CS);            //       vdivCS.f32 s0, s2, s12
+
+// ThreeFltNon
+    __ vmla_f64(d0, d3, d6);                           //       vmla.f64 d0, d3, d6
+    __ vmls_f64(d0, d1, d5);                           //       vmls.f64 d0, d1, d5
+    __ vnmla_f64(d1, d4, d6);                          //       vnmla.f64 d1, d4, d6
+    __ vnmls_f64(d0, d1, d1, Assembler::NE);           //       vnmlsNE.f64 d0, d1, d1
+    __ vnmul_f64(d3, d5, d5, Assembler::NE);           //       vnmulNE.f64 d3, d5, d5
+    __ vadd_f64(d0, d2, d4, Assembler::LO);            //       vaddLO.f64 d0, d2, d4
+    __ vsub_f64(d1, d2, d4);                           //       vsub.f64 d1, d2, d4
+    __ vdiv_f64(d0, d1, d5, Assembler::MI);            //       vdivMI.f64 d0, d1, d5
+
+// TwoFltNon
+    __ vabs_f32(d3, d3);                               //       vabs.f32 s6, s6
+    __ vneg_f32(d3, d4, Assembler::PL);                //       vnegPL.f32 s6, s8
+    __ vsqrt_f32(d0, d4);                              //       vsqrt.f32 s0, s8
+
+// TwoFltNon
+    __ vabs_f64(d0, d4);                               //       vabs.f64 d0, d4
+    __ vneg_f64(d1, d4);                               //       vneg.f64 d1, d4
+    __ vsqrt_f64(d0, d1);                              //       vsqrt.f64 d0, d1
+
+// vmov_f32
+    __ vmov_f32(d0, lr, Assembler::PL);                //       vmovPL.f32 s0, lr
+
+// vmov_f32
+    __ vmov_f32(r11, d4);                              //       vmov.f32 r11, s8
+
+// vmov_f64
+    __ vmov_f64(d1, r11, lr, Assembler::LT);           //       vmovLT.f64 d1, r11, lr
+
+// vmov_f64
+    __ vmov_f64(r7, r5, d5);                           //       vmov.f64 r7, r5, d5
+
+// vmov_f32
+    __ vmov_f32(d4, d6);                               //       vmov.f32 s8, s12
+
+// vmov_f64
+    __ vmov_f64(d1, d2, Assembler::HI);                //       vmovHI.f64 d1, d2
+
+// vmov_f32
+    __ vmov_f32(d2, 1.0f, Assembler::VS);              //       vmovVS.f32 s4, #1.0
+
+// vmov_f64
+    __ vmov_f64(d2, 1.0);                              //       vmov.f64 d2, #1.0
+
+// vmov_f32
+    __ vmov_f32(d3, 2.0f);                             //       vmov.f32 s6, #2.0
+
+// vmov_f64
+    __ vmov_f64(d1, 2.0);                              //       vmov.f64 d1, #2.0
+
+// vector memory
+    __ vldr_f32(d2, Address(r5, 116));                 //       vldr.f32 s4, [r5, #116]
+    __ vstr_f32(d1, Address(r1, 56), Assembler::CC);   //       vstrCC.f32 s2, [r1, #56]
+
+// vector memory
+    __ vldr_f64(d7, Address(r5, 16), Assembler::NE);   //       vldrNE.f64 d7, [r5, #16]
+    __ vstr_f64(d6, Address(r1, 228));                 //       vstr.f64 d6, [r1, #228]
+
+    __ bind(near_flt);
+
+// vector memory
+    __ vldr_f32(d1, near_post_flt);                    //       vldr.f32 s2, near_post_flt
+    __ vstr_f32(d3, near_post_flt);                    //       vstr.f32 s6, near_post_flt
+
+// vector memory
+    __ vldr_f64(d2, near_flt, Assembler::LT);          //       vldrLT.f64 d2, near_flt
+    __ vstr_f64(d3, __ pc(), Assembler::GT);           //       vstrGT.f64 d3, .
+
+// vector memory
+    __ vldr_f32(d2, near_post_flt, Assembler::CC);     //       vldrCC.f32 s4, near_post_flt
+    __ vstr_f32(d0, near_post_flt);                    //       vstr.f32 s0, near_post_flt
+
+// vector memory
+    __ vldr_f64(d4, near_post_flt, Assembler::GT);     //       vldrGT.f64 d4, near_post_flt
+    __ vstr_f64(d0, near_flt);                         //       vstr.f64 d0, near_flt
+
+// vector memory
+    __ vldr_f32(d4, near_post_flt);                    //       vldr.f32 s8, near_post_flt
+    __ vstr_f32(d3, near_post_flt);                    //       vstr.f32 s6, near_post_flt
+
+// vector memory
+    __ vldr_f64(d4, near_flt, Assembler::PL);          //       vldrPL.f64 d4, near_flt
+    __ vstr_f64(d5, near_flt);                         //       vstr.f64 d5, near_flt
+
+// vector memory
+    __ vldr_f32(d4, near_post_flt, Assembler::LS);     //       vldrLS.f32 s8, near_post_flt
+    __ vstr_f32(d6, __ pc(), Assembler::CC);           //       vstrCC.f32 s12, .
+
+// vector memory
+    __ vldr_f64(d6, near_post_flt, Assembler::AL);     //       vldrAL.f64 d6, near_post_flt
+    __ vstr_f64(d1, near_post_flt, Assembler::LT);     //       vstrLT.f64 d1, near_post_flt
+
+    __ bind(near_post_flt);
+
+// FltMultMemOp
+    __ vldmia_f32(r1, 4U, false);                      //       vldmia.f32 r1, {s4}
+    __ vstmia_f32(r6, 4U, true, Assembler::CS);        //       vstmiaCS.f32 r6!, {s4}
+
+// DblMultMemOp
+    __ vldmia_f64(r9, 30U, true);                      //       vldmia.f64 r9!, {d1, d2, d3, d4}
+    __ vstmia_f64(r3, 192U, true);                     //       vstmia.f64 r3!, {d6, d7}
+
+// FltMultMemOp
+    __ vldmdb_f32(r2, 8U, Assembler::VS);              //       vldmdbVS.f32 r2!, {s6}
+    __ vstmdb_f32(r6, 128U);                           //       vstmdb.f32 r6!, {s14}
+
+// DblMultMemOp
+    __ vldmdb_f64(sp, 240U);                           //       vldmdb.f64 sp!, {d4, d5, d6, d7}
+    __ vstmdb_f64(r0, 224U);                           //       vstmdb.f64 r0!, {d5, d6, d7}
+
+// vcmp_f32
+    __ vcmp_f32(d1, d1);                               //       vcmp.f32 s2, s2
+
+// vcmpe_f32
+    __ vcmpe_f32(d4, d4, Assembler::VC);               //       vcmpeVC.f32 s8, s8
+
+// vcmp_f64
+    __ vcmp_f64(d0, d6);                               //       vcmp.f64 d0, d6
+
+// vcmpe_f64
+    __ vcmpe_f64(d3, d7, Assembler::GE);               //       vcmpeGE.f64 d3, d7
+
+// vcmp_f32
+    __ vcmp_f32(d1, 0.0f, Assembler::LT);              //       vcmpLT.f32 s2, #0.0
+
+// vcmpe_f32
+    __ vcmpe_f32(d7, 0.0f, Assembler::GT);             //       vcmpeGT.f32 s14, #0.0
+
+// vcmp_f64
+    __ vcmp_f64(d4, 0.0);                              //       vcmp.f64 d4, #0.0
+
+// vcmpe_f64
+    __ vcmpe_f64(d1, 0.0);                             //       vcmpe.f64 d1, #0.0
+
+// vcvt
+    __ vcvt_s32_f32(d1, d3, Assembler::VS);            //       vcvtVS.s32.f32 s2, s6
+    __ vcvt_u32_f32(d3, d7, Assembler::GT);            //       vcvtGT.u32.f32 s6, s14
+    __ vcvt_f32_s32(d0, d1, Assembler::CC);            //       vcvtCC.f32.s32 s0, s2
+    __ vcvt_f32_u32(d1, d2, Assembler::CC);            //       vcvtCC.f32.u32 s2, s4
+
+// vcvt
+    __ vcvt_s32_f64(d2, d4, Assembler::HI);            //       vcvtHI.s32.f64 s4, d4
+    __ vcvt_u32_f64(d3, d6, Assembler::HI);            //       vcvtHI.u32.f64 s6, d6
+    __ vcvt_f32_f64(d3, d7, Assembler::LS);            //       vcvtLS.f32.f64 s6, d7
+
+// vcvt
+    __ vcvt_f64_s32(d3, d4);                           //       vcvt.f64.s32 d3, s8
+    __ vcvt_f64_u32(d5, d7, Assembler::EQ);            //       vcvtEQ.f64.u32 d5, s14
+    __ vcvt_f64_f32(d4, d5, Assembler::AL);            //       vcvtAL.f64.f32 d4, s10
+
+// BKPT
+    __ bkpt((unsigned)26U);                            //       bkpt #26
+
+    __ bind(forth);
+
+/*
+aarch32ops.o:     file format elf32-littlearm
+
+
+Disassembly of section .text:
+
+00000000 <back>:
+   0:   e082852b        add     r8, r2, fp, lsr #10
+   4:   009310c7        addseq  r1, r3, r7, asr #1
+   8:   e0290284        eor     r0, r9, r4, lsl #5
+   c:   c0329066        eorsgt  r9, r2, r6, rrx
+  10:   c04c000e        subgt   r0, ip, lr
+  14:   00528364        subseq  r8, r2, r4, ror #6
+  18:   e069818d        rsb     r8, r9, sp, lsl #3
+  1c:   60708864        rsbsvs  r8, r0, r4, ror #16
+  20:   d08597a1        addle   r9, r5, r1, lsr #15
+  24:   e09d12c6        adds    r1, sp, r6, asr #5
+  28:   c0adb0c7        adcgt   fp, sp, r7, asr #1
+  2c:   e0b80329        adcs    r0, r8, r9, lsr #6
+  30:   e0c392e6        sbc     r9, r3, r6, ror #5
+  34:   80dd1845        sbcshi  r1, sp, r5, asr #16
+  38:   30e28486        rsccc   r8, r2, r6, lsl #9
+  3c:   e0f4a76d        rscs    sl, r4, sp, ror #14
+  40:   118db785        orrne   fp, sp, r5, lsl #15
+  44:   e19a9764        orrs    r9, sl, r4, ror #14
+  48:   e1cd90e5        bic     r9, sp, r5, ror #1
+  4c:   e1d20547        bics    r0, r2, r7, asr #10
+  50:   e086d777        add     sp, r6, r7, ror r7
+  54:   809c4776        addshi  r4, ip, r6, ror r7
+  58:   90265c57        eorls   r5, r6, r7, asr ip
+  5c:   e035841d        eors    r8, r5, sp, lsl r4
+  60:   e04c2055        sub     r2, ip, r5, asr r0
+  64:   20539c17        subscs  r9, r3, r7, lsl ip
+  68:   c06c9614        rsbgt   r9, ip, r4, lsl r6
+  6c:   e072811c        rsbs    r8, r2, ip, lsl r1
+  70:   e08c4d1d        add     r4, ip, sp, lsl sp
+  74:   e09b8d76        adds    r8, fp, r6, ror sp
+  78:   10a20415        adcne   r0, r2, r5, lsl r4
+  7c:   e0beb256        adcs    fp, lr, r6, asr r2
+  80:   80ca835e        sbchi   r8, sl, lr, asr r3
+  84:   e0dc1615        sbcs    r1, ip, r5, lsl r6
+  88:   60e54a7e        rscvs   r4, r5, lr, ror sl
+  8c:   e0fc181d        rscs    r1, ip, sp, lsl r8
+  90:   61818076        orrvs   r8, r1, r6, ror r0
+  94:   e19db577        orrs    fp, sp, r7, ror r5
+  98:   e1ce4216        bic     r4, lr, r6, lsl r2
+  9c:   e1dba31d        bics    sl, fp, sp, lsl r3
+  a0:   828d8261        addhi   r8, sp, #268435462      ; 0x10000006
+  a4:   e29ed69b        adds    sp, lr, #162529280      ; 0x9b00000
+  a8:   e226e87d        eor     lr, r6, #8192000        ; 0x7d0000
+  ac:   e2332f49        eors    r2, r3, #292    ; 0x124
+  b0:   e24d46d9        sub     r4, sp, #227540992      ; 0xd900000
+  b4:   b25e1402        subslt  r1, lr, #33554432       ; 0x2000000
+  b8:   e2650325        rsb     r0, r5, #-1811939328    ; 0x94000000
+  bc:   3274882f        rsbscc  r8, r4, #3080192        ; 0x2f0000
+  c0:   b2849102        addlt   r9, r4, #-2147483648    ; 0x80000000
+  c4:   e2948902        adds    r8, r4, #32768  ; 0x8000
+  c8:   22aeac2a        adccs   sl, lr, #10752  ; 0x2a00
+  cc:   e2b6aabd        adcs    sl, r6, #774144 ; 0xbd000
+  d0:   e2cc2426        sbc     r2, ip, #637534208      ; 0x26000000
+  d4:   e2da85a5        sbcs    r8, sl, #692060160      ; 0x29400000
+  d8:   e2e6d871        rsc     sp, r6, #7405568        ; 0x710000
+  dc:   12fba6e9        rscsne  sl, fp, #244318208      ; 0xe900000
+  e0:   638737ff        orrvs   r3, r7, #66846720       ; 0x3fc0000
+  e4:   03952951        orrseq  r2, r5, #1327104        ; 0x144000
+  e8:   63c18eea        bicvs   r8, r1, #3744   ; 0xea0
+  ec:   33d2020a        bicscc  r0, r2, #-1610612736    ; 0xa0000000
+  f0:   e118028d        tst     r8, sp, lsl #5
+  f4:   e13601a7        teq     r6, r7, lsr #3
+  f8:   e15c0164        cmp     ip, r4, ror #2
+  fc:   b1750807        cmnlt   r5, r7, lsl #16
+ 100:   e112073e        tst     r2, lr, lsr r7
+ 104:   31300572        teqcc   r0, r2, ror r5
+ 108:   915e0b37        cmpls   lr, r7, lsr fp
+ 10c:   617a0b17        cmnvs   sl, r7, lsl fp
+ 110:   e3120585        tst     r2, #557842432  ; 0x21400000
+ 114:   433e071b        teqmi   lr, #7077888    ; 0x6c0000
+ 118:   e355030e        cmp     r5, #939524096  ; 0x38000000
+ 11c:   3377010a        cmncc   r7, #-2147483646        ; 0x80000002
+ 120:   e1a00b84        lsl     r0, r4, #23
+ 124:   e1b01484        lsls    r1, r4, #9
+ 128:   e1a001aa        lsr     r0, sl, #3
+ 12c:   e1b00a2a        lsrs    r0, sl, #20
+ 130:   e1a015c9        asr     r1, r9, #11
+ 134:   61b0254b        asrsvs  r2, fp, #10
+ 138:   31a08fe2        rorcc   r8, r2, #31
+ 13c:   e1b0946c        rors    r9, ip, #8
+ 140:   e1a0877e        ror     r8, lr, r7
+ 144:   e1b0c473        rors    ip, r3, r4
+ 148:   c1a0ce1d        lslgt   ip, sp, lr
+ 14c:   e1b0c61d        lsls    ip, sp, r6
+ 150:   c1a00931        lsrgt   r0, r1, r9
+ 154:   c1b0bc33        lsrsgt  fp, r3, ip
+ 158:   d1a0265c        asrle   r2, ip, r6
+ 15c:   b1b0165a        asrslt  r1, sl, r6
+ 160:   e1a0a003        mov     sl, r3
+ 164:   e1b00009        movs    r0, r9
+ 168:   73a03e29        movvc   r3, #656        ; 0x290
+ 16c:   e3b0497e        movs    r4, #2064384    ; 0x1f8000
+ 170:   e1a0c1a6        lsr     ip, r6, #3
+ 174:   71b0554d        asrsvc  r5, sp, #10
+ 178:   e1a0137e        ror     r1, lr, r3
+ 17c:   01b0897c        rorseq  r8, ip, r9
+ 180:   330cbf31        movwcc  fp, #53041      ; 0xcf31
+ 184:   33429bf7        movtcc  r9, #11255      ; 0x2bf7
+ 188:   d001059d        mulle   r1, sp, r5
+ 18c:   e0100b9a        muls    r0, sl, fp
+ 190:   e0207c93        mla     r0, r3, ip, r7
+ 194:   0038639b        mlaseq  r8, fp, r3, r6
+ 198:   e084e695        umull   lr, r4, r5, r6
+ 19c:   e0940796        umulls  r0, r4, r6, r7
+ 1a0:   e0a08e9b        umlal   r8, r0, fp, lr
+ 1a4:   e0b4b79e        umlals  fp, r4, lr, r7
+ 1a8:   20c51796        smullcs r1, r5, r6, r7
+ 1ac:   40db059c        smullsmi        r0, fp, ip, r5
+ 1b0:   e0498592        umaal   r8, r9, r2, r5
+ 1b4:   0060ed94        mlseq   r0, r4, sp, lr
+ 1b8:   510d9054        qaddpl  r9, r4, sp
+ 1bc:   4125005c        qsubmi  r0, ip, r5
+ 1c0:   e1473055        qdadd   r3, r5, r7
+ 1c4:   e1649052        qdsub   r9, r2, r4
+ 1c8:   e101658c        smlabb  r1, ip, r5, r6
+ 1cc:   e1006cca        smlabt  r0, sl, ip, r6
+ 1d0:   e108e3a1        smlatb  r8, r1, r3, lr
+ 1d4:   e10176ed        smlatt  r1, sp, r6, r7
+ 1d8:   e1206483        smlawb  r0, r3, r4, r6
+ 1dc:   e12b7ec4        smlawt  fp, r4, lr, r7
+ 1e0:   e14a0786        smlalbb r0, sl, r6, r7
+ 1e4:   914b3ec4        smlalbtls       r3, fp, r4, lr
+ 1e8:   e14b8ca3        smlaltb r8, fp, r3, ip
+ 1ec:   e14185e3        smlaltt r8, r1, r3, r5
+ 1f0:   21220dac        smulwbcs        r2, ip, sp
+ 1f4:   e12806ec        smulwt  r8, ip, r6
+ 1f8:   a1620e86        smulbbge        r2, r6, lr
+ 1fc:   e16807cc        smulbt  r8, ip, r7
+ 200:   016a0ea3        smultbeq        sl, r3, lr
+ 204:   e1600de3        smultt  r0, r3, sp
+ 208:   e697a009        ldr     sl, [r7], r9
+ 20c:   e5d900c4        ldrb    r0, [r9, #196]  ; 0xc4
+ 210:   e1b4e0b6        ldrh    lr, [r4, r6]!
+ 214:   e1f96ed8        ldrsb   r6, [r9, #232]! ; 0xe8
+ 218:   e09120f1        ldrsh   r2, [r1], r1
+ 21c:   e6890004        str     r0, [r9], r4
+ 220:   e5e5305c        strb    r3, [r5, #92]!  ; 0x5c
+ 224:   e1c82ab0        strh    r2, [r8, #160]  ; 0xa0
+ 228:   e79c8008        ldr     r8, [ip, r8]
+ 22c:   e4dab010        ldrb    fp, [sl], #16
+ 230:   e19ab0b6        ldrh    fp, [sl, r6]
+ 234:   e1bb50da        ldrsb   r5, [fp, sl]!
+ 238:   e19360f7        ldrsh   r6, [r3, r7]
+ 23c:   e7ad7005        str     r7, [sp, r5]!
+ 240:   e5ca2000        strb    r2, [sl]
+ 244:   e08460b3        strh    r6, [r4], r3
+ 248:   e59ca000        ldr     sl, [ip]
+ 24c:   e4db4084        ldrb    r4, [fp], #132  ; 0x84
+ 250:   e09990bc        ldrh    r9, [r9], ip
+ 254:   e0d399d4        ldrsb   r9, [r3], #148  ; 0x94
+ 258:   e1f2b9f4        ldrsh   fp, [r2, #148]! ; 0x94
+ 25c:   e78db00b        str     fp, [sp, fp]
+ 260:   e7cd100a        strb    r1, [sp, sl]
+ 264:   e08ea0b9        strh    sl, [lr], r9
+ 268:   e7b36004        ldr     r6, [r3, r4]!
+ 26c:   e7f6400d        ldrb    r4, [r6, sp]!
+ 270:   e09760ba        ldrh    r6, [r7], sl
+ 274:   e1b600db        ldrsb   r0, [r6, fp]!
+ 278:   e096a0fd        ldrsh   sl, [r6], sp
+ 27c:   e783700c        str     r7, [r3, ip]
+ 280:   e7e83001        strb    r3, [r8, r1]!
+ 284:   e1cc44b0        strh    r4, [ip, #64]   ; 0x40
+
+00000288 <near>:
+ 288:   e51f1008        ldr     r1, [pc, #-8]   ; 288 <near>
+ 28c:   e55f7008        ldrb    r7, [pc, #-8]   ; 28c <near+0x4>
+ 290:   e15f21b0        ldrh    r2, [pc, #-16]  ; 288 <near>
+ 294:   e15fa0d8        ldrsb   sl, [pc, #-8]   ; 294 <near+0xc>
+ 298:   e1dfe3f8        ldrsh   lr, [pc, #56]   ; 2d8 <near_post>
+ 29c:   e51f2008        ldr     r2, [pc, #-8]   ; 29c <near+0x14>
+ 2a0:   e55f3008        ldrb    r3, [pc, #-8]   ; 2a0 <near+0x18>
+ 2a4:   e1df72bc        ldrh    r7, [pc, #44]   ; 2d8 <near_post>
+ 2a8:   e15fd0d8        ldrsb   sp, [pc, #-8]   ; 2a8 <near+0x20>
+ 2ac:   e15fa2fc        ldrsh   sl, [pc, #-44]  ; 288 <near>
+ 2b0:   e51f5008        ldr     r5, [pc, #-8]   ; 2b0 <near+0x28>
+ 2b4:   e5dfe01c        ldrb    lr, [pc, #28]   ; 2d8 <near_post>
+ 2b8:   e1df51b8        ldrh    r5, [pc, #24]   ; 2d8 <near_post>
+ 2bc:   e15f63dc        ldrsb   r6, [pc, #-60]  ; 288 <near>
+ 2c0:   e15fb4f0        ldrsh   fp, [pc, #-64]  ; 288 <near>
+ 2c4:   e59f700c        ldr     r7, [pc, #12]   ; 2d8 <near_post>
+ 2c8:   e5df5008        ldrb    r5, [pc, #8]    ; 2d8 <near_post>
+ 2cc:   e15fa4bc        ldrh    sl, [pc, #-76]  ; 288 <near>
+ 2d0:   e1df60d0        ldrsb   r6, [pc]        ; 2d8 <near_post>
+ 2d4:   e15f90f8        ldrsh   r9, [pc, #-8]   ; 2d4 <near+0x4c>
+
+000002d8 <near_post>:
+ 2d8:   e690036a        ldr     r0, [r0], sl, ror #6
+ 2dc:   e7d8348e        ldrb    r3, [r8, lr, lsl #9]
+ 2e0:   e78d5783        str     r5, [sp, r3, lsl #15]
+ 2e4:   e6c99145        strb    r9, [r9], r5, asr #2
+ 2e8:   e7945360        ldr     r5, [r4, r0, ror #6]
+ 2ec:   e7d0e4a4        ldrb    lr, [r0, r4, lsr #9]
+ 2f0:   e68c52cc        str     r5, [ip], ip, asr #5
+ 2f4:   e7e13667        strb    r3, [r1, r7, ror #12]!
+ 2f8:   e7b26063        ldr     r6, [r2, r3, rrx]!
+ 2fc:   e7fe8842        ldrb    r8, [lr, r2, asr #16]!
+ 300:   e7a363e6        str     r6, [r3, r6, ror #7]!
+ 304:   e7c83502        strb    r3, [r8, r2, lsl #10]
+ 308:   e79db40e        ldr     fp, [sp, lr, lsl #8]
+ 30c:   e7fda20c        ldrb    sl, [sp, ip, lsl #4]!
+ 310:   e789d142        str     sp, [r9, r2, asr #2]
+ 314:   e7eb774e        strb    r7, [fp, lr, asr #14]!
+ 318:   e19bcf9f        ldrex   r12, [fp]
+ 31c:   e1dc4f9f        ldrexb  r4, [ip]
+ 320:   e1fbbf9f        ldrexh  fp, [fp]
+ 324:   e18e1f97        strex   r1, r7, [lr]
+ 328:   e1c4cf96        strexb  ip, r6, [r4]
+ 32c:   21e74f96        strexhcs        r4, r6, [r7]
+ 330:   e6143f17        sadd16  r3, r4, r7
+ 334:   e61a9f33        sasx    r9, sl, r3
+ 338:   e615cf56        ssax    ip, r5, r6
+ 33c:   e615cf7e        ssub16  ip, r5, lr
+ 340:   e61a0f97        sadd8   r0, sl, r7
+ 344:   66180ff2        ssub8vs r0, r8, r2
+ 348:   5624bf15        qadd16pl        fp, r4, r5
+ 34c:   6623bf3c        qasxvs  fp, r3, ip
+ 350:   e6230f55        qsax    r0, r3, r5
+ 354:   e61caf75        ssub16  sl, ip, r5
+ 358:   3626af9e        qadd8cc sl, r6, lr
+ 35c:   e62baff7        qsub8   sl, fp, r7
+ 360:   56349f1e        shadd16pl       r9, r4, lr
+ 364:   e63e1f37        shasx   r1, lr, r7
+ 368:   363b9f55        shsaxcc r9, fp, r5
+ 36c:   a6313f7b        shsub16ge       r3, r1, fp
+ 370:   c635df97        shadd8gt        sp, r5, r7
+ 374:   e6351ff7        shsub8  r1, r5, r7
+ 378:   e654af17        uadd16  sl, r4, r7
+ 37c:   26591f37        uasxcs  r1, r9, r7
+ 380:   e65dbf57        usax    fp, sp, r7
+ 384:   e654bf7e        usub16  fp, r4, lr
+ 388:   365d2f97        uadd8cc r2, sp, r7
+ 38c:   c65a8ffe        usub8gt r8, sl, lr
+ 390:   e66c3f1d        uqadd16 r3, ip, sp
+ 394:   e66d4f36        uqasx   r4, sp, r6
+ 398:   e66a1f5e        uqsax   r1, sl, lr
+ 39c:   d66d2f7e        uqsub16le       r2, sp, lr
+ 3a0:   e66c1f95        uqadd8  r1, ip, r5
+ 3a4:   c6640ffd        uqsub8gt        r0, r4, sp
+ 3a8:   867a0f15        uhadd16hi       r0, sl, r5
+ 3ac:   d674bf37        uhasxle fp, r4, r7
+ 3b0:   a67e1f59        uhsaxge r1, lr, r9
+ 3b4:   e67b2f7e        uhsub16 r2, fp, lr
+ 3b8:   a6749f95        uhadd8ge        r9, r4, r5
+ 3bc:   867d2ffe        uhsub8hi        r2, sp, lr
+ 3c0:   e683a877        sxtab16 sl, r3, r7, ror #16
+ 3c4:   26a59c77        sxtabcs r9, r5, r7, ror #24
+ 3c8:   e6b53477        sxtah   r3, r5, r7, ror #8
+ 3cc:   e6c48476        uxtab16 r8, r4, r6, ror #8
+ 3d0:   06eb007d        uxtabeq r0, fp, sp
+ 3d4:   e6fc9075        uxtah   r9, ip, r5
+ 3d8:   a68f387b        sxtb16ge        r3, fp, ror #16
+ 3dc:   86af2076        sxtbhi  r2, r6
+ 3e0:   c6bf3c7d        sxthgt  r3, sp, ror #24
+ 3e4:   e6cfc875        uxtb16  ip, r5, ror #16
+ 3e8:   e6efc875        uxtb    ip, r5, ror #16
+ 3ec:   e6ff8875        uxth    r8, r5, ror #16
+ 3f0:   06bfaf34        reveq   sl, r4
+ 3f4:   a6bf8fbc        rev16ge r8, ip
+ 3f8:   e6ffef37        rbit    lr, r7
+ 3fc:   c6ffdfb7        revshgt sp, r7
+ 400:   e719fe1d        sdiv    r9, sp, lr
+ 404:   e732f61c        udiv    r2, ip, r6
+ 408:   47a20a51        sbfxmi  r0, r1, #20, #3
+ 40c:   e7ee9852        ubfx    r9, r2, #16, #15
+ 410:   87dd1d9b        bfihi   r1, fp, #27, #3
+ 414:   e7d0339f        bfc     r3, #7, #10
+ 418:   e8060d6b        stmda   r6, {r0, r1, r3, r5, r6, r8, sl, fp}
+ 41c:   e80438df        stmda   r4, {r0, r1, r2, r3, r4, r6, r7, fp, ip, sp}
+ 420:   e810e1d4        ldmda   r0, {r2, r4, r6, r7, r8, sp, lr, pc}
+ 424:   e83c9873        ldmda   ip!, {r0, r1, r4, r5, r6, fp, ip, pc}
+ 428:   e8a931bd        stmia   r9!, {r0, r2, r3, r4, r5, r7, r8, ip, sp}
+ 42c:   e88b55c3        stm     fp, {r0, r1, r6, r7, r8, sl, ip, lr}
+ 430:   e8bcbd22        ldm     ip!, {r1, r5, r8, sl, fp, ip, sp, pc}
+ 434:   e8bda10a        pop     {r1, r3, r8, sp, pc}
+ 438:   e92b2219        stmdb   fp!, {r0, r3, r4, r9, sp}
+ 43c:   e9298dd5        stmdb   r9!, {r0, r2, r4, r6, r7, r8, sl, fp, pc}
+ 440:   e935605b        ldmdb   r5!, {r0, r1, r3, r4, r6, sp, lr}
+ 444:   e91191a7        ldmdb   r1, {r0, r1, r2, r5, r7, r8, ip, pc}
+ 448:   e9ab6e6a        stmib   fp!, {r1, r3, r5, r6, r9, sl, fp, sp, lr}
+ 44c:   e98b4507        stmib   fp, {r0, r1, r2, r8, sl, lr}
+ 450:   e9b053cc        ldmib   r0!, {r2, r3, r6, r7, r8, r9, ip, lr}
+ 454:   e9912de7        ldmib   r1, {r0, r1, r2, r5, r6, r7, r8, sl, fp, sp}
+ 458:   2a000075        bcs     634 <forth>
+ 45c:   4bfffffe        blmi    45c <near_post+0x184>
+ 460:   612fff10        bxvs    r0
+ 464:   e12fff33        blx     r3
+ 468:   eafffffe        b       468 <near_post+0x190>
+ 46c:   ebfffffe        bl      46c <near_post+0x194>
+ 470:   612fff10        bxvs    r0
+ 474:   e12fff35        blx     r5
+ 478:   da00006d        ble     634 <forth>
+ 47c:   4bfffffe        blmi    47c <near_post+0x1a4>
+ 480:   112fff19        bxne    r9
+ 484:   e12fff3c        blx     ip
+ 488:   eafffedc        b       0 <back>
+ 48c:   8bfffffe        blhi    48c <near_post+0x1b4>
+ 490:   712fff11        bxvc    r1
+ 494:   c12fff37        blxgt   r7
+ 498:   aafffed8        bge     0 <back>
+ 49c:   8bfffffe        blhi    49c <near_post+0x1c4>
+ 4a0:   e12fff1c        bx      ip
+ 4a4:   312fff37        blxcc   r7
+ 4a8:   eafffffe        b       4a8 <near_post+0x1d0>
+ 4ac:   cbfffed3        blgt    0 <back>
+ 4b0:   a12fff11        bxge    r1
+ 4b4:   e12fff30        blx     r0
+ 4b8:   eafffffe        b       4b8 <near_post+0x1e0>
+ 4bc:   eb00005c        bl      634 <forth>
+ 4c0:   c12fff1e        bxgt    lr
+ 4c4:   112fff3b        blxne   fp
+ 4c8:   2afffffe        bcs     4c8 <near_post+0x1f0>
+ 4cc:   ebfffffe        bl      4cc <near_post+0x1f4>
+ 4d0:   212fff1a        bxcs    sl
+ 4d4:   e12fff34        blx     r4
+ 4d8:   eafffec8        b       0 <back>
+ 4dc:   ebfffffe        bl      4dc <near_post+0x204>
+ 4e0:   312fff1c        bxcc    ip
+ 4e4:   e12fff38        blx     r8
+ 4e8:   ea000051        b       634 <forth>
+ 4ec:   ebfffffe        bl      4ec <near_post+0x214>
+ 4f0:   e12fff1a        bx      sl
+ 4f4:   e12fff31        blx     r1
+ 4f8:   4e042a06        vmlami.f32      s4, s8, s12
+ 4fc:   ee052a45        vmls.f32        s4, s10, s10
+ 500:   ee151a46        vnmla.f32       s2, s10, s12
+ 504:   be134a04        vnmlslt.f32     s8, s6, s8
+ 508:   4e263a47        vnmulmi.f32     s6, s12, s14
+ 50c:   ee310a00        vadd.f32        s0, s2, s0
+ 510:   ee321a45        vsub.f32        s2, s4, s10
+ 514:   2e810a06        vdivcs.f32      s0, s2, s12
+ 518:   ee030b06        vmla.f64        d0, d3, d6
+ 51c:   ee010b45        vmls.f64        d0, d1, d5
+ 520:   ee141b46        vnmla.f64       d1, d4, d6
+ 524:   1e110b01        vnmlsne.f64     d0, d1, d1
+ 528:   1e253b45        vnmulne.f64     d3, d5, d5
+ 52c:   3e320b04        vaddcc.f64      d0, d2, d4
+ 530:   ee321b44        vsub.f64        d1, d2, d4
+ 534:   4e810b05        vdivmi.f64      d0, d1, d5
+ 538:   eeb03ac3        vabs.f32        s6, s6
+ 53c:   5eb13a44        vnegpl.f32      s6, s8
+ 540:   eeb10ac4        vsqrt.f32       s0, s8
+ 544:   eeb00bc4        vabs.f64        d0, d4
+ 548:   eeb11b44        vneg.f64        d1, d4
+ 54c:   eeb10bc1        vsqrt.f64       d0, d1
+ 550:   5e00ea10        vmovpl  s0, lr
+ 554:   ee14ba10        vmov    fp, s8
+ 558:   bc4ebb11        vmovlt  d1, fp, lr
+ 55c:   ec557b15        vmov    r7, r5, d5
+ 560:   eeb04a46        vmov.f32        s8, s12
+ 564:   8eb01b42        vmovhi.f64      d1, d2
+ 568:   6eb72a00        vmovvs.f32      s4, #112        ; 0x70
+ 56c:   eeb72b00        vmov.f64        d2, #112        ; 0x70
+ 570:   eeb03a00        vmov.f32        s6, #0
+ 574:   eeb01b00        vmov.f64        d1, #0
+ 578:   ed952a1d        vldr    s4, [r5, #116]  ; 0x74
+ 57c:   3d811a0e        vstrcc  s2, [r1, #56]   ; 0x38
+ 580:   1d957b04        vldrne  d7, [r5, #16]
+ 584:   ed816b39        vstr    d6, [r1, #228]  ; 0xe4
+
+00000588 <near_flt>:
+ 588:   ed9f1a0e        vldr    s2, [pc, #56]   ; 5c8 <near_post_flt>
+ 58c:   ed8f3a0d        vstr    s6, [pc, #52]   ; 5c8 <near_post_flt>
+ 590:   bd1f2b04        vldrlt  d2, [pc, #-16]  ; 588 <near_flt>
+ 594:   cd0f3b02        vstrgt  d3, [pc, #-8]   ; 594 <near_flt+0xc>
+ 598:   3d9f2a0a        vldrcc  s4, [pc, #40]   ; 5c8 <near_post_flt>
+ 59c:   ed8f0a09        vstr    s0, [pc, #36]   ; 5c8 <near_post_flt>
+ 5a0:   cd9f4b08        vldrgt  d4, [pc, #32]   ; 5c8 <near_post_flt>
+ 5a4:   ed0f0b09        vstr    d0, [pc, #-36]  ; 588 <near_flt>
+ 5a8:   ed9f4a06        vldr    s8, [pc, #24]   ; 5c8 <near_post_flt>
+ 5ac:   ed8f3a05        vstr    s6, [pc, #20]   ; 5c8 <near_post_flt>
+ 5b0:   5d1f4b0c        vldrpl  d4, [pc, #-48]  ; 588 <near_flt>
+ 5b4:   ed0f5b0d        vstr    d5, [pc, #-52]  ; 588 <near_flt>
+ 5b8:   9d9f4a02        vldrls  s8, [pc, #8]    ; 5c8 <near_post_flt>
+ 5bc:   3d0f6a02        vstrcc  s12, [pc, #-8]  ; 5bc <near_flt+0x34>
+ 5c0:   ed9f6b00        vldr    d6, [pc]        ; 5c8 <near_post_flt>
+ 5c4:   bd0f1b01        vstrlt  d1, [pc, #-4]   ; 5c8 <near_post_flt>
+
+000005c8 <near_post_flt>:
+ 5c8:   ec912a01        vldmia  r1, {s4}
+ 5cc:   2ca62a01        vstmiacs        r6!, {s4}
+ 5d0:   ecb91b08        vldmia  r9!, {d1-d4}
+ 5d4:   eca36b04        vstmia  r3!, {d6-d7}
+ 5d8:   6d323a01        vldmdbvs        r2!, {s6}
+ 5dc:   ed267a01        vstmdb  r6!, {s14}
+ 5e0:   ed3d4b08        vldmdb  sp!, {d4-d7}
+ 5e4:   ed205b06        vstmdb  r0!, {d5-d7}
+ 5e8:   eeb41a41        vcmp.f32        s2, s2
+ 5ec:   7eb44ac4        vcmpevc.f32     s8, s8
+ 5f0:   eeb40b46        vcmp.f64        d0, d6
+ 5f4:   aeb43bc7        vcmpege.f64     d3, d7
+ 5f8:   beb51a40        vcmplt.f32      s2, #0.0
+ 5fc:   ceb57ac0        vcmpegt.f32     s14, #0.0
+ 600:   eeb54b40        vcmp.f64        d4, #0.0
+ 604:   eeb51bc0        vcmpe.f64       d1, #0.0
+ 608:   6ebd1ac3        vcvtvs.s32.f32  s2, s6
+ 60c:   cebc3ac7        vcvtgt.u32.f32  s6, s14
+ 610:   3eb80ac1        vcvtcc.f32.s32  s0, s2
+ 614:   3eb81a42        vcvtcc.f32.u32  s2, s4
+ 618:   8ebd2bc4        vcvthi.s32.f64  s4, d4
+ 61c:   8ebc3bc6        vcvthi.u32.f64  s6, d6
+ 620:   9eb73bc7        vcvtls.f32.f64  s6, d7
+ 624:   eeb83bc4        vcvt.f64.s32    d3, s8
+ 628:   0eb85b47        vcvteq.f64.u32  d5, s14
+ 62c:   eeb74ac5        vcvt.f64.f32    d4, s10
+ 630:   e120017a        bkpt    0x001a
+ */
+
+  static const unsigned int insns[] =
+  {
+    0xe082852b,     0x009310c7,     0xe0290284,     0xc0329066,
+    0xc04c000e,     0x00528364,     0xe069818d,     0x60708864,
+    0xd08597a1,     0xe09d12c6,     0xc0adb0c7,     0xe0b80329,
+    0xe0c392e6,     0x80dd1845,     0x30e28486,     0xe0f4a76d,
+    0x118db785,     0xe19a9764,     0xe1cd90e5,     0xe1d20547,
+    0xe086d777,     0x809c4776,     0x90265c57,     0xe035841d,
+    0xe04c2055,     0x20539c17,     0xc06c9614,     0xe072811c,
+    0xe08c4d1d,     0xe09b8d76,     0x10a20415,     0xe0beb256,
+    0x80ca835e,     0xe0dc1615,     0x60e54a7e,     0xe0fc181d,
+    0x61818076,     0xe19db577,     0xe1ce4216,     0xe1dba31d,
+    0x828d8261,     0xe29ed69b,     0xe226e87d,     0xe2332f49,
+    0xe24d46d9,     0xb25e1402,     0xe2650325,     0x3274882f,
+    0xb2849102,     0xe2948902,     0x22aeac2a,     0xe2b6aabd,
+    0xe2cc2426,     0xe2da85a5,     0xe2e6d871,     0x12fba6e9,
+    0x638737ff,     0x03952951,     0x63c18eea,     0x33d2020a,
+    0xe118028d,     0xe13601a7,     0xe15c0164,     0xb1750807,
+    0xe112073e,     0x31300572,     0x915e0b37,     0x617a0b17,
+    0xe3120585,     0x433e071b,     0xe355030e,     0x3377010a,
+    0xe1a00b84,     0xe1b01484,     0xe1a001aa,     0xe1b00a2a,
+    0xe1a015c9,     0x61b0254b,     0x31a08fe2,     0xe1b0946c,
+    0xe1a0877e,     0xe1b0c473,     0xc1a0ce1d,     0xe1b0c61d,
+    0xc1a00931,     0xc1b0bc33,     0xd1a0265c,     0xb1b0165a,
+    0xe1a0a003,     0xe1b00009,     0x73a03e29,     0xe3b0497e,
+    0xe1a0c1a6,     0x71b0554d,     0xe1a0137e,     0x01b0897c,
+    0x330cbf31,     0x33429bf7,     0xd001059d,     0xe0100b9a,
+    0xe0207c93,     0x0038639b,     0xe084e695,     0xe0940796,
+    0xe0a08e9b,     0xe0b4b79e,     0x20c51796,     0x40db059c,
+    0xe0498592,     0x0060ed94,     0x510d9054,     0x4125005c,
+    0xe1473055,     0xe1649052,     0xe101658c,     0xe1006cca,
+    0xe108e3a1,     0xe10176ed,     0xe1206483,     0xe12b7ec4,
+    0xe14a0786,     0x914b3ec4,     0xe14b8ca3,     0xe14185e3,
+    0x21220dac,     0xe12806ec,     0xa1620e86,     0xe16807cc,
+    0x016a0ea3,     0xe1600de3,     0xe697a009,     0xe5d900c4,
+    0xe1b4e0b6,     0xe1f96ed8,     0xe09120f1,     0xe6890004,
+    0xe5e5305c,     0xe1c82ab0,     0xe79c8008,     0xe4dab010,
+    0xe19ab0b6,     0xe1bb50da,     0xe19360f7,     0xe7ad7005,
+    0xe5ca2000,     0xe08460b3,     0xe59ca000,     0xe4db4084,
+    0xe09990bc,     0xe0d399d4,     0xe1f2b9f4,     0xe78db00b,
+    0xe7cd100a,     0xe08ea0b9,     0xe7b36004,     0xe7f6400d,
+    0xe09760ba,     0xe1b600db,     0xe096a0fd,     0xe783700c,
+    0xe7e83001,     0xe1cc44b0,     0xe51f1008,     0xe55f7008,
+    0xe15f21b0,     0xe15fa0d8,     0xe1dfe3f8,     0xe51f2008,
+    0xe55f3008,     0xe1df72bc,     0xe15fd0d8,     0xe15fa2fc,
+    0xe51f5008,     0xe5dfe01c,     0xe1df51b8,     0xe15f63dc,
+    0xe15fb4f0,     0xe59f700c,     0xe5df5008,     0xe15fa4bc,
+    0xe1df60d0,     0xe15f90f8,     0xe690036a,     0xe7d8348e,
+    0xe78d5783,     0xe6c99145,     0xe7945360,     0xe7d0e4a4,
+    0xe68c52cc,     0xe7e13667,     0xe7b26063,     0xe7fe8842,
+    0xe7a363e6,     0xe7c83502,     0xe79db40e,     0xe7fda20c,
+    0xe789d142,     0xe7eb774e,     0xe19bcf9f,     0xe1dc4f9f,
+    0xe1fbbf9f,     0xe18e1f97,     0xe1c4cf96,     0x21e74f96,
+    0xe6143f17,     0xe61a9f33,     0xe615cf56,     0xe615cf7e,
+    0xe61a0f97,     0x66180ff2,     0x5624bf15,     0x6623bf3c,
+    0xe6230f55,     0xe61caf75,     0x3626af9e,     0xe62baff7,
+    0x56349f1e,     0xe63e1f37,     0x363b9f55,     0xa6313f7b,
+    0xc635df97,     0xe6351ff7,     0xe654af17,     0x26591f37,
+    0xe65dbf57,     0xe654bf7e,     0x365d2f97,     0xc65a8ffe,
+    0xe66c3f1d,     0xe66d4f36,     0xe66a1f5e,     0xd66d2f7e,
+    0xe66c1f95,     0xc6640ffd,     0x867a0f15,     0xd674bf37,
+    0xa67e1f59,     0xe67b2f7e,     0xa6749f95,     0x867d2ffe,
+    0xe683a877,     0x26a59c77,     0xe6b53477,     0xe6c48476,
+    0x06eb007d,     0xe6fc9075,     0xa68f387b,     0x86af2076,
+    0xc6bf3c7d,     0xe6cfc875,     0xe6efc875,     0xe6ff8875,
+    0x06bfaf34,     0xa6bf8fbc,     0xe6ffef37,     0xc6ffdfb7,
+    0xe719fe1d,     0xe732f61c,     0x47a20a51,     0xe7ee9852,
+    0x87dd1d9b,     0xe7d0339f,     0xe8060d6b,     0xe80438df,
+    0xe810e1d4,     0xe83c9873,     0xe8a931bd,     0xe88b55c3,
+    0xe8bcbd22,     0xe8bda10a,     0xe92b2219,     0xe9298dd5,
+    0xe935605b,     0xe91191a7,     0xe9ab6e6a,     0xe98b4507,
+    0xe9b053cc,     0xe9912de7,     0x2a000075,     0x4bfffffe,
+    0x612fff10,     0xe12fff33,     0xeafffffe,     0xebfffffe,
+    0x612fff10,     0xe12fff35,     0xda00006d,     0x4bfffffe,
+    0x112fff19,     0xe12fff3c,     0xeafffedc,     0x8bfffffe,
+    0x712fff11,     0xc12fff37,     0xaafffed8,     0x8bfffffe,
+    0xe12fff1c,     0x312fff37,     0xeafffffe,     0xcbfffed3,
+    0xa12fff11,     0xe12fff30,     0xeafffffe,     0xeb00005c,
+    0xc12fff1e,     0x112fff3b,     0x2afffffe,     0xebfffffe,
+    0x212fff1a,     0xe12fff34,     0xeafffec8,     0xebfffffe,
+    0x312fff1c,     0xe12fff38,     0xea000051,     0xebfffffe,
+    0xe12fff1a,     0xe12fff31,     0x4e042a06,     0xee052a45,
+    0xee151a46,     0xbe134a04,     0x4e263a47,     0xee310a00,
+    0xee321a45,     0x2e810a06,     0xee030b06,     0xee010b45,
+    0xee141b46,     0x1e110b01,     0x1e253b45,     0x3e320b04,
+    0xee321b44,     0x4e810b05,     0xeeb03ac3,     0x5eb13a44,
+    0xeeb10ac4,     0xeeb00bc4,     0xeeb11b44,     0xeeb10bc1,
+    0x5e00ea10,     0xee14ba10,     0xbc4ebb11,     0xec557b15,
+    0xeeb04a46,     0x8eb01b42,     0x6eb72a00,     0xeeb72b00,
+    0xeeb03a00,     0xeeb01b00,     0xed952a1d,     0x3d811a0e,
+    0x1d957b04,     0xed816b39,     0xed9f1a0e,     0xed8f3a0d,
+    0xbd1f2b04,     0xcd0f3b02,     0x3d9f2a0a,     0xed8f0a09,
+    0xcd9f4b08,     0xed0f0b09,     0xed9f4a06,     0xed8f3a05,
+    0x5d1f4b0c,     0xed0f5b0d,     0x9d9f4a02,     0x3d0f6a02,
+    0xed9f6b00,     0xbd0f1b01,     0xec912a01,     0x2ca62a01,
+    0xecb91b08,     0xeca36b04,     0x6d323a01,     0xed267a01,
+    0xed3d4b08,     0xed205b06,     0xeeb41a41,     0x7eb44ac4,
+    0xeeb40b46,     0xaeb43bc7,     0xbeb51a40,     0xceb57ac0,
+    0xeeb54b40,     0xeeb51bc0,     0x6ebd1ac3,     0xcebc3ac7,
+    0x3eb80ac1,     0x3eb81a42,     0x8ebd2bc4,     0x8ebc3bc6,
+    0x9eb73bc7,     0xeeb83bc4,     0x0eb85b47,     0xeeb74ac5,
+    0xe120017a,
+  };
+// END  Generated code -- do not edit
+  {
+    bool ok = true;
+    unsigned int *insns1 = (unsigned int *)entry;
+    for (unsigned int i = 0; i < sizeof insns / sizeof insns[0]; i++) {
+      if (insns[i] != insns1[i]) {
+        ok = false;
+        printf("Ours:\n");
+        Disassembler::decode((address)&insns1[i], (address)&insns1[i+1]);
+        printf("  Raw: 0x%x\n", insns1[i]);
+        printf("Theirs:\n");
+        Disassembler::decode((address)&insns[i], (address)&insns[i+1]);
+        printf("  Raw: 0x%x\n", insns[i]);
+        printf("\n");
+      }
+    }
+    assert(ok, "Assembler smoke test failed");
+  }
+
+#ifndef PRODUCT
+
+  //address PC = __ pc();
+  //__ ld1(v0, __ T16B, Address(r16)); // No offset
+  //__ ld1(v0, __ T16B, __ post(r16, 0)); // Post-index
+  //__ ld1(v0, __ T16B, Address(r16, r17)); //
+
+
+#endif // PRODUCT
+#endif // ASSERT
+}
+
+#undef __
+void Address::AddressConstruct(Register base, RegisterOrConstant index, enum reg_op op,
+                               shift_op shift, enum wb_mode mode) {
+  _base = base;
+  _wb_mode = mode;
+  _shift = shift;
+  _target = 0;
+  if (index.is_register()) {
+    _acc_mode = reg;
+    _index = index.as_register();
+    _offset = 0;
+    _as_op = op;
+  } else {
+    assert(shift == lsl(), "should be");
+    assert(index.is_constant(), "should be");
+    _acc_mode = imm;
+    // _index = no_reg;
+    _offset = index.as_constant();
+    if(SUB == _as_op)
+      _offset = -_offset;
+  }
+}
+
+void Address::encode(Instruction_aarch32 *i, CodeSection *sec, address pc) const {
+  long offset = _offset;
+  access_mode mode = _acc_mode;
+
+  if(lit == mode) {
+    //Create the offset from the address
+    offset = _target - pc;
+    mode = imm;
+  }
+
+  //Correct the offset if the base is the PC
+  if(r15_pc == _base && imm == mode) {
+    offset -= 8;
+  }
+
+  int U = (offset >= 0 && _acc_mode == imm) || (_as_op == ADD && _acc_mode == reg);
+  int P = pre == _wb_mode || off == _wb_mode;
+  int W = pre == _wb_mode;
+  i->f(P, 24), i->f(U, 23), i->f(W, 21), i->rf(_base, 16);
+
+  offset = offset < 0 ? -offset : offset;
+  int opc = i->get(27, 25);
+
+  if (imm == mode) {
+    switch(opc) {
+    case 0b010:
+      // LDR, LDRB
+      // STR, STRB
+      i->f(offset, 11, 0);
+      break;
+    case 0b000:
+      // LDRH, LDRSH, LDRSB, LDRD
+      // STRH, STRD
+      i->f(1, 22);
+      assert(offset < (1 << 8), "Offset larger than a byte");
+      i->f(offset & 0xF, 3, 0);
+      i->f(offset >> 4, 11, 8);
+      break;
+    default:
+      ShouldNotReachHere();
+    }
+  } else if (reg == mode) {
+    assert(r15_pc->encoding_nocheck() !=
+            _base->encoding_nocheck(), "Remove this if you have your offsets right");
+    switch(opc) {
+    case 0b010:
+      // LDR, LDRB
+      // STR, STRB
+      //Need to set bit 25 as Register 0b011
+      i->f(1, 25);
+      i->f(_shift.shift(), 11, 7);
+      i->f(_shift.kind(), 6, 5);
+      i->f(0, 4);
+      i->rf(_index, 0);
+      break;
+    case 0b000:
+      // LDRH, LDRSH, LDRSB, LDRD
+      // STRH, STRD
+      //Need to clear bit 22 as Register
+      i->f(0, 22);
+      assert(_shift == lsl(), "Type of load/store does not support shift");
+      i->f(0b0000, 11, 8);
+      i->rf(_index, 0);
+      break;
+    default:
+      ShouldNotReachHere();
+    }
+  } else {
+    ShouldNotReachHere();
+  }
+
+  if(lit == _acc_mode) {
+    sec->relocate(pc, _rspec);
+  }
+}
+
+void Address::fp_encode(Instruction_aarch32 *i, CodeSection *sec, address pc) const {
+  // ATM works only for immediate
+  assert(_wb_mode == off, "Can't do pre or post addressing for vldr, vstr");
+  long offset = _offset;
+  if(imm == _acc_mode) {
+    if(r15_pc == _base) {
+      //Correct the offset if the base is the PC
+      offset -= 8;
+    }
+    bool U = offset >= 0;
+    assert(0 == (offset & 3), "Can only access aligned data");
+    unsigned imm8 = uabs(offset) / 4;
+    i->f(U, 23), i->rf(_base, 16), i->f(imm8, 7, 0);
+  } else {
+    ShouldNotReachHere();
+  }
+}
+
+#define __ as->
+void Address::lea(MacroAssembler *as, Register r) const {
+  Relocation* reloc = _rspec.reloc();
+  relocInfo::relocType rtype = (relocInfo::relocType) reloc->type();
+
+  //TODO Potentially remove this - added as aarch64 doesn't contain
+  // any method of handling pre or post
+  assert( _wb_mode != pre && _wb_mode != post, "Wrong wb mode");
+  // could probably permit post however
+  switch(_acc_mode) {
+  case imm: {
+    if (_offset == 0 && _base == r) // it's a nop
+      break;
+    if (_offset > 0)
+      __ add(r, _base, _offset);
+    else
+      __ sub(r, _base, -_offset);
+      break;
+  }
+  case reg: {
+    __ add(r, _base, _index, _shift);
+    break;
+  }
+  case lit: {
+    if (rtype == relocInfo::none)
+      __ mov(r, target());
+    else
+      __ movptr(r, (u_int32_t)target());
+    break;
+  }
+  default:
+    ShouldNotReachHere();
+  }
+}
+#undef __
+
+bool Address::offset_ok_for_immed(long imm12) {
+  assert(false, "Size varies for instructions - answer inaccurate");
+  return imm12 >= 0 && imm12 < (1 << 12);
+}
+
+
+
+void Assembler::emit_data64(jlong data,
+                            relocInfo::relocType rtype,
+                            int format) {
+  if (rtype == relocInfo::none) {
+    emit_int64(data);
+  } else {
+    emit_data64(data, Relocation::spec_simple(rtype), format);
+  }
+}
+
+void Assembler::emit_data64(jlong data,
+                            RelocationHolder const& rspec,
+                            int format) {
+
+  assert(inst_mark() != NULL, "must be inside InstructionMark");
+  // Do not use AbstractAssembler::relocate, which is not intended for
+  // embedded words.  Instead, relocate to the enclosing instruction.
+  code_section()->relocate(inst_mark(), rspec, format);
+  emit_int64(data);
+}
+
+extern "C" {
+  void das(uint64_t start, int len) {
+    ResourceMark rm;
+    len <<= 2;
+    if (len < 0)
+      Disassembler::decode((address)start + len, (address)start);
+    else
+      Disassembler::decode((address)start, (address)start + len);
+  }
+
+  JNIEXPORT void das1(unsigned long insn) {
+    das(insn, 1);
+  }
+}
+
+#define starti Instruction_aarch32 do_not_use(this); set_current(&do_not_use)
+
+  void Assembler::adr(Register Rd, address adr, Condition cond) {
+    int offset = adr - pc();
+    adr_encode(Rd, offset, cond);
+  }
+
+#undef starti
+
+Address::Address(address target, relocInfo::relocType rtype)
+  : _acc_mode(lit), _base(sp), _offset(0), _wb_mode(off) {
+  //TODO we don't complete _wb_mode - what about Addresses that are pre/post accessed?
+  _is_lval = false;
+  _target = target;
+  switch (rtype) {
+  case relocInfo::oop_type:
+  case relocInfo::metadata_type:
+    // Oops are a special case. Normally they would be their own section
+    // but in cases like icBuffer they are literals in the code stream that
+    // we don't have a section for. We use none so that we get a literal address
+    // which is always patchable.
+    break;
+  case relocInfo::external_word_type:
+    _rspec = external_word_Relocation::spec(target);
+    break;
+  case relocInfo::internal_word_type:
+    _rspec = internal_word_Relocation::spec(target);
+    break;
+  case relocInfo::opt_virtual_call_type:
+    _rspec = opt_virtual_call_Relocation::spec();
+    break;
+  case relocInfo::static_call_type:
+    _rspec = static_call_Relocation::spec();
+    break;
+  case relocInfo::runtime_call_type:
+    _rspec = runtime_call_Relocation::spec();
+    break;
+  case relocInfo::poll_type:
+  case relocInfo::poll_return_type:
+    _rspec = Relocation::spec_simple(rtype);
+    break;
+  case relocInfo::none:
+    _rspec = RelocationHolder::none;
+    break;
+  default:
+    ShouldNotReachHere();
+    break;
+  }
+}
+
+void Assembler::adr(Register r, const Address &dest, Condition cond) {
+  code_section()->relocate(pc(), dest.rspec());
+  adr(r, dest.target());
+}
+
+void Assembler::wrap_label(Label &L, Assembler::uncond_branch_insn insn) {
+  if (L.is_bound()) {
+    (this->*insn)(target(L));
+  } else {
+    L.add_patch_at(code(), locator());
+    (this->*insn)(pc());
+  }
+}
+void Assembler::wrap_label(Label &L, Condition cond,
+                           Assembler::cond_branch_insn insn) {
+  if (L.is_bound()) {
+    (this->*insn)(target(L), cond);
+  } else {
+    L.add_patch_at(code(), locator());
+    (this->*insn)(pc(), cond);
+  }
+}
+
+void Assembler::wrap_label(Register r, Label &L, Condition cond,
+                           Assembler::cond_ldst_insn insn) {
+  if (L.is_bound()) {
+    (this->*insn)(r, target(L), cond);
+  } else {
+    L.add_patch_at(code(), locator());
+    (this->*insn)(r, pc(), cond);
+  }
+}
+
+void Assembler::wrap_label(FloatRegister r, Label &L, Condition cond,
+                           Assembler::cond_fp_ldst_insn insn) {
+  if (L.is_bound()) {
+    (this->*insn)(r, target(L), cond);
+  } else {
+    L.add_patch_at(code(), locator());
+    (this->*insn)(r, pc(), cond);
+  }
+}
+
+bool Assembler::operand_valid_for_add_sub_immediate(long imm) {
+  return operand_valid_immediate12(imm) ||
+         operand_valid_immediate12(-imm);
+}
+
+bool Assembler::operand_valid_for_mov_immediate(u_int32_t imm, bool s) {
+  bool vi12 = operand_valid_immediate12(imm);
+  return (s && vi12) || (!s && !(imm >> 16));
+}
+
+
+// n.b. this is implemented in subclass MacroAssembler
+void Assembler::bang_stack_with_offset(int offset) { Unimplemented(); }
+
+int AbstractAssembler::code_fill_byte() {
+  return 0;
+}
+
+bool Assembler::operand_valid_immediate12(int imm) {
+  //Check that it can be formed through rotations.
+  return encode_immediate12(imm) != 0xffffffff;
+}
+
+u_int32_t Assembler::encode_immediate12(int imm) {
+  //Right rotatates in multiples of two
+  //Just trying the rotations out - probably a way to make this nicer.
+  int i;
+  u_int32_t imm32 = (u_int32_t)imm;
+  for(i = 0; i < 16; i++) {
+    if(0 == (0xffffff00 & imm32))
+      return i << 8 | imm32;
+    //Left rotate by 2 (instruction rotates right)
+    imm32 = (imm32 << 2) | (imm32 >> 30);
+  }
+  return 0xffffffff;
+}
+
+u_int32_t Assembler::decode_immediate12(int imm) {
+  int rotation = (imm >> 7) & 1;
+  u_int32_t imm32 = imm;
+  return imm32 >> rotation | imm32 << (32 - rotation);
+}
+
+void Assembler::mov_immediate(Register dst, uint32_t imm32, Condition cond, bool s) {
+#ifndef PRODUCT
+    {
+      char buffer[64];
+      snprintf(buffer, sizeof(buffer), "0x%"PRIX32, imm32);
+      block_comment(buffer);
+    }
+#endif
+  if(operand_valid_immediate12(imm32)) {
+    if(s) movs_i(dst, (unsigned)imm32, cond);
+    else  mov_i (dst, (unsigned)imm32, cond);
+  } else if(operand_valid_immediate12(~imm32)) {
+    if(s) mvns_i(dst, (unsigned)~imm32, cond);
+    else  mvn_i (dst, (unsigned)~imm32, cond);
+  } else if (!s && VM_Version::features() & (FT_ARMV7 | FT_ARMV6T2) &&
+             (imm32 < (1 << 16))) {
+    movw_i(dst, (unsigned)imm32, cond);
+  } else if (!s && VM_Version::features() & (FT_ARMV7 | FT_ARMV6T2) &&
+             !(imm32 & ((1 << 16) - 1))) {
+    movt_i(dst, (unsigned)(imm32 >> 16), cond);
+  } else { // TODO Could expand to varied numbers of mov and orrs
+    //Need to do a full 32 bits
+    mov_immediate32(dst, imm32, cond, s);
+  }
+}
+
+//This should really be in the macroassembler
+void Assembler::mov_immediate32(Register dst, u_int32_t imm32, Condition cond, bool s)
+{
+        // Need to move a full 32 bit immediate, for example if we're loading an address that
+        // might change later and therefore need to be updated.
+  if (VM_Version::features() & (FT_ARMV7 | FT_ARMV6T2))  {
+    //Use a movw and a movt
+    Assembler::movw_i(dst, (unsigned)(imm32 & 0xffff), cond);
+    Assembler::movt_i(dst, (unsigned)(imm32 >> 16), cond);
+    if(s) {
+      //Additionally emit a cmp instruction
+      Assembler::cmp(dst, 0);
+    }
+  } else {
+        // Sadly we don't have movw, movt
+        // instead emit a mov and three orr
+        mov_i(dst,    imm32 & (0xff      ), cond);
+        orr(dst, dst, imm32 & (0xff << 8 ), cond);
+        orr(dst, dst, imm32 & (0xff << 16), cond);
+        if(s) orrs(dst, dst, imm32 & (0xff << 24), cond);
+        else  orr (dst, dst, imm32 & (0xff << 24), cond);
+  }
+}
+
+#define starti Instruction_aarch32 do_not_use(this); set_current(&do_not_use)
+void Assembler::add_sub_imm(int decode, Register Rd, Register Rn, int imm,
+                            Condition cond, bool s) {
+  int cpart;
+  switch(decode) {
+    case 0b0100: cpart = 0b0010; break; // ADD  ->  SUB
+    case 0b0010:                        // SUB  ->  ADD
+    case 0b0011: cpart = 0b0100; break; // RSB  ->  ADD
+    case 0b0101: cpart = 0b0110; break; // ADC  ->  SUBC
+    case 0b0110:                        // SUBC ->  ADC
+    case 0b0111: cpart = 0b0101; break; // RSC  ->  ADC
+    default: ShouldNotReachHere();
+  }
+  //try both possible imm_instrs
+  if(imm_instr(decode, Rd, Rn, imm, cond, s)) return;
+  if(imm_instr(cpart, Rd, Rn, -imm, cond, s)) return;
+
+  //Try plan B - a mov first - need to have destination that is not an arg
+  assert(Rd != Rn, "Can't use imm and can't do a mov. I'm in a jam.");
+  mov_immediate(Rd, (u_int32_t)uabs(imm), cond, s);
+  //Now do the non immediate version - copied from the immediate encodings
+  {
+    starti;
+    reg_instr( imm < 0 ? cpart : decode, lsl(), cond, s);
+    rf(Rn, 16), rf(Rd, 12), rf(Rd, 0);
+  }
+}
+
+void Assembler::vmov_imm(FloatRegister Rd, unsigned imm, bool is64bit,
+                         Condition cond) {
+  starti;
+  fp_instr_base(is64bit, cond);
+  f(0b1011, 23, 20);
+  fp_rencode(Rd, is64bit, 12, 22);
+  f(0b0000, 7, 4);
+  f(imm & 0xf, 3, 0);
+  f(imm >> 4, 19, 16);
+}
+
+void Assembler::vmov_imm_zero(FloatRegister Rd, bool is64bit,
+                              Condition cond) {
+  // Note that this is not a floating point vmov but instead
+  // an integer vmov from the SIMD instructions.
+  // cannot be conditional.
+  assert(cond == C_DFLT, "Unable to vmov #0 conditionally");
+  int cmod = is64bit? 0b1110 : 0b0000; // ? I64 : I32
+  {
+    starti;
+    f(0b1111001, 31, 25);
+    f(0, 24); // imm1
+    f(0b10000, 23, 19);
+    fp_rencode(Rd, is64bit, 12, 22);
+    f(0b000, 18, 16); //imm3
+    f(cmod, 11, 8);
+    f(0b00, 7, 6);
+    f(is64bit, 5);
+    f(1, 4);
+    f(0b0000, 3, 0); //imm4
+  }
+}
+
+unsigned Assembler::encode_float_fp_imm(float imm_f) {
+  union ufloat {
+    float f;
+    uint32_t u;
+  } imm;
+  unsigned tmp, imm8;
+  imm.f = imm_f;
+
+  assert(!(imm.u & ((1 << 19) - 1)), "Invalid float imm");
+  tmp = (imm.u >> 25) & ((1 << 6) - 1);
+  assert(tmp == 32 || tmp == 31, "Invalid float imm");
+
+  imm8 = (imm.u >> 24) & 0x80; // set a
+  imm8 |= (imm.u >> 19) & 0x7F; // set bcdefgh
+  return imm8;
+}
+
+unsigned Assembler::encode_double_fp_imm(double imm_f) {
+  union ufloat {
+    double f;
+    uint64_t u;
+  } imm;
+  unsigned tmp, imm8;
+  imm.f = imm_f;
+
+  assert(!(imm.u & (uint64_t)0xffffffffffffLL), "Invalid float imm");
+  imm.u >>= 48;
+
+  tmp = (imm.u >> 6) & ((1 << 9) - 1);
+  assert(tmp == 0x100 || tmp == 0xff, "Invalid float imm");
+
+  imm8 = (imm.u >> 8) & 0x80; // set a
+  imm8 |= imm.u & 0x7F; // set bcdefgh
+  return imm8;
+}
+
+unsigned Assembler::count_bits(unsigned val) {
+  unsigned i, count;
+  for(i = 0, count = 0; i < 8 * sizeof(val); val >>= 1, i++)
+    if( val & 1 ) count++;
+  return count;
+}
+bool Assembler::can_ldst_multiple( unsigned regset, const Address& adr) {
+  int nbits = count_bits(regset);
+  return adr.get_mode() == Address::imm &&
+         !(adr.base()->bit() & regset) && // FIXME, this could be relaxed
+         (((adr.offset() == 0 || adr.offset() == wordSize || adr.offset() == -nbits * wordSize) &&
+           (adr.get_wb_mode() == Address::pre || adr.get_wb_mode() == Address::off)) ||
+          ((adr.offset() == 0 || adr.offset() == -wordSize || adr.offset() == nbits * wordSize) &&
+           adr.get_wb_mode() == Address::post));
+}
+
+void Assembler::double_ldst_failed_dispatch(Register Rt, Register Rt2, const Address& adr,
+                                            void (Assembler::* mul)(unsigned, const Address&, Condition),
+                                            void (Assembler::* sgl)(Register, const Address&, Condition),
+                                            Condition cond) {
+  if(can_ldst_multiple(RegSet::of(Rt, Rt2).bits(), adr) &&
+     (Rt->encoding_nocheck() < Rt2->encoding_nocheck())) {
+    /* Do a load or store multiple instruction */
+    (this->*mul)(RegSet::of(Rt, Rt2).bits(), adr, cond);
+  } else if(adr.get_wb_mode() == Address::pre) {
+    (this->*sgl)(Rt, adr, cond);
+    (this->*sgl)(Rt2, Address(adr.base(), wordSize), cond);
+  } else if(adr.get_wb_mode() == Address::post) {
+    (this->*sgl)(Rt, adr, cond);
+    (this->*sgl)(Rt2, Address(adr.base(), wordSize - adr.offset()), cond);
+  } else if(adr.get_wb_mode() == Address::off) {
+    (this->*sgl)(Rt, adr, cond);
+    (this->*sgl)(Rt2, Address(adr.base(), adr.offset() + wordSize), cond);
+  } else {
+    ShouldNotReachHere();
+  }
+}
+
+void Assembler::fp_ldst_instr(int decode, bool is64bit, const Address& adr,
+                              Condition cond) {
+  f(cond, 31, 28), f(0b110, 27, 25), f(decode, 24, 20);
+  f(0b101, 11, 9), f(is64bit, 8);
+  adr.fp_encode(current, code_section(), pc());
+}
+
+void Assembler::fp_ldst_mul(Register Rn, int regset, bool load, bool is64bit,
+                            enum fp_mode mode, Condition cond) {
+  assert(is64bit || (1 == count_bits(regset)),
+         "Due to non contiguous single precision registers (could be fixed) "
+         "and fpldstm contiguous registers requirement, only a single "
+         "register is permitted in single-precision mode.");
+  starti;
+  bool P = db_wb == mode;
+  bool U = ia_wb == mode || ia == mode;
+  bool W = ia_wb == mode || db_wb == mode;
+  // Encode registers
+  unsigned i, fp_first_reg, nregs = 1;
+  bool enc_z = false;
+  for(fp_first_reg = 0; !(regset & 1); regset >>= 1, fp_first_reg++);
+  FloatRegister Rd = (FloatRegister) fp_first_reg;
+  for(i = 0; i + fp_first_reg < 8 * sizeof(int); i++) {
+    regset >>= 1;
+    if(regset & 1) {
+      assert(!enc_z, "Unable to encode non-consecutive registers in fp_ldst_mul");
+      nregs++;
+    } else {
+      enc_z = true;
+    }
+  }
+  // Disable multiple store for single precsion, see note below
+  assert(is64bit || (1 == nregs), "Single precision fp_ldst_mul only operates on one register");
+
+  if(is64bit) nregs *= 2;
+  f(cond, 31, 28), f(0b110, 27, 25); f(P, 24), f(U, 23), f(W, 21), f(load, 20);
+  rf(Rn, 16), fp_rencode(Rd, is64bit, 12, 22), f(0b101, 11, 9), f(is64bit, 8);
+  f(nregs, 7, 0);
+}
+
+#undef starti
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/assembler_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,1958 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_ASSEMBLER_AARCH32_HPP
+#define CPU_AARCH32_VM_ASSEMBLER_AARCH32_HPP
+
+#include "asm/register.hpp"
+
+// definitions of various symbolic names for machine registers
+
+// First intercalls between C and Java which use 8 general registers
+// and 8 floating registers
+
+// we also have to copy between x86 and ARM registers but that's a
+// secondary complication -- not all code employing C call convention
+// executes as x86 code though -- we generate some of it
+
+
+/* Calling conventions : this is perhaps not always what is wanted however currently all
+  JNI code needs to use the same calling convention as OpenJDK */
+
+class Argument VALUE_OBJ_CLASS_SPEC {
+ public:
+  enum {
+        n_int_register_parameters_c   = 4,  // r0, r1, ... r3 (c_rarg0, c_rarg1, ...)
+        // These are number of double registers, each double register can instead be
+        // used as two single precision registers.
+        #ifdef __VFP_FP__
+                n_float_register_parameters_c = 8,  // d0, d1, ... d7 (c_farg0, c_farg1, ... )
+                #define HARD_FLOAT_CC
+        #elif defined(__SOFTFP__)
+                n_float_register_parameters_c = 0,  // Not realy used, in this case
+                // pass_float -> pass_int & pass_double -> pass_long
+                #else
+                #error "Floating point ABI not supported";
+                #endif
+
+    // Not that these only make sense for compiled
+                // value are irrelevant currently, if c1, c2, ... will go ahead these need to be
+                // sorted out.
+    n_int_register_parameters_j   = 4, // r1, ... r7, r0 (rj_rarg0, j_rarg1, ...
+    n_float_register_parameters_j = 4  // d0, d1, ... d7 (j_farg0, j_farg1, ...
+  };
+};
+
+REGISTER_DECLARATION(Register, c_rarg0, r0);
+REGISTER_DECLARATION(Register, c_rarg1, r1);
+REGISTER_DECLARATION(Register, c_rarg2, r2);
+REGISTER_DECLARATION(Register, c_rarg3, r3);
+
+REGISTER_DECLARATION(FloatRegister, c_farg0, d0);
+REGISTER_DECLARATION(FloatRegister, c_farg1, d1);
+REGISTER_DECLARATION(FloatRegister, c_farg2, d2);
+REGISTER_DECLARATION(FloatRegister, c_farg3, d3);
+REGISTER_DECLARATION(FloatRegister, c_farg4, d4);
+REGISTER_DECLARATION(FloatRegister, c_farg5, d5);
+REGISTER_DECLARATION(FloatRegister, c_farg6, d6);
+REGISTER_DECLARATION(FloatRegister, c_farg7, d7);
+
+// Symbolically name the register arguments used by the Java calling convention.
+// We have control over the convention for java so we can do what we please.
+// What pleases us is to offset the java calling convention so that when
+// we call a suitable jni method the arguments are lined up and we don't
+// have to do much shuffling. A suitable jni method is non-static and a
+// small number of arguments
+//
+//  |-----------------------------------|
+//  | c_rarg0  c_rarg1  c_rarg2 c_rarg3 |
+//  |-----------------------------------|
+//  | r0       r1       r2      r3      |
+//  |-----------------------------------|
+//  | j_rarg3  j_rarg0  j_rarg1 j_rarg2 |
+//  |-----------------------------------|
+
+
+REGISTER_DECLARATION(Register, j_rarg0, c_rarg1);
+REGISTER_DECLARATION(Register, j_rarg1, c_rarg2);
+REGISTER_DECLARATION(Register, j_rarg2, c_rarg3);
+REGISTER_DECLARATION(Register, j_rarg3, c_rarg0);
+
+// Java floating args are passed as per C
+
+REGISTER_DECLARATION(FloatRegister, j_farg0, d0);
+REGISTER_DECLARATION(FloatRegister, j_farg1, d1);
+REGISTER_DECLARATION(FloatRegister, j_farg2, d2);
+REGISTER_DECLARATION(FloatRegister, j_farg3, d3);
+REGISTER_DECLARATION(FloatRegister, j_farg4, d4);
+REGISTER_DECLARATION(FloatRegister, j_farg5, d5);
+REGISTER_DECLARATION(FloatRegister, j_farg6, d6);
+REGISTER_DECLARATION(FloatRegister, j_farg7, d7);
+
+// registers used to hold VM data either temporarily within a method
+// or across method calls
+// non-volatile (callee-save) registers are r4-r11,r13,r14
+// of which the following are dedicated global state
+
+//Program counter
+REGISTER_DECLARATION(Register, r15_pc,    r15);
+// link register
+REGISTER_DECLARATION(Register, lr,        r14);
+// Java stack pointer
+REGISTER_DECLARATION(Register, sp,        r13);
+//TODO REMOVE THIS AND REPLACE ALL OCCURANCES
+// WITH JUST SP
+REGISTER_DECLARATION(Register, esp,       r13);
+//r4 & r5 are callee saved but used as scratch registers
+REGISTER_DECLARATION(Register, rscratch2, r12);
+REGISTER_DECLARATION(Register, rscratch1, r9); //NOTE this is not actually a scratch register!
+// current method -- must be in a call-clobbered register
+//Potentially FIXME - it's not!
+REGISTER_DECLARATION(Register, rmethod,   r10);
+// frame pointer
+REGISTER_DECLARATION(Register, rfp,    r11);
+// current thread
+REGISTER_DECLARATION(Register, rthread,   r8);
+// constant pool cache
+REGISTER_DECLARATION(Register, rcpool,       r7);
+// locals on stack
+REGISTER_DECLARATION(Register, rlocals,   r6);
+// bytecode pointer
+REGISTER_DECLARATION(Register, rbcp,      r5);
+// Dispatch table base
+REGISTER_DECLARATION(Register, rdispatch, r4);
+
+
+extern "C" void entry(CodeBuffer *cb);
+
+
+#define assert_cond(ARG1) assert(ARG1, #ARG1)
+
+namespace asm_util {
+  uint32_t encode_logical_immediate(bool is32, uint64_t imm);
+};
+
+using namespace asm_util;
+
+
+class Assembler;
+
+class Instruction_aarch32 {
+  unsigned insn;
+#ifdef ASSERT
+  unsigned bits;
+#endif
+  Assembler *assem;
+
+public:
+
+  Instruction_aarch32(class Assembler *as) {
+#ifdef ASSERT
+    bits = 0;
+#endif
+    insn = 0;
+    assem = as;
+  }
+
+  inline ~Instruction_aarch32();
+
+  unsigned &get_insn() { return insn; }
+#ifdef ASSERT
+  unsigned &get_bits() { return bits; }
+#endif
+
+  static inline int32_t extend(unsigned val, int hi = 31, int lo = 0) {
+    union {
+      unsigned u;
+      int n;
+    };
+
+    u = val << (31 - hi);
+    n = n >> (31 - hi + lo);
+    return n;
+  }
+
+  static inline uint32_t extract(uint32_t val, int msb, int lsb) {
+    int nbits = msb - lsb + 1;
+    assert_cond(msb >= lsb);
+    uint32_t mask = (1U << nbits) - 1;
+    uint32_t result = val >> lsb;
+    result &= mask;
+    return result;
+  }
+
+  static inline int32_t sextract(uint32_t val, int msb, int lsb) {
+    uint32_t uval = extract(val, msb, lsb);
+    return extend(uval, msb - lsb);
+  }
+
+  static void patch(address a, int msb, int lsb, unsigned long val) {
+    int nbits = msb - lsb + 1;
+    guarantee(val < (1U << nbits), "Field too big for insn");
+    assert_cond(msb >= lsb);
+    unsigned mask = (1U << nbits) - 1;
+    val <<= lsb;
+    mask <<= lsb;
+    unsigned target = *(unsigned *)a;
+    target &= ~mask;
+    target |= val;
+    *(unsigned *)a = target;
+  }
+
+  static void spatch(address a, int msb, int lsb, long val) {
+    int nbits = msb - lsb + 1;
+    long chk = val >> (nbits - 1);
+    guarantee (chk == -1 || chk == 0, "Field too big for insn");
+    unsigned uval = val;
+    unsigned mask = (1U << nbits) - 1;
+    uval &= mask;
+    uval <<= lsb;
+    mask <<= lsb;
+    unsigned target = *(unsigned *)a;
+    target &= ~mask;
+    target |= uval;
+    *(unsigned *)a = target;
+  }
+
+/*  void f(unsigned val, int msb, int lsb) {
+    int nbits = msb - lsb + 1;
+    guarantee(val < (1U << nbits), "Field too big for insn");
+    assert_cond(msb >= lsb);
+    unsigned mask = (1U << nbits) - 1;
+    val <<= lsb;
+    mask <<= lsb;
+    insn |= val;
+    assert_cond((bits & mask) == 0);
+#ifdef ASSERT
+    bits |= mask;
+#endif
+  }*/
+
+  void f(unsigned val, int msb, int lsb) {
+    int nbits = msb - lsb + 1;
+    guarantee(val < (1U << nbits), "Field too big for insn");
+    assert_cond(msb >= lsb);
+    unsigned mask = (1U << nbits) - 1;
+    val <<= lsb;
+    mask <<= lsb;
+    insn &= ~mask;
+    insn |= val;
+#ifdef ASSERT
+    bits |= mask;
+#endif
+  }
+
+  void f(unsigned val, int bit) {
+    f(val, bit, bit);
+  }
+
+  void sf(long val, int msb, int lsb) {
+    int nbits = msb - lsb + 1;
+    long chk = val >> (nbits - 1);
+    guarantee (chk == -1 || chk == 0, "Field too big for insn");
+    unsigned uval = val;
+    unsigned mask = (1U << nbits) - 1;
+    uval &= mask;
+    f(uval, lsb + nbits - 1, lsb);
+  }
+
+  void rf(Register r, int lsb) {
+    f(r->encoding_nocheck(), lsb + 3, lsb);
+  }
+
+  void rf(FloatRegister r, int lsb) {
+    f(r->encoding_nocheck(), lsb + 4, lsb);
+  }
+
+  unsigned get(int msb = 31, int lsb = 0) {
+    int nbits = msb - lsb + 1;
+    unsigned mask = ((1U << nbits) - 1) << lsb;
+    assert_cond((bits & mask) == mask);
+    return (insn & mask) >> lsb;
+  }
+
+  void fixed(unsigned value, unsigned mask) {
+    assert_cond ((mask & bits) == 0);
+#ifdef ASSERT
+    bits |= mask;
+#endif
+    insn |= value;
+  }
+};
+
+#define starti Instruction_aarch32 do_not_use(this); set_current(&do_not_use)
+
+// abs methods which cannot overflow and so are well-defined across
+// the entire domain of integer types.
+static inline unsigned int uabs(unsigned int n) {
+  union {
+    unsigned int result;
+    int value;
+  };
+  result = n;
+  if (value < 0) result = -result;
+  return result;
+}
+static inline unsigned long uabs(unsigned long n) {
+  union {
+    unsigned long result;
+    long value;
+  };
+  result = n;
+  if (value < 0) result = -result;
+  return result;
+}
+static inline unsigned long uabs(long n) { return uabs((unsigned long)n); }
+static inline unsigned long uabs(int n) { return uabs((unsigned int)n); }
+
+#define S_DFLT ::lsl()
+#define C_DFLT AL
+
+
+// Shift for base reg + reg offset addressing
+class shift_op {
+ public:
+  enum shift_kind { LSL, LSR, ASR, ROR };
+ private:
+  enum shift_source { imm_s, reg_s };
+  enum shift_source _source;
+  enum shift_kind _op;
+  int _shift;
+  Register _reg;
+
+  bool check_valid() {
+    if(imm_s == _source) {
+      switch(_op) {
+        case LSL: return _shift >= 0 && _shift <= 31;
+        case ROR: return _shift >= 1 && _shift <= 32;
+        default:  return _shift >= 1 && _shift <= 32;
+      }
+    }
+    return true; //Don't check register shifts
+  }
+ public:
+  // Default shift is lsl(0)
+  shift_op()
+    : _source(imm_s), _op(LSL), _shift(0) { }
+  shift_op(enum shift_kind op, int shift)
+    : _source(imm_s), _op(op), _shift(shift) {
+    if(!shift) {
+      // All zero shift encodings map to LSL 0
+      _shift = 0;
+      _op = LSL;
+    }
+    int pshift = _shift;
+    if(-1 == _shift && ROR == _op) {
+      // This is an RRX, make shift valid for the check
+      _shift = 1;
+      pshift = 0; //set to zero
+    }
+    assert(check_valid(), "Invalid shift quantity");
+    _shift = pshift; //restore shift
+  }
+  shift_op(enum shift_kind op, Register r)
+    : _source(reg_s), _op(op), _reg(r) {}
+
+  shift_kind kind() const {
+    return _op;
+  }
+
+  int shift() const {
+    assert(imm_s == _source, "Not an immediate shift");
+    return _shift;
+  }
+  Register reg() const {
+    assert(reg_s == _source, "Not a register shift");
+    return _reg;
+  }
+  bool is_register() {
+    return reg_s == _source;
+  }
+  bool operator==(const shift_op& other) const {
+    if(imm_s == _source && imm_s == other._source) {
+      return _op == other._op && _shift == other._shift;
+    } else if (reg_s == _source && imm_s == _source) {
+      return _op == other._op && _reg == other._reg;
+    }
+    return false;
+  }
+  bool operator!=(const shift_op& other) const {
+    return !( *this == other);
+  }
+};
+class lsl : public shift_op {
+ public:
+  lsl(int sft = 0): shift_op(LSL, sft) { }
+  lsl(Register r): shift_op(LSL, r) { }
+};
+class lsr : public shift_op {
+ public:
+  lsr(int sft = 0): shift_op(LSR, sft) { }
+  lsr(Register r): shift_op(LSR, r) { }
+};
+class asr : public shift_op {
+ public:
+  asr(int sft = 0): shift_op(ASR, sft) { }
+  asr(Register r): shift_op(ASR, r) { }
+};
+class ror : public shift_op {
+ public:
+  ror(int sft = 0): shift_op(ROR, sft) {}
+  ror(Register r): shift_op(ROR, r) { }
+};
+class rrx : public shift_op {
+ public:
+  rrx(): shift_op(ROR, -1) {}
+};
+
+
+// Addressing modes
+class Address VALUE_OBJ_CLASS_SPEC {
+ public:
+  enum access_mode { no_mode, imm, reg, lit };
+  //literal is class of imm? -> potentially have to split later if some instructions work
+  // with one but not other although can be determined from registers.
+  enum wb_mode { off, pre, post };
+
+  enum reg_op { ADD, SUB };
+
+ private:
+  Register _base;
+  Register _index;
+  int _offset;
+  enum access_mode _acc_mode;
+  enum wb_mode _wb_mode;
+  enum reg_op _as_op;
+  shift_op _shift;
+
+  RelocationHolder _rspec;
+
+  // Typically we use AddressLiterals we want to use their rval
+  // However in some situations we want the lval (effect address) of
+  // the item.  We provide a special factory for making those lvals.
+  bool _is_lval;
+
+  // If the target is far we'll need to load the ea of this to a
+  // register to reach it. Otherwise if near we can do PC-relative
+  // addressing.
+  address _target;
+
+ public:
+  Address()
+    : _acc_mode(no_mode) { }
+  //immediate & literal
+  Address(Register r, enum wb_mode mode = off)
+    : _base(r), _index(noreg), _offset(0), _acc_mode(imm), _wb_mode(mode),
+      _shift(lsl()), _target(0) {
+    assert(!(r == r15_pc && _wb_mode == pre), "The PC can't be pre-indexed.");
+  }
+  Address(Register r, int o, enum wb_mode mode = off)
+    : _base(r), _index(noreg), _offset(o), _acc_mode(imm), _wb_mode(mode),
+      _shift(lsl()), _target(0) {
+    assert(!(r == r15_pc && _wb_mode == pre), "The PC can't be pre-indexed.");
+  }
+  Address(Register r, long o, enum wb_mode mode = off)
+    : _base(r), _index(noreg), _offset(o), _acc_mode(imm), _wb_mode(mode),
+      _shift(lsl()), _target(0) {
+    assert(!(r == r15_pc && _wb_mode == pre), "The PC can't be pre-indexed.");
+  }
+  Address(Register r, unsigned long o, enum wb_mode mode = off)
+    : _base(r), _index(noreg), _offset(o), _acc_mode(imm), _wb_mode(mode),
+      _shift(lsl()), _target(0) {
+    assert(!(r == r15_pc && _wb_mode == pre), "The PC can't be pre-indexed.");
+  }
+  Address(Register r, unsigned int o, enum wb_mode mode = off)
+    : _base(r), _index(noreg), _offset(o), _acc_mode(imm), _wb_mode(mode),
+      _shift(lsl()), _target(0) {
+    assert(!(r == r15_pc && _wb_mode == pre), "The PC can't be pre-indexed.");
+  }
+#ifdef ASSERT
+  Address(Register r, ByteSize disp)
+    : _base(r), _index(noreg), _offset(in_bytes(disp)), _acc_mode(imm), _wb_mode(off),
+      _shift(lsl()), _target(0) {
+    assert(!(r == r15_pc && _wb_mode == pre), "The PC can't be pre-indexed.");
+  }
+#endif
+
+
+  //Register-offset
+  Address(Register r, Register r1, shift_op shift = lsl(), enum reg_op op = ADD,
+          enum wb_mode wbm = off)
+    : _base(r), _index(r1), _offset(0), _acc_mode(reg), _wb_mode(wbm), _as_op(op),
+      _shift(shift), _target(0) {
+        assert(!shift.is_register(), "Can't shift a register-offset address by a register");
+  }
+
+  Address(address target, RelocationHolder const& rspec)
+    : _acc_mode(lit),
+      _base(sp),
+      _wb_mode(off),
+      _rspec(rspec),
+      _is_lval(false),
+      _target(target)
+      { }
+  Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type);
+
+ private:
+  //Could be either
+  void AddressConstruct(Register base, RegisterOrConstant index, enum reg_op op, shift_op shift,
+                        enum wb_mode mode);
+ public:
+
+  Address(Register base, RegisterOrConstant index, enum reg_op op, enum wb_mode mode) {
+    AddressConstruct(base, index, op, lsl(), mode);
+  }
+  Address(Register base, RegisterOrConstant index, shift_op shift = lsl(), enum reg_op op = ADD,
+          enum wb_mode mode = off) {
+    if(shift.kind() != lsl().kind()) {
+      assert(index.is_register(), "should be");
+    }
+    AddressConstruct(base, index, op, shift, mode);
+  }
+
+
+  Register base() const {
+    //in aarch64 this didn't apply to preindex mode -> why?
+    guarantee(_acc_mode == imm || _acc_mode == reg, "wrong mode");
+    return _base;
+  }
+  long offset() const {
+    return _offset;
+  }
+  Register index() const {
+    return _index;
+  }
+  access_mode get_mode() const {
+    return _acc_mode;
+  }
+  wb_mode get_wb_mode() const {
+    return _wb_mode;
+  }
+  bool uses(Register reg) const { return _base == reg || _index == reg; }
+  address target() const { return _target; }
+  const RelocationHolder& rspec() const { return _rspec; }
+
+  void encode(Instruction_aarch32 *i, CodeSection *sec, address pc) const;
+
+  void fp_encode(Instruction_aarch32 *i, CodeSection *sec, address pc) const;
+
+  void lea(MacroAssembler *, Register) const;
+
+  static bool offset_ok_for_immed(long imm12);
+};
+
+// Convience classes
+class RuntimeAddress: public Address {
+  public:
+    RuntimeAddress(address target) : Address(target, relocInfo::runtime_call_type) {}
+};
+
+class OopAddress: public Address {
+  public:
+    OopAddress(address target) : Address(target, relocInfo::oop_type){}
+};
+
+class ExternalAddress: public Address {
+ private:
+  static relocInfo::relocType reloc_for_target(address target) {
+    // Sometimes ExternalAddress is used for values which aren't
+    // exactly addresses, like the card table base.
+    // external_word_type can't be used for values in the first page
+    // so just skip the reloc in that case.
+    return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none;
+  }
+
+ public:
+    ExternalAddress(address target) : Address(target, reloc_for_target(target)) {}
+};
+
+class InternalAddress: public Address {
+  public:
+    InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {}
+};
+
+
+
+//TODO Change this back to 16 * 2
+const int FPUStateSizeInWords = 32 * 2;
+typedef enum {
+  PLDL1KEEP = 0b00000, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM,
+  PSTL1KEEP = 0b10000, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM,
+  PLIL1KEEP = 0b01000, PLIL1STRM, PLIL2KEEP, PLIL2STRM, PLIL3KEEP, PLIL3STRM
+} prfop;
+
+
+
+class Assembler : public AbstractAssembler {
+#ifndef PRODUCT
+  static const unsigned long asm_bp;
+
+  void emit_long(jint x) {
+    if ((unsigned long)pc() == asm_bp)
+      asm volatile ("nop");
+    AbstractAssembler::emit_int32(x);
+  }
+#else
+  void emit_long(jint x) {
+    AbstractAssembler::emit_int32(x);
+  }
+#endif
+
+public:
+  //TODO REMOVE shift_kind from here once done
+  enum shift_kind { LSL, LSR, ASR, ROR };
+  // NOTE RRX is a special case of ROR with shift = 0#
+
+  // Helper functions for shifts
+  // Here to allow compiler to find global shift_op without :: prefix as lsl is a
+  // standalone instruction
+#define HELPER(NAME)                                                                \
+  shift_op NAME(int sft = 0) { return ::NAME(sft); }                                \
+  shift_op NAME(Register r) { return ::NAME(r); }
+  HELPER(lsl);
+  HELPER(lsr);
+  HELPER(asr);
+  HELPER(ror);
+  shift_op rrx() { return ::rrx(); }
+#undef HELPER
+
+  typedef enum {
+    EQ, NE, HS, CS=HS, LO, CC=LO, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV
+  } Condition;
+
+  enum { instruction_size = 4 };
+
+  Address adjust(Register base, int offset, bool preIncrement) {
+    if (preIncrement)
+      return Address(base, offset, Address::pre);
+    else
+      return Address(base, offset, Address::post);
+  }
+
+  Address pre(Register base, int offset) {
+    return adjust(base, offset, true);
+  }
+
+  Address post (Register base, int offset) {
+    return adjust(base, offset, false);
+  }
+
+  Instruction_aarch32* current;
+
+  void set_current(Instruction_aarch32* i) { current = i; }
+
+  void f(unsigned val, int msb, int lsb) {
+    current->f(val, msb, lsb);
+  }
+  void f(unsigned val, int msb) {
+    current->f(val, msb, msb);
+  }
+  void sf(long val, int msb, int lsb) {
+    current->sf(val, msb, lsb);
+  }
+  void rf(Register reg, int lsb) {
+    current->rf(reg, lsb);
+  }
+  void rf(FloatRegister reg, int lsb) {
+    current->rf(reg, lsb);
+  }
+  void fixed(unsigned value, unsigned mask) {
+    current->fixed(value, mask);
+  }
+
+  void emit() {
+    emit_long(current->get_insn());
+    assert_cond(current->get_bits() == 0xffffffff);
+    current = NULL;
+  }
+
+  typedef void (Assembler::* uncond_branch_insn)(address dest);
+  typedef void (Assembler::* cond_branch_insn)(address dest, Condition cond);
+  typedef void (Assembler::* cond_ldst_insn)(Register Rt, address dest, Condition cond);
+  typedef void (Assembler::* cond_fp_ldst_insn)(FloatRegister Vd, address dest, Condition cond);
+
+  void wrap_label(Label &L, uncond_branch_insn insn);
+  void wrap_label(Label &L, Condition cond, cond_branch_insn insn);
+  void wrap_label(Register r, Label &L, Condition cond, cond_ldst_insn insn);
+  void wrap_label(FloatRegister r, Label &L, Condition cond, cond_fp_ldst_insn insn);
+
+#undef INSN
+
+// AARCH32 Instructions
+// Defined roughly in the order they are found in
+// ARM Archicture Reference Manual, section 5
+
+#define ZERO_ADDR_REG r0
+#define ONES_ADDR_REG r15
+
+// Data processing (register & register-shifted-register)
+  void reg_instr(int decode, shift_op shift, Condition cond, bool s) {
+    f(cond, 31, 28), f(0b000, 27, 25), f(decode, 24, 21), f(s, 20);
+    f(shift.shift(), 11, 7), f(shift.kind(), 6, 5), f(0, 4);
+  }
+  void reg_shift_reg_instr(int decode, enum shift_op::shift_kind kind,
+                           Condition cond, bool s) {
+    f(cond, 31, 28), f(0b000, 27, 25), f(decode, 24, 21), f(s, 20);
+    f(0, 7), f(kind, 6, 5), f(1, 4);
+  }
+
+#define INSN(NAME, decode, s_flg)                                                   \
+  void NAME(Register Rd, Register Rn, Register Rm, shift_op shift = S_DFLT,         \
+            Condition cond = C_DFLT) {                                              \
+    starti;                                                                         \
+    if(shift.is_register()) {                                                       \
+      reg_shift_reg_instr(decode, shift.kind(), cond, s_flg);                       \
+      rf(Rn, 16), rf(Rd, 12), rf(shift.reg(), 8), rf(Rm, 0);                        \
+    } else {                                                                        \
+      reg_instr(decode, shift, cond, s_flg);                                        \
+      rf(Rn, 16), rf(Rd, 12), rf(Rm, 0);                                            \
+    }                                                                               \
+  }
+  INSN(andr, 0b0000, 0);
+  INSN(eor,  0b0001, 0);
+  INSN(sub,  0b0010, 0);
+  INSN(rsb,  0b0011, 0);
+  INSN(add,  0b0100, 0);
+  INSN(adc,  0b0101, 0);
+  INSN(sbc,  0b0110, 0);
+  INSN(rsc,  0b0111, 0);
+  INSN(orr,  0b1100, 0);
+  INSN(bic,  0b1110, 0);
+  INSN(mvn,  0b1111, 0);
+
+  INSN(ands, 0b0000, 1);
+  INSN(eors, 0b0001, 1);
+  INSN(subs, 0b0010, 1);
+  INSN(rsbs, 0b0011, 1);
+  INSN(adds, 0b0100, 1);
+  INSN(adcs, 0b0101, 1);
+  INSN(sbcs, 0b0110, 1);
+  INSN(rscs, 0b0111, 1);
+  INSN(orrs, 0b1100, 1);
+  INSN(bics, 0b1110, 1);
+  INSN(mvns, 0b1111, 1);
+
+#undef INSN
+
+#define INSN(NAME, decode)                                                           \
+  void NAME(Register Rn, Register Rm, shift_op shift = S_DFLT,                       \
+            Condition cond = C_DFLT) {                                               \
+    starti;                                                                          \
+    if(shift.is_register()) {                                                        \
+        reg_shift_reg_instr(decode, shift.kind(), cond, true);                       \
+    rf(Rn, 16), f(0b0000, 15, 12), rf(shift.reg(), 8), rf(Rm, 0);                    \
+    } else {                                                                         \
+      reg_instr(decode, shift, cond, true);                                          \
+      rf(Rn, 16), f(0, 15, 12), rf(Rm, 0);                                           \
+    }                                                                                \
+  }
+  INSN(tst, 0b1000);
+  INSN(teq, 0b1001);
+  INSN(cmp, 0b1010);
+  INSN(cmn, 0b1011);
+#undef INSN
+
+// TODO appears that if Rd = 15 and s flag set then perhaps different method
+void mov_internal(Register Rd, Register Rnm, shift_op shift, bool s, Condition cond) {
+  starti;
+  if(shift.is_register()) {
+    reg_shift_reg_instr(0b1101, shift.kind(), cond, s);
+    f(0b0000, 19, 16), rf(Rd, 12), rf(shift.reg(), 8), rf(Rnm, 0);
+  } else {
+    reg_instr(0b1101, shift, cond, s);
+    f(0, 19, 16), rf(Rd, 12), rf(Rnm, 0);
+  }
+}
+void mov(Register Rd, Register Rm, shift_op shift, Condition cond = C_DFLT) {
+  mov_internal(Rd, Rm, shift, false, cond);
+}
+void movs(Register Rd, Register Rm, shift_op shift, Condition cond = C_DFLT) {
+  mov_internal(Rd, Rm, shift, true, cond);
+}
+void mov(Register Rd, Register Rm, Condition cond = C_DFLT) {
+  mov_internal(Rd, Rm, S_DFLT, false, cond);
+}
+void movs(Register Rd, Register Rm, Condition cond = C_DFLT) {
+  mov_internal(Rd, Rm, S_DFLT, true, cond);
+}
+
+#define INSN(NAME, type, s_flg, ASSERTION)                                           \
+  void NAME(Register Rd, Register Rm, unsigned shift, Condition cond = C_DFLT) {     \
+    assert_cond(ASSERTION);                                                          \
+    if(s_flg) movs(Rd, Rm, shift_op(type, shift), cond);                             \
+    else       mov(Rd, Rm, shift_op(type, shift), cond);                             \
+  }
+  INSN(lsl, shift_op::LSL, 0, true);
+  INSN(lsr, shift_op::LSR, 0, true);
+  INSN(asr, shift_op::ASR, 0, true);
+  INSN(ror, shift_op::ROR, 0, shift != 0); //shift == 0 => RRX
+
+  INSN(lsls, shift_op::LSL, 1, true);
+  INSN(lsrs, shift_op::LSR, 1, true);
+  INSN(asrs, shift_op::ASR, 1, true);
+  INSN(rors, shift_op::ROR, 1, shift != 0); //shift == 0 => RRX
+#undef INSN
+
+#define INSN(NAME, type, s_flg)                                                      \
+  void NAME(Register Rd, Register Rm, Condition cond = C_DFLT) {                     \
+    if(s_flg) movs(Rd, Rm, shift_op(type, 0), cond);                                 \
+    else       mov(Rd, Rm, shift_op(type, 0), cond);                                 \
+  }
+  INSN(rrx,  shift_op::LSR, 0);
+  INSN(rrxs, shift_op::LSR, 1);
+#undef INSN
+
+//Data processing (register-shifted-register)
+#define INSN(NAME, type, s_flg)                                                      \
+  void NAME(Register Rd, Register Rn, Register Rm, Condition cond = C_DFLT) {        \
+    if(s_flg) movs(Rd, Rn, shift_op(type, Rm), cond);                                \
+    else       mov(Rd, Rn, shift_op(type, Rm), cond);                                \
+  }
+  INSN(lsl, shift_op::LSL, 0);
+  INSN(lsr, shift_op::LSR, 0);
+  INSN(asr, shift_op::ASR, 0);
+  INSN(ror, shift_op::ROR, 0);
+
+  INSN(lsls, shift_op::LSL, 1);
+  INSN(lsrs, shift_op::LSR, 1);
+  INSN(asrs, shift_op::ASR, 1);
+  INSN(rors, shift_op::ROR, 1);
+#undef INSN
+
+
+
+//Data processing (immediate)
+static bool operand_valid_immediate12(int imm);
+static u_int32_t encode_immediate12(int imm);
+static u_int32_t decode_immediate12(int imm);
+
+
+  bool imm_instr(int decode, Register Rd, Register Rn, int imm, Condition cond,
+                 bool s) {
+    if(!operand_valid_immediate12(imm))
+      return false;
+    {
+      starti;
+      f(cond, 31, 28), f(0b001, 27, 25), f(decode, 24, 21), f(s, 20), rf(Rn, 16);
+      int imm12 = encode_immediate12(imm);
+      rf(Rd, 12), f(imm12, 11, 0);
+    }
+    return true;
+  }
+
+#define INSN(NAME, decode, s_flg)                                                    \
+  inline void NAME(Register Rd, Register Rn, unsigned imm, Condition cond = C_DFLT) {\
+    bool status = imm_instr(decode, Rd, Rn, imm, cond, s_flg);                       \
+    assert(status, "invalid imm");                                                   \
+  }
+  INSN(andr, 0b0000, 0);
+  INSN(eor,  0b0001, 0);
+  INSN(orr,  0b1100, 0);
+  INSN(bic,  0b1110, 0);
+
+  INSN(ands, 0b0000, 1);
+  INSN(eors, 0b0001, 1);
+  INSN(orrs, 0b1100, 1);
+  INSN(bics, 0b1110, 1);
+  //NOTE: arithmetic immediate instructions are defined below to allow dispatch.
+#undef INSN
+ protected:
+  // Mov data to destination register in the shortest number of instructions
+  // possible.
+  void mov_immediate(Register dst, u_int32_t imm32, Condition cond, bool s);
+  // Mov data to destination register but always emit enough instructions that would
+  // permit any 32-bit constant to be loaded. (Allow for rewriting later).
+  void mov_immediate32(Register dst, u_int32_t imm32, Condition cond, bool s);
+
+   void add_sub_imm(int decode, Register Rd, Register Rn, int imm,
+                   Condition cond, bool s);
+
+ public:
+#define INSN(NAME, decode, s_flg)                                                    \
+  inline void NAME(Register Rd, Register Rn, int imm, Condition cond = C_DFLT) {     \
+    assert(Rn->encoding_nocheck() != 0b1111, "add/sub with PC is adr");              \
+    add_sub_imm(decode, Rd, Rn, imm, cond, s_flg);                                   \
+  }                                                                                  \
+  inline void NAME(Register Rd, Register Rn, unsigned imm,                           \
+                   Condition cond = C_DFLT) {                                        \
+    assert(Rn->encoding_nocheck() != 0b1111, "add/sub with PC is adr");              \
+    add_sub_imm(decode, Rd, Rn, imm, cond, s_flg);                                   \
+  }                                                                                  \
+  inline void NAME(Register Rd, Register Rn, long imm, Condition cond = C_DFLT) {    \
+    assert(Rn->encoding_nocheck() != 0b1111, "add/sub with PC is adr");              \
+    add_sub_imm(decode, Rd, Rn, imm, cond, s_flg);                                   \
+  }                                                                                  \
+  inline void NAME(Register Rd, Register Rn, unsigned long imm,                      \
+                   Condition cond = C_DFLT) {                                        \
+    assert(Rn->encoding_nocheck() != 0b1111, "add/sub with PC is adr");              \
+    add_sub_imm(decode, Rd, Rn, imm, cond, s_flg);                                   \
+  }                                                                                  \
+  /*Addition dispatch - place in macroassembler?*/                                   \
+  void NAME(Register Rd, Register Rn, RegisterOrConstant operand,                    \
+           Condition cond = C_DFLT) {                                                \
+    if(operand.is_register()) {                                                      \
+      NAME(Rd, Rn, (Register)operand.as_register(), lsl(), cond);                    \
+    } else {                                                                         \
+      NAME(Rd, Rn, (unsigned)operand.as_constant(), cond);                           \
+    }                                                                                \
+  }
+  //Note that the RegisterOrConstant version can't take a shift even though
+  // one of the instructions dispatched to can
+  INSN(sub,  0b0010, 0);
+  INSN(rsb,  0b0011, 0);
+  INSN(add,  0b0100, 0);
+  INSN(adc,  0b0101, 0);
+  INSN(sbc,  0b0110, 0);
+  INSN(rsc,  0b0111, 0);
+
+  INSN(subs, 0b0010, 1);
+  INSN(rsbs, 0b0011, 1);
+  INSN(adds, 0b0100, 1);
+  INSN(adcs, 0b0101, 1);
+  INSN(sbcs, 0b0110, 1);
+  INSN(rscs, 0b0111, 1);
+#undef INSN
+  //No need to do reverse as register subtracted from immediate
+
+  //Helper op
+  void inv(Register Rd, Register Rn, Condition cond = C_DFLT) {
+    rsb(Rd, Rn, 0, cond);
+    sub(Rd, Rd, 1);
+  }
+  //alias for rsb
+  void neg(Register Rd, Register Rn, Condition cond = C_DFLT) {
+    rsb(Rd, Rn, 0, cond);
+  }
+  void negs(Register Rd, Register Rn, Condition cond = C_DFLT) {
+    rsbs(Rd, Rn, 0, cond);
+  }
+
+  // PC-rel. addressing
+  void adr_encode(Register Rd, int imm, Condition cond) {
+    add_sub_imm(0b0100, Rd, r15_pc, imm, cond, false); //opcode for add
+  }
+
+  void adr(Register Rd, address dest, Condition cond = C_DFLT);
+
+  void adr(Register Rd, const Address &dest, Condition cond = C_DFLT);
+
+  void adr(Register Rd, Label &L, Condition cond = C_DFLT) {
+    wrap_label(Rd, L, cond, &Assembler::Assembler::adr);
+  }
+
+ private:
+        friend void entry(CodeBuffer *cb);
+#define INSN(NAME, decode, s_flg)                                                    \
+  inline void NAME(Register Rd, unsigned imm, Condition cond = C_DFLT) {             \
+    bool status = imm_instr(decode, Rd, ZERO_ADDR_REG, imm, cond, s_flg);            \
+    assert(status, "invalid imm");                                                   \
+  }                                                                                  \
+  inline void NAME(Register Rd, int imm, Condition cond = C_DFLT) {                  \
+   bool status = imm_instr(decode, Rd, ZERO_ADDR_REG, imm, cond, s_flg);             \
+   assert(status, "invalid imm");                                                    \
+  }
+  INSN(mov_i, 0b1101, 0);
+  INSN(mvn_i, 0b1111, 0);
+
+  INSN(movs_i, 0b1101, 1);
+  INSN(mvns_i, 0b1111, 1);
+#undef INSN
+
+void movw_i(Register Rd, unsigned imm, Condition cond = C_DFLT) {
+  starti;
+  assert(imm < (1 << 16), "Immediate too big for movw");
+  f(cond, 31, 28), f(0b00110000, 27, 20), f(imm >> 12, 19, 16);
+  rf(Rd, 12), f(imm & 0xfff, 11, 0);
+}
+
+void movt_i(Register Rd, unsigned imm, Condition cond = C_DFLT) {
+  starti;
+  assert(imm < (1 << 16), "Immediate too big for movt");
+  f(cond, 31, 28), f(0b00110100, 27, 20), f(imm >> 12, 19, 16);
+  rf(Rd, 12), f(imm & 0xfff, 11, 0);
+}
+ public:
+
+#define INSN(NAME, decode)                                                           \
+  inline void NAME(Register Rn, int imm, Condition cond = C_DFLT) {                  \
+    bool status = imm_instr(decode, ZERO_ADDR_REG, Rn, imm, cond, true);             \
+    assert(status, "invalid imm");                                                   \
+  }                                                                                  \
+  inline void NAME(Register Rn, unsigned imm, Condition cond = C_DFLT) {             \
+    bool status = imm_instr(decode, ZERO_ADDR_REG, Rn, imm, cond, true);             \
+    assert(status, "invalid imm");                                                   \
+  }
+  INSN(tst, 0b1000);
+  INSN(teq, 0b1001);
+  INSN(cmp, 0b1010);
+  INSN(cmn, 0b1011);
+#undef INSN
+
+
+// Multiply and multiply accumulate
+  void mult_instr(int decode, Register a, Register b, Register c,
+                  Register d, Condition cond, bool s) {
+    starti;
+    f(cond, 31, 28), f(0b0000, 27, 24), f(decode, 23, 21), f(s, 20);
+    rf(a, 16), rf(b, 12), rf(c, 8), rf(d, 0), f(0b1001, 7, 4);
+  }
+
+  void mul(Register Rd, Register Rn, Register Rm, Condition cond = C_DFLT) {
+    mult_instr(0b000, Rd, ZERO_ADDR_REG, Rm, Rn, cond, false);
+  }
+  void muls(Register Rd, Register Rn, Register Rm, Condition cond = C_DFLT) {
+    mult_instr(0b000, Rd, ZERO_ADDR_REG, Rm, Rn, cond, true);
+  }
+
+  void mla(Register Rd, Register Rn, Register Rm, Register Ra, Condition cond = C_DFLT) {
+    mult_instr(0b001, Rd, Ra, Rm, Rn, cond, false);
+  }
+  void mlas(Register Rd, Register Rn, Register Rm, Register Ra, Condition cond = C_DFLT) {
+    mult_instr(0b001, Rd, Ra, Rm, Rn, cond, true);
+  }
+
+  void mls(Register Rd, Register Rn, Register Rm, Register Ra, Condition cond = C_DFLT) {
+    mult_instr(0b011, Rd, Ra, Rm, Rn, cond, false);
+  }
+
+  void umaal(Register RdLo, Register RdHi, Register Rn, Register Rm, Condition cond = C_DFLT) {
+    mult_instr(0b010, RdHi, RdLo, Rm, Rn, cond, false);
+  }
+
+#define INSN(NAME, decode, s_flg)                                                    \
+  void NAME(Register RdLo, Register RdHi, Register Rn, Register Rm,                  \
+            Condition cond = C_DFLT) {                                               \
+    mult_instr(decode, RdHi, RdLo, Rm, Rn, cond, s_flg);                             \
+  }
+  INSN(umull, 0b100, 0);
+  INSN(umlal, 0b101, 0);
+  INSN(smull, 0b110, 0);
+  INSN(smlal, 0b111, 0);
+
+  INSN(umulls, 0b100, 1);
+  INSN(umlals, 0b101, 1);
+  INSN(smulls, 0b110, 1);
+  INSN(smlals, 0b111, 1);
+
+#undef INSN
+
+//Saturating addition and subtraction
+#define INSN(NAME, decode)                                                           \
+  void NAME(Register Rd, Register Rm, Register Rn, Condition cond = C_DFLT) {        \
+    starti;                                                                          \
+    f(cond, 31, 28), f( 0b00010, 27, 23), f(decode, 22, 21), f(0, 20);               \
+    rf(Rn, 16), rf(Rd, 12), f( 0b00000101, 11, 4),  rf(Rm, 0);                       \
+  }
+  INSN(qadd,  0b00);
+  INSN(qsub,  0b01);
+  INSN(qdadd, 0b10);
+  INSN(qdsub, 0b11);
+#undef INSN
+
+// Halfword multiply and multiply accumulate
+  void mul_instr(int decode, Register Ra, Register Rb, Register Rc, Register Rd,
+                 bool N, bool M, Condition cond) {
+      starti;
+      f(cond, 31, 28), f(0b00010, 27, 23), f(decode, 22, 21), f(0, 20);
+      rf(Ra, 16), rf(Rb, 12), rf(Rc, 8), f(1, 7), f(M, 6), f(N, 5), f(0, 4);
+      rf(Rd, 0);
+  }
+
+#define INSN(NAME, decode, N, M)                                                     \
+  void NAME(Register Rd, Register Rn, Register Rm, Register Ra,                      \
+            Condition cond = C_DFLT) {                                               \
+    mul_instr(decode, Rd, Ra, Rm, Rn, N, M, cond);                                   \
+  }
+  INSN(smlabb, 0b00, 0, 0);
+  INSN(smlabt, 0b00, 0, 1)
+  INSN(smlatb, 0b00, 1, 0)
+  INSN(smlatt, 0b00, 1, 1)
+
+  INSN(smlawb, 0b01, 0, 0);
+  INSN(smlawt, 0b01, 0, 1);
+#undef INSN
+
+#define INSN(NAME, decode, N, M)                                                     \
+  void NAME(Register RdLo, Register RdHi, Register Rn, Register Rm,                  \
+            Condition cond = C_DFLT) {                                               \
+    mul_instr(decode, RdHi, RdLo, Rm, Rn, N, M, cond);                               \
+  }
+  INSN(smlalbb, 0b10, 0, 0);
+  INSN(smlalbt, 0b10, 0, 1);
+  INSN(smlaltb, 0b10, 1, 0);
+  INSN(smlaltt, 0b10, 1, 1);
+#undef INSN
+
+#define INSN(NAME, decode, N, M)                                                     \
+  void NAME(Register Rd, Register Rn, Register Rm, Condition cond = C_DFLT) {        \
+    mul_instr(decode, Rd, ZERO_ADDR_REG, Rm, Rn, N, M, cond);                        \
+  }
+  INSN(smulwb, 0b01, 1, 0);
+  INSN(smulwt, 0b01, 1, 1);
+
+  INSN(smulbb, 0b11, 0, 0);
+  INSN(smulbt, 0b11, 0, 1);
+  INSN(smultb, 0b11, 1, 0);
+  INSN(smultt, 0b11, 1, 1);
+#undef INSN
+
+// For Extra load/store instructions, see load/store section
+// For Synchronization primitives, see load/store section
+
+// MSR(immediate), and hints
+#define INSN(NAME, decode)                                                           \
+  void NAME(Condition cond = C_DFLT) {                                               \
+    starti;                                                                          \
+    f(cond, 31, 28), f(0b001100100000, 27, 16), f(0b11110000, 15, 8);                \
+    f(decode, 7, 0);                                                                 \
+  }
+  INSN(nop,   0b000);
+  INSN(yield, 0b001);
+  INSN(wfe,   0b010);
+  INSN(wfi,   0b011);
+  INSN(sev,   0b100);
+  void dbg(int dbg_hint, Condition cond = C_DFLT) {
+    f(cond, 31, 28), f(0b001100100000, 27, 16), f(0b11110000, 15, 8);
+    f(0b1111, 7, 4); f(dbg_hint, 3, 0);
+  }
+#undef INSN
+
+  //TODO Misc instructions
+  void bkpt(unsigned imm) {
+    starti;
+    f(AL, 31, 28), f(0b00010010, 27, 20);
+    f(imm >> 4, 19, 8), f(0b0111, 7, 4), f(imm & 0xf, 3, 0);
+  }
+  void hlt(unsigned imm) {
+    bkpt(imm);
+    // FIXME This seemed like the best option!
+  }
+
+  // Load/store register (all modes)
+  void load_store_instr(Register Rt, const Address &adr, int op, int op2, int a, int b,
+                        Condition cond) {
+    starti;
+    f(cond, 31, 28), f(op, 27, 25), f(a, 22), f(b, 20);
+    if(op2 >= 0)
+      f(op2, 7, 4);
+    //Destination
+    rf(Rt, 12);
+    adr.encode(current, code_section(), pc());
+  }
+
+  bool encodeable(int decode, address dest) {
+    long offset = dest - pc();
+    switch(decode) {
+      case 0b010:
+        // LDR, LDRB, STR, STRB
+        return uabs(offset) < ((1 << 12) - 1);
+      case 0b000:
+        //LDRD, LDRH, LDRSB, LDRSH, STRH, STRD
+        return uabs(offset) < ((1 << 8) - 1);
+      default:
+        ShouldNotReachHere();
+    }
+    return false;
+  }
+
+
+
+#define INSN_INT(NAME, op, op2, a, b, isload)                                        \
+  void NAME(Register Rt, address dest, Condition cond = C_DFLT) {                    \
+    if(encodeable(op, dest)) { /* Plan A */                                          \
+      long offset = dest - pc();                                                     \
+      NAME(Rt, Address(r15_pc, offset), cond);                                       \
+    } else if(isload){ /* Plan B */                                                  \
+      /* TODO check we don't have to relocate this*/                                 \
+      mov_immediate(Rt, (u_int32_t)dest, cond, false);                               \
+      NAME(Rt, Address(Rt, 0), cond);                                                \
+    } else { /* There is no plan C */                                                \
+      ShouldNotReachHere();                                                          \
+    }                                                                                \
+  }                                                                                  \
+  void NAME(Register Rt, address dest, relocInfo::relocType rtype,                   \
+            Condition cond = C_DFLT) {                                               \
+    guarantee(rtype == relocInfo::internal_word_type,                                \
+              "only internal_word_type relocs make sense here");                     \
+    NAME(Rt, InternalAddress(dest), cond);                                           \
+  }                                                                                  \
+  void NAME(Register Rt, Label &L, Condition cond = C_DFLT) {                        \
+    wrap_label(Rt, L, cond, &Assembler::NAME);                                       \
+  }
+
+#define INSN(NAME, op, op2, a, b, isload)                                            \
+  void NAME(Register Rt, const Address &adr, Condition cond = C_DFLT) {              \
+    load_store_instr(Rt, adr, op, op2, a, b, cond);                                  \
+  }                                                                                  \
+  INSN_INT(NAME, op, op2, a, b, isload);
+  INSN(ldr,   0b010,     -1, 0, 1, 1);
+  INSN(ldrb,  0b010,     -1, 1, 1, 1);
+
+  INSN(ldrsb, 0b000, 0b1101, 0, 1, 1);
+  INSN(ldrh,  0b000, 0b1011, 0, 1, 1);
+  INSN(ldrsh, 0b000, 0b1111, 0, 1, 1);
+
+  INSN(str,   0b010,     -1, 0, 0, 0);
+  INSN(strb,  0b010,     -1, 1, 0, 0);
+  INSN(strh,  0b000, 0b1011, 0, 0, 0);
+  //Note LDRD & STRD are defined with the load/store multiple instructions
+
+  //TODO Need to introduce ldrsb ldrsh - then check that the encoding works properly!
+#undef INSN
+
+
+  //Synchronization primitives
+  void sync_instr(int decode, Register Ra, Register Rb, Register Rc, Register Rd,
+             Condition cond) {
+    starti;
+    f(cond, 31, 28), f(0b0001, 27, 24), f(decode, 23, 20), rf(Ra, 16), rf(Rb, 12);
+    rf(Rc, 8), f(0b1001, 7, 4), rf(Rd, 0);
+  }
+
+#define INSN(NAME, decode)                                                           \
+  void NAME(Register Rd, Register Rt, Register Rn, Condition cond = C_DFLT) {        \
+    assert(r15_pc != Rn, "Unpredictable");                                           \
+    sync_instr(decode, Rn, Rd, ONES_ADDR_REG, Rt, cond);                             \
+  }
+  INSN( strex, 0b1000);
+  INSN(strexd, 0b1010);
+  INSN(strexb, 0b1100);
+  INSN(strexh, 0b1110);
+#undef INSN
+
+#define INSN(NAME, decode)                                                           \
+  void NAME(Register Rt, Register Rn, Condition cond = C_DFLT) {                     \
+    assert(r15_pc != Rn, "Unpredictable");                                           \
+    sync_instr(decode, Rn, Rt, ONES_ADDR_REG, ONES_ADDR_REG, cond);                  \
+  }
+  INSN(ldrex,  0b1001);
+  INSN(ldrexd, 0b1011);
+  INSN(ldrexb, 0b1101);
+  INSN(ldrexh, 0b1111);
+#undef INSN
+
+// Media instructions
+void media_instr(int decode, int decode2, Condition cond) {
+  f(cond, 31, 28), f(0b011, 27, 25), f(decode, 24, 20);
+  f(decode2, 7, 5), f(1, 4);
+}
+
+#define INSN(NAME, decode, decode2)                                                  \
+  void NAME(Register Rd, Register Rn, Register Rm, Condition cond = C_DFLT) {        \
+    starti;                                                                          \
+    media_instr(0b00000 | decode, decode2, cond);                                    \
+    rf(Rn, 16), rf(Rd, 12), f(0b1111, 11, 8), rf(Rm, 0);                             \
+  }
+  INSN(sadd16, 0b01, 0b000);
+  INSN(sasx,   0b01, 0b001);
+  INSN(ssax,   0b01, 0b010);
+  INSN(ssub16, 0b01, 0b011);
+  INSN(sadd8,  0b01, 0b100);
+  INSN(ssub8,  0b01, 0b111);
+  //Saturating
+  INSN(qadd16, 0b10, 0b000);
+  INSN(qasx,   0b10, 0b001);
+  INSN(qsax,   0b10, 0b010);
+  INSN(qsub16, 0b10, 0b011);
+  INSN(qadd8,  0b10, 0b100);
+  INSN(qsub8,  0b10, 0b111);
+  //Halving
+  INSN(shadd16, 0b11, 0b000);
+  INSN(shasx,   0b11, 0b001);
+  INSN(shsax,   0b11, 0b010);
+  INSN(shsub16, 0b11, 0b011);
+  INSN(shadd8,  0b11, 0b100);
+  INSN(shsub8,  0b11, 0b111);
+
+  //Now unsigned
+  INSN(uadd16, 0b101, 0b000);
+  INSN(uasx,   0b101, 0b001);
+  INSN(usax,   0b101, 0b010);
+  INSN(usub16, 0b101, 0b011);
+  INSN(uadd8,  0b101, 0b100);
+  INSN(usub8,  0b101, 0b111);
+  //Saturating
+  INSN(uqadd16, 0b110, 0b000);
+  INSN(uqasx,   0b110, 0b001);
+  INSN(uqsax,   0b110, 0b010);
+  INSN(uqsub16, 0b110, 0b011);
+  INSN(uqadd8,  0b110, 0b100);
+  INSN(uqsub8,  0b110, 0b111);
+  //Halving
+  INSN(uhadd16, 0b111, 0b000);
+  INSN(uhasx,   0b111, 0b001);
+  INSN(uhsax,   0b111, 0b010);
+  INSN(uhsub16, 0b111, 0b011);
+  INSN(uhadd8,  0b111, 0b100);
+  INSN(uhsub8,  0b111, 0b111);
+#undef INSN
+
+//Packing, unpacking, saturation and reversal
+// Note rotation can only be one of ROR #0 ROR #8 ROR #16 ROR #24
+void extend_instr(int decode, int decode2, int decode3, Register Rd, Register Rn,
+                  Register Rm, shift_op shift, Condition cond) {
+  starti;
+  assert(0 == shift.shift() ||
+         shift_op::ROR == shift.kind(), "Only ROR may be used for op");
+  // All zero shifts are mapped to LSL #0
+  int shift_enc = 0;
+  switch(shift.shift()) {
+    case 0:                 break;
+    case 8:  shift_enc = 1; break;
+    case 16: shift_enc = 2; break;
+    case 24: shift_enc = 3; break;
+    default: assert(false, "Invalid shift quantity");
+  }
+  media_instr(0b01000 | decode, decode2, cond);
+  rf(Rn, 16), rf(Rd, 12), f(shift_enc, 11, 10), f(decode3, 9, 8), rf(Rm, 0);
+}
+
+#define INSN(NAME, decode, decode2)                                                  \
+  void NAME(Register Rd, Register Rn, Register Rm, shift_op shift = ::ror(),         \
+            Condition cond = C_DFLT) {                                               \
+    assert(0xf != Rn->encoding_nocheck(), "Rn = pc makes different instruction");    \
+    extend_instr(decode, decode2, 0b00, Rd, Rn, Rm, shift, cond);                    \
+  }
+  INSN(sxtab16, 0b000, 0b011);
+  INSN(sxtab,   0b010, 0b011);
+  INSN(sxtah,   0b011, 0b011);
+  INSN(uxtab16, 0b100, 0b011);
+  INSN(uxtab,   0b110, 0b011);
+  INSN(uxtah,   0b111, 0b011);
+#undef INSN
+
+#define INSN(NAME, decode, decode2)                                                  \
+  void NAME(Register Rd, Register Rm, shift_op shift = ::ror(),                      \
+            Condition cond = C_DFLT) {                                               \
+    extend_instr(decode, decode2, 0b00, Rd, ONES_ADDR_REG, Rm, shift, cond);         \
+  }
+  INSN(sxtb16, 0b000, 0b011);
+  INSN(sxtb,   0b010, 0b011);
+  INSN(sxth,   0b011, 0b011);
+  INSN(uxtb16, 0b100, 0b011);
+  INSN(uxtb,   0b110, 0b011);
+  INSN(uxth,   0b111, 0b011);
+#undef INSN
+
+  //Reverse instructions
+#define INSN(NAME, decode, decode2)                                                  \
+  void NAME(Register Rd, Register Rm, Condition cond = C_DFLT) {                     \
+    extend_instr(decode, decode2, 0b11, Rd, ONES_ADDR_REG, Rm, ::ror(24), cond);     \
+  }
+  INSN(rev,   0b011, 0b001);
+  INSN(rev16, 0b011, 0b101);
+  INSN(rbit,  0b111, 0b001);
+  INSN(revsh, 0b111, 0b101);
+#undef INSN
+
+// Signed multiply, signed and unsigned divide
+#define INSN(NAME, decode, decode2)                                                  \
+  void NAME(Register Rd, Register Rn, Register Rm, Condition cond = C_DFLT) {        \
+    starti;                                                                          \
+    media_instr(0b10000 | decode, decode2, cond);                                    \
+    rf(Rd, 16), f(0b1111, 15, 12), rf(Rm, 8), rf(Rn, 0);                             \
+  }
+  INSN(sdiv, 0b001, 0b000);
+  INSN(udiv, 0b011, 0b000);
+  //TODO ALL THE REST!
+#undef INSN
+
+// Remainder of things
+//TODO USAD8
+#define INSN(NAME, decode, decode2)                                                  \
+  void NAME(Register Rd, Register Rn, int lsb, int width,                            \
+            Condition cond = C_DFLT) {                                               \
+    starti;                                                                          \
+    assert(lsb >= 0 && lsb < 32, "lsb out of range");                                \
+    assert(width > 0 && width <= 32 - lsb, "width out of range");                    \
+    media_instr(decode, decode2, cond);                                              \
+    f(width - 1, 20, 16), rf(Rd, 12), f(lsb, 11, 7), rf(Rn, 0);                      \
+  }
+  INSN(sbfx, 0b11010, 0b010);
+  INSN(ubfx, 0b11110, 0b010);
+#undef INSN
+
+void bfi(Register Rd, Register Rn, int lsb, int width, Condition cond = C_DFLT) {
+  int msb = lsb + width - 1;
+  assert(lsb >= 0 && lsb < 32, "lsb out of range");
+  assert(msb < 32 && msb >= lsb, "width out of range");
+  starti;
+  media_instr(0b11100, 0b000, cond);
+  f(msb, 20, 16), rf(Rd, 12), f(lsb, 11, 7), rf(Rn, 0);
+}
+
+void bfc(Register Rd, int lsb, int width, Condition cond = C_DFLT) {
+  int msb = lsb + width - 1;
+  assert(lsb >= 0 && lsb < 32, "lsb out of range");
+  assert(msb < 32 && msb >= lsb, "width out of range");
+  starti;
+  media_instr(0b11100, 0b000, cond);
+  f(msb, 20, 16), rf(Rd, 12), f(lsb, 11, 7), f(0b1111, 3, 0);
+}
+
+//Branch, branch with link, and block data transfer
+
+void block_imm_instr(int decode, int w, Register Rn, unsigned regset,
+                     Condition cond) {
+  starti;
+  f(cond, 31, 28), f(0b10, 27, 26), f(decode | (w << 1), 25, 20);
+  rf(Rn, 16), f(regset, 15, 0);
+}
+#define INSN(NAME, decode)                                                           \
+  void NAME(Register Rn, unsigned regset, bool wb = true, Condition cond = C_DFLT) { \
+    block_imm_instr(decode, wb, Rn, regset, cond);                                   \
+  }
+  INSN(stmda, 0b000000);
+  INSN(stmed, 0b000000);
+
+  INSN(ldmda, 0b000001);
+  INSN(ldmfa, 0b000001);
+
+  //INSN(stm,   0b001000);
+  INSN(stmia, 0b001000);
+  INSN(stmea, 0b001000);
+
+  //INSN(ldm,   0b001001);
+  INSN(ldmia, 0b001001);
+  INSN(ldmfd, 0b001001);
+
+  INSN(stmdb, 0b010000);
+  INSN(stmfd, 0b010000);
+
+  INSN(ldmdb, 0b010001);
+  INSN(ldmea, 0b010001);
+
+  INSN(stmib, 0b011000);
+  INSN(stmfa, 0b011000);
+
+  INSN(ldmib, 0b011001);
+  INSN(ldmed, 0b011001);
+#undef INSN
+
+unsigned count_bits(unsigned val);
+bool can_ldst_multiple( unsigned regset, const Address& adr);
+
+//NOTE!! Have repurposed stm and ldm for auto dispatch instructions
+#define INSN(NAME, PREFIX)                                                           \
+  void NAME(unsigned regset, const Address& adr, Condition cond = C_DFLT) {          \
+    assert(can_ldst_multiple(regset, adr), "Can't do anything with this!");          \
+    int offset = adr.offset();                                                       \
+    switch(adr.get_wb_mode()) {                                                      \
+      case Address::pre:                                                             \
+        if(offset > 0) PREFIX##mib(adr.base(), regset, true, cond);                  \
+        else           PREFIX##mdb(adr.base(), regset, true, cond);                  \
+        break;                                                                       \
+      case Address::post:                                                            \
+        if(offset > 0) PREFIX##mia(adr.base(), regset, true, cond);                  \
+        else           PREFIX##mda(adr.base(), regset, offset != 0, cond);           \
+        break;                                                                       \
+      case Address::off:                                                             \
+        if(offset > 0)   PREFIX##mib(adr.base(), regset, false, cond);               \
+        else if(!offset) PREFIX##mia(adr.base(), regset, false, cond);               \
+        else             PREFIX##mdb(adr.base(), regset, false, cond);               \
+        break;                                                                       \
+      default:                                                                       \
+        ShouldNotReachHere();                                                        \
+    }                                                                                \
+  }
+  INSN(ldm, ld);
+  INSN(stm, st);
+#undef INSN
+
+//Made push and pop operate on full descending stacks
+#define INSN(NAME, CNAME)                                                            \
+  inline void NAME(unsigned regset, Condition cond = C_DFLT) {                       \
+    CNAME(r13, regset, true, cond);                                                  \
+  }
+  INSN(pop,  ldmia);
+  INSN(push, stmdb);
+#undef INSN
+
+ private:
+  void double_ldst_failed_dispatch(Register Rt, Register Rt2, const Address& adr,
+                            void (Assembler::* mul)(unsigned, const Address&, Condition),
+                            void (Assembler::* sgl)(Register, const Address&, Condition),
+                            Condition cond);
+ public:
+
+#define INSN(NAME, PREFIX, op, op2, a, b, isload)                                    \
+  void NAME(Register Rt, Register Rt2, const Address& adr,                           \
+            Condition cond = C_DFLT) {                                               \
+    if(0 == Rt->encoding_nocheck() % 2 &&                                            \
+       (Rt->encoding_nocheck() + 1 == Rt2->encoding_nocheck())) {                    \
+      /* Good to go with a ldrd/strd */                                              \
+      load_store_instr(Rt, adr, op, op2, a, b, cond);                                \
+    } else {                                                                         \
+      double_ldst_failed_dispatch(Rt, Rt2, adr, &Assembler::PREFIX##m,               \
+                                  &Assembler::PREFIX##r, cond);                      \
+    }                                                                                \
+  }                                                                                  \
+  void NAME(Register Rt, const Address& adr, Condition cond = C_DFLT) {              \
+    NAME(Rt, (Register)(Rt + 1), adr, cond);                                         \
+  }                                                                                  \
+  INSN_INT(NAME, op, op2, a, b, isload);
+
+  INSN(ldrd, ld, 0b000, 0b1101, 0, 0, 1);
+  INSN(strd, st, 0b000, 0b1111, 0, 0, 0);
+#undef INSN
+#undef INSN_INT
+
+  // Branches
+
+  // For immediate branches:
+  // The maximum range of a branch is fixed for the aarch32
+  // architecture.  In debug mode we shrink it in order to test
+  // trampolines, but not so small that branches in the interpreter
+  // are out of range.
+  static const unsigned long branch_range = NOT_DEBUG(32 * M) DEBUG_ONLY(2 * M);
+  static bool reachable_from_branch_at(address branch, address target) {
+    return uabs(target - branch) < branch_range;
+  }
+
+  void branch_imm_instr(int decode, address dest, Condition cond) {
+    starti;
+    // Correct PC for as it will be when executing this instruction
+    int offset = (dest - (pc() + 8)) >> 2;
+    assert(reachable_from_branch_at(pc(), dest), "branch target unreachable");
+    f(cond, 31, 28), f(decode, 27, 24), sf(offset, 23, 0);
+  }
+
+  void branch_reg_instr(int decode, Register Rm, Condition cond) {
+    starti;
+    f(cond, 31, 28), f(0b00010010, 27, 20);
+    f(0b111111111111, 19, 8), f(decode, 7, 4), rf(Rm, 0);
+  }
+
+#define INSN(NAME, decode_imm, decode_reg)                                           \
+  void NAME(Register Rm, Condition cond = C_DFLT) {                                  \
+    branch_reg_instr(decode_reg, Rm, cond);                                          \
+  }                                                                                  \
+  void NAME(address dest, Condition cond = C_DFLT) {                                 \
+    branch_imm_instr(decode_imm, dest, cond);                                        \
+  }                                                                                  \
+  void NAME(Label &L, Condition cond = C_DFLT) {                                     \
+    wrap_label(L, cond, &Assembler::NAME);                                           \
+  }                                                                                  \
+  void NAME(const Address &dest, Condition cond = C_DFLT) {                          \
+    code_section()->relocate(pc(), dest.rspec());                                    \
+    NAME(dest.target(), cond);                                                       \
+  }
+  //TODO assert type of address
+  INSN(b,  0b1010, 0b0001); // B & BX
+  INSN(bl, 0b1011, 0b0011); // BL & BLX
+#undef INSN
+
+
+//TODO Coprocessor instructions, and Supervisor Call
+
+
+// Unconditional Instructions
+  enum barrier {OSHST = 0b0010, OSH,
+                NSHST = 0b0110, NSH,
+                ISHST = 0b1010, ISH,
+                   ST = 0b1110, SY};
+
+  void sync_instr(int decode, enum barrier option) {
+    starti;
+    f(0b11110, 31, 27), f(0b1010111, 26, 20), f(0b111111110000, 19, 8);
+    f(decode, 7, 4), f(option, 3, 0);
+  }
+  void clrex() {
+    sync_instr(0b0001, SY);
+  }
+  void dsb(enum barrier option) {
+    sync_instr(0b0100, option);
+  }
+  void dmb(enum barrier option) {
+    sync_instr(0b0100, option);
+  }
+  void bkpt();
+  void isb() {
+    sync_instr(0b0110, SY);
+  }
+
+  // And the relevant instructions for ARMv6.
+
+  // MCR<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}
+  void mcr(int cpc_dex, int opc1, Register Rt, int cpc_reg_dex1,
+           int cpc_reg_dex2, int opc2, Condition cond = C_DFLT) {
+        starti;
+        f(cond, 31, 28), f(0b1110, 27, 24), f(opc1, 23, 21), f(0, 20);
+        f(cpc_reg_dex1, 19, 16), rf(Rt, 12), f(cpc_dex, 11, 8);
+        f(opc2, 7, 5), f(1, 4), f(cpc_reg_dex2, 3, 0);
+  }
+
+  // These instructions do not read the value of the register passed,
+  // can be any. Chosen r0.
+  void cp15dmb(Condition cond = C_DFLT) {
+        mcr(15, 0, r0, 7, 10, 5, cond);
+  }
+
+  void cp15dsb(Condition cond = C_DFLT) {
+        mcr(15, 0, r0, 7, 10, 4, cond);
+  }
+
+  void cp15isb(Condition cond = C_DFLT) {
+        mcr(15, 0, r0, 7, 5, 4, cond);
+  }
+
+  enum Membar_mask_bits {
+    // We can use ISH for a barrier because the ARM ARM says "This
+    // architecture assumes that all Processing Elements that use the
+    // same operating system or hypervisor are in the same Inner
+    // Shareable shareability domain."
+    StoreStore = ISHST,
+    LoadStore  = ISH, //ISHLD, Changed to
+    LoadLoad   = ISH, //ISHLD,
+    StoreLoad  = ISH,
+    AnyAny     = ISH
+  };
+
+// Floating point operations
+
+// A note on floating point operations:
+// As we're not short on floating point registers if we're given a bit D which
+// in 64 bit mode allows access to the higher double support registers or in
+// single precision mode allow access to the odd number registers. We always
+// clear the bit reducing the number of single and double precision registers
+// available but simplifiying encoding.
+// the fp rencode function can be easily modified however to do something
+// a bit snazzier!
+
+enum fpscr_cond { FP_EQ = 0b0110 << 28,
+                  FP_LT = 0b1000 << 28,
+                  FP_GT = 0b0010 << 28,
+                  FP_UN = 0b0011 << 28,
+                  FP_MASK = 0b1111 << 28 };
+
+  void fp_instr_base(bool is64bit, Condition cond) {
+    f(cond, 31, 28), f(0b1110, 27, 24), f(0b101, 11, 9), f(is64bit, 8), f(0, 4);
+  }
+
+  void fp_rencode(FloatRegister reg, bool is64bit, int base, int bit) {
+    int reg_val = reg->encoding_nocheck();
+    /*if(is64bit) {
+      f( reg_val >> 1, base + 3, base);
+      f( reg_val & 1, bit);
+    } else {
+      f( reg_val & 0xf, base + 3, base);
+      f( reg_val >> 4, bit);
+    }*/
+    f(reg_val & 0xf, base + 3, base);
+    f(0, bit);
+    // Force alignment to double registers
+    // for all ops.
+  }
+
+  void fp_instr(int decode, int op, bool is64bit, FloatRegister Rd, FloatRegister Rn,
+                FloatRegister Rm, Condition cond) {
+    fp_instr_base(is64bit, cond);
+    f(decode, 23, 20), f(op, 6);
+    // Register encoding is a bit involved
+    fp_rencode(Rn, is64bit, 16, 7);
+    fp_rencode(Rd, is64bit, 12, 22);
+    fp_rencode(Rm, is64bit,  0, 5);
+  }
+
+#define INSN(NAME, decode, op, is64bit)                                              \
+  void NAME(FloatRegister Rd, FloatRegister Rn, FloatRegister Rm,                    \
+            Condition cond = C_DFLT) {                                               \
+    starti;                                                                          \
+    fp_instr(decode, op, is64bit, Rd, Rn, Rm, cond);                                 \
+  }
+  INSN(vmla_f32,  0b0000, 0, 0);
+  INSN(vmla_f64,  0b0000, 0, 1);
+  INSN(vmls_f32,  0b0000, 1, 0);
+  INSN(vmls_f64,  0b0000, 1, 1);
+
+  INSN(vnmla_f32, 0b0001, 1, 0);
+  INSN(vnmla_f64, 0b0001, 1, 1);
+  INSN(vnmls_f32, 0b0001, 0, 0);
+  INSN(vnmls_f64, 0b0001, 0, 1);
+  INSN(vnmul_f32, 0b0010, 1, 0);
+  INSN(vnmul_f64, 0b0010, 1, 1);
+  INSN(vmul_f32,  0b0010, 0, 0);
+  INSN(vmul_f64,  0b0010, 0, 1);
+
+  INSN(vadd_f32,  0b0011, 0, 0);
+  INSN(vadd_f64,  0b0011, 0, 1);
+  INSN(vsub_f32,  0b0011, 1, 0);
+  INSN(vsub_f64,  0b0011, 1, 1);
+
+  INSN(vdiv_f32,  0b1000, 0, 0);
+  INSN(vdiv_f64,  0b1000, 0, 1);
+
+  INSN(vfnma_f32, 0b1001, 1, 0);
+  INSN(vfnma_f64, 0b1001, 1, 1);
+  INSN(vfnms_f32, 0b1001, 0, 0);
+  INSN(vfnms_f64, 0b1001, 0, 1);
+
+  INSN(vfma_f32,  0b1010, 0, 0);
+  INSN(vfma_f64,  0b1010, 0, 1);
+  INSN(vfms_f32,  0b1010, 1, 0);
+  INSN(vfms_f64,  0b1010, 1, 1);
+#undef INSN
+
+
+  void vmov_imm(FloatRegister Rd, unsigned imm, bool is64bit, Condition cond);
+  void vmov_imm_zero(FloatRegister Rd, bool is64bit, Condition cond);
+
+#define INSN(NAME, is64bit, ntype)                                                   \
+  unsigned encode_##ntype##_fp_imm(ntype imm_f);                                     \
+  void NAME(FloatRegister Rd, ntype imm, Condition cond = C_DFLT) {                  \
+    if(0.0 == imm) vmov_imm_zero(Rd, is64bit, cond);                                 \
+    else           vmov_imm(Rd, encode_##ntype##_fp_imm(imm), is64bit, cond);        \
+  }
+  INSN(vmov_f32, false, float);
+  INSN(vmov_f64, true, double);
+#undef INSN
+
+#define INSN(NAME, decode, op, is64bit)                                              \
+  void NAME(FloatRegister Rd, FloatRegister Rm, Condition cond = C_DFLT) {           \
+    starti;                                                                          \
+    fp_instr_base(is64bit, cond);                                                    \
+    f(0b1011, 23, 20), f(decode, 19, 16), f(op, 7, 6), f(0b00, 5, 4);                \
+    fp_rencode(Rd, is64bit, 12, 22);                                                 \
+    fp_rencode(Rm, is64bit, 0, 5);                                                   \
+  }
+  INSN(vmov_f32,  0b0000, 0b01, 0);
+  INSN(vmov_f64,  0b0000, 0b01, 1);
+  INSN(vabs_f32,  0b0000, 0b11, 0);
+  INSN(vabs_f64,  0b0000, 0b11, 1);
+  INSN(vneg_f32,  0b0001, 0b01, 0);
+  INSN(vneg_f64,  0b0001, 0b01, 1);
+  INSN(vsqrt_f32, 0b0001, 0b11, 0);
+  INSN(vsqrt_f64, 0b0001, 0b11, 1);
+#undef INSN
+
+//ARM -> FP, FP -> ARM
+// NOTE - Have only implemented the double precision variant as only operating on
+// double registers - can still be used to copy single precision
+void vmov64_instr_base(FloatRegister Rm, Register Rt, Register Rt2, int op,
+                       Condition cond) {
+  starti;
+  f(cond, 31, 28), f(0b1100010, 27, 21), f(op, 20);
+  rf(Rt2, 16), rf(Rt, 12), f(0b101100, 11, 6), f(1, 4);
+  fp_rencode(Rm, true, 0, 5);
+}
+
+void vmov_f64(FloatRegister Rm, Register Rt, Register Rt2, Condition cond = C_DFLT) {
+  vmov64_instr_base(Rm, Rt, Rt2, 0, cond);
+}
+void vmov_f64(Register Rt, Register Rt2, FloatRegister Rm, Condition cond = C_DFLT) {
+  vmov64_instr_base(Rm, Rt, Rt2, 1, cond);
+}
+
+void vmov_f32(FloatRegister Rn, Register Rt, Condition cond = C_DFLT) {
+  starti;
+  fp_instr_base(false, cond);
+  f(0b000, 23, 21), f(0, 20);
+  rf(Rt, 12), f(0b101000010000, 11, 0);
+  fp_rencode(Rn, false, 16, 7);
+}
+void vmov_f32(Register Rt, FloatRegister Rn, Condition cond = C_DFLT) {
+  starti;
+  fp_instr_base(false, cond);
+  f(0b000, 23, 21), f(1, 20);
+  rf(Rt, 12), f(0b101000010000, 11, 0);
+  fp_rencode(Rn, false, 16, 7);
+}
+
+// Floating-point comparison
+#define INSN(NAME, E, is64bit)                                                       \
+  void NAME(FloatRegister Rd, int imm, Condition cond = C_DFLT) {                    \
+    assert(0 == imm, "vector compare can only be with another vector or zero");      \
+    starti;                                                                          \
+    fp_instr_base(is64bit, cond);                                                    \
+    f(0b10110101, 23, 16), f(E, 7), f(0b1000000, 6, 0);                              \
+    fp_rencode(Rd, is64bit, 12, 22);                                                 \
+  }                                                                                  \
+  void NAME(FloatRegister Vd, FloatRegister Vm, Condition cond = C_DFLT) {           \
+    starti;                                                                          \
+    fp_instr_base(is64bit, cond);                                                    \
+    f(0b10110100, 23, 16), f(E, 7), f(1, 6), f(0, 4);                                \
+    fp_rencode(Vd, is64bit, 12, 22), fp_rencode(Vm, is64bit, 0, 5);                  \
+  }
+  INSN(vcmpe_f64, 1, 1);
+  INSN(vcmpe_f32, 1, 0);
+  INSN( vcmp_f64, 0, 1);
+  INSN( vcmp_f32, 0, 0);
+#undef INSN
+
+//Move FPSCR to ARM register
+void vmrs(Register Rt, Condition cond = C_DFLT) {
+  starti;
+  f(cond, 31, 28), f(0b111011110001, 27, 16), rf(Rt, 12), f(0b101000010000, 11, 0);
+}
+
+//Move ARM register to FPSCR
+void vmsr(Register Rt, Condition cond = C_DFLT) {
+  starti;
+  f(cond, 31, 28), f(0b111011100001, 27, 16), rf(Rt, 12), f(0b101000010000, 11, 0);
+}
+
+// TODO These instructions use round towards zero mode. It is possible
+//  for the mode to be taken from the FPSCR however it doesn't do it currently
+#define INSN(NAME, decode2, b19, op, is64bit)                                        \
+  void NAME(FloatRegister Rd, FloatRegister Rm, Condition cond = C_DFLT) {           \
+    starti;                                                                          \
+    fp_instr_base(is64bit, cond);                                                    \
+    f(0b1011, 23, 20), f(b19, 19), f(decode2, 18, 16), f(op, 7), f(0b100, 6, 4);     \
+    fp_rencode(Rd, is64bit, 12, 22);                                                 \
+    fp_rencode(Rm, is64bit, 0, 5);                                                   \
+  }
+  INSN(vcvt_s32_f32, 0b101, 1, 1, 0);
+  INSN(vcvt_s32_f64, 0b101, 1, 1, 1);
+  INSN(vcvt_u32_f32, 0b100, 1, 1, 0);
+  INSN(vcvt_u32_f64, 0b100, 1, 1, 1);
+
+  INSN(vcvt_f64_s32, 0b000, 1, 1, 1);
+  INSN(vcvt_f64_u32, 0b000, 1, 0, 1);
+  INSN(vcvt_f32_s32, 0b000, 1, 1, 0);
+  INSN(vcvt_f32_u32, 0b000, 1, 0, 0);
+
+  INSN(vcvt_f32_f64, 0b111, 0, 1, 1);
+  INSN(vcvt_f64_f32, 0b111, 0, 1, 0);
+#undef INSN
+
+//Vector load/store
+ private:
+  void fp_ldst_instr(int decode, bool is64bit, const Address& adr, Condition cond);
+ public:
+
+#define INSN(NAME, decode, is64bit)                                                  \
+  void NAME(FloatRegister Vd, const Address &adr, Condition cond = C_DFLT) {         \
+    starti;                                                                          \
+    fp_ldst_instr(decode, is64bit, adr, cond);                                       \
+    fp_rencode(Vd, is64bit, 12, 22);                                                 \
+  }                                                                                  \
+  void NAME(FloatRegister Vd, address dest, Condition cond = C_DFLT) {               \
+    long offset = dest - pc();                                                       \
+    NAME(Vd, Address(r15_pc, offset), cond);                                         \
+  }                                                                                  \
+  void NAME(FloatRegister Vd, address dest, relocInfo::relocType rtype,              \
+            Condition cond = C_DFLT) {                                               \
+    guarantee(rtype == relocInfo::internal_word_type,                                \
+              "only internal_word_type relocs make sense here");                     \
+    NAME(Vd, InternalAddress(dest), cond);                                           \
+  }                                                                                  \
+  void NAME(FloatRegister Vd, Label &L, Condition cond = C_DFLT) {                   \
+    wrap_label(Vd, L, cond, &Assembler::NAME);                                       \
+  }
+  INSN(vstr_f64, 0b10000, 1);
+  INSN(vstr_f32, 0b10000, 0);
+  INSN(vldr_f64, 0b10001, 1);
+  INSN(vldr_f32, 0b10001, 0);
+#undef INSN
+
+// This is a hack. Because of the way floating point registers have been used we reach a
+// tricky situation when calling out the C land that doesn't expect all single precision
+// arguments to be on a double boundary.
+  void fp_rencode_real(int reg_val, bool is64bit, int base, int bit) {
+    if(is64bit) {
+      f( reg_val >> 1, base + 3, base);
+      f( reg_val & 1, bit);
+    } else {
+      f( reg_val & 0xf, base + 3, base);
+      f( reg_val >> 4, bit);
+    }
+  }
+
+  void vldr_f32_real(int reg_val, const Address &adr, Condition cond = C_DFLT) {
+    starti;
+    fp_ldst_instr(0b10001, false, adr, cond);
+    fp_rencode_real(reg_val, false, 12, 22);
+  }
+
+ private:
+  enum fp_mode { ia_wb, ia, db_wb };
+  void fp_ldst_mul(Register Rn, int regset, bool load, bool is64bit, enum fp_mode mode, Condition cond);
+ public:
+// A note here - load/store multiple only works on consecutive vector registers.
+// The 32bit version therefore works on consecutive 32bit float registers.
+// We are not using consecutive registers for single precision and so for single
+// precision storage only one register is allowed.
+#define INSN(NAME, EXT, is64bit, load)                                               \
+  inline void NAME##ia##EXT(Register Rn, unsigned regset, bool wb = true,            \
+                            Condition cond = C_DFLT) {                               \
+    fp_ldst_mul(Rn, regset, load, is64bit,                                           \
+                (enum fp_mode)( ia_wb + ( wb?0:1 )), cond);                          \
+  }                                                                                  \
+  inline void NAME##db##EXT(Register Rn, unsigned regset, Condition cond = C_DFLT) { \
+    fp_ldst_mul(Rn, regset, load, is64bit, db_wb, cond);                             \
+  }
+  INSN(vldm, _f32, 0, 1);
+  INSN(vldm, _f64, 1, 1);
+  INSN(vstm, _f32, 0, 0);
+  INSN(vstm, _f64, 1, 0);
+#undef INSN
+
+#undef ZERO_ADDR_REG
+#undef ONES_ADDR_REG
+
+
+  Assembler(CodeBuffer* code) : AbstractAssembler(code) {}
+
+  virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
+                                                Register tmp,
+                                                int offset) {
+    ShouldNotCallThis();
+    return RegisterOrConstant();
+  }
+
+  // Stack overflow checking
+  virtual void bang_stack_with_offset(int offset);
+
+  //static bool operand_valid_for_logical_immediate(bool is32, uint64_t imm);
+  static bool operand_valid_for_add_sub_immediate(long imm);
+  //static bool operand_valid_for_float_immediate(double imm);
+  static bool operand_valid_for_mov_immediate(u_int32_t imm, bool s);
+
+  void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
+  void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
+};
+
+inline Assembler::Membar_mask_bits operator|(Assembler::Membar_mask_bits a,
+                                             Assembler::Membar_mask_bits b) {
+  return Assembler::Membar_mask_bits(unsigned(a)|unsigned(b));
+}
+
+Instruction_aarch32::~Instruction_aarch32() {
+  assem->emit();
+}
+
+#undef starti
+
+// Invert a condition
+inline const Assembler::Condition operator~(const Assembler::Condition cond) {
+  return Assembler::Condition(int(cond) ^ 1);
+}
+
+class BiasedLockingCounters;
+
+extern "C" void das(uint64_t start, int len);
+
+#endif // CPU_AARCH32_VM_ASSEMBLER_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/assembler_aarch32.inline.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_ASSEMBLER_AARCH32_INLINE_HPP
+#define CPU_AARCH32_VM_ASSEMBLER_AARCH32_INLINE_HPP
+
+#include "asm/assembler.inline.hpp"
+#include "asm/codeBuffer.hpp"
+#include "code/codeCache.hpp"
+
+#endif // CPU_AARCH32_VM_ASSEMBLER_AARCH32_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/bytecodeInterpreter_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "interpreter/bytecodeInterpreter.hpp"
+#include "interpreter/bytecodeInterpreter.inline.hpp"
+#include "interpreter/interpreter.hpp"
+#include "interpreter/interpreterRuntime.hpp"
+#include "oops/methodData.hpp"
+#include "oops/method.hpp"
+#include "oops/oop.inline.hpp"
+#include "prims/jvmtiExport.hpp"
+#include "prims/jvmtiThreadState.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/frame.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "runtime/synchronizer.hpp"
+#include "runtime/vframeArray.hpp"
+#include "utilities/debug.hpp"
+#include "interp_masm_aarch32.hpp"
+
+#ifdef CC_INTERP
+
+#endif // CC_INTERP (all)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/bytecodeInterpreter_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_BYTECODEINTERPRETER_AARCH32_HPP
+#define CPU_AARCH32_VM_BYTECODEINTERPRETER_AARCH32_HPP
+
+// Platform specific for C++ based Interpreter
+
+private:
+
+    interpreterState _self_link;          /*  Previous interpreter state  */ /* sometimes points to self??? */
+    address   _result_handler;            /* temp for saving native result handler */
+    intptr_t* _sender_sp;                 /* sender's sp before stack (locals) extension */
+
+    address   _extra_junk1;               /* temp to save on recompiles */
+    address   _extra_junk2;               /* temp to save on recompiles */
+    address   _extra_junk3;               /* temp to save on recompiles */
+    // address dummy_for_native2;         /* a native frame result handler would be here... */
+    // address dummy_for_native1;         /* native result type stored here in a interpreter native frame */
+    address   _extra_junk4;               /* temp to save on recompiles */
+    address   _extra_junk5;               /* temp to save on recompiles */
+    address   _extra_junk6;               /* temp to save on recompiles */
+public:
+                                                         // we have an interpreter frame...
+inline intptr_t* sender_sp() {
+  return _sender_sp;
+}
+
+// The interpreter always has the frame anchor fully setup so we don't
+// have to do anything going to vm from the interpreter. On return
+// we do have to clear the flags in case they we're modified to
+// maintain the stack walking invariants.
+//
+#define SET_LAST_JAVA_FRAME()
+
+#define RESET_LAST_JAVA_FRAME()
+
+/*
+ * Macros for accessing the stack.
+ */
+#undef STACK_INT
+#undef STACK_FLOAT
+#undef STACK_ADDR
+#undef STACK_OBJECT
+#undef STACK_DOUBLE
+#undef STACK_LONG
+
+// JavaStack Implementation
+
+#define GET_STACK_SLOT(offset)    (*((intptr_t*) &topOfStack[-(offset)]))
+#define STACK_SLOT(offset)    ((address) &topOfStack[-(offset)])
+#define STACK_ADDR(offset)    (*((address *) &topOfStack[-(offset)]))
+#define STACK_INT(offset)     (*((jint*) &topOfStack[-(offset)]))
+#define STACK_FLOAT(offset)   (*((jfloat *) &topOfStack[-(offset)]))
+#define STACK_OBJECT(offset)  (*((oop *) &topOfStack [-(offset)]))
+#define STACK_DOUBLE(offset)  (((VMJavaVal64*) &topOfStack[-(offset)])->d)
+#define STACK_LONG(offset)    (((VMJavaVal64 *) &topOfStack[-(offset)])->l)
+
+#define SET_STACK_SLOT(value, offset)   (*(intptr_t*)&topOfStack[-(offset)] = *(intptr_t*)(value))
+#define SET_STACK_ADDR(value, offset)   (*((address *)&topOfStack[-(offset)]) = (value))
+#define SET_STACK_INT(value, offset)    (*((jint *)&topOfStack[-(offset)]) = (value))
+#define SET_STACK_FLOAT(value, offset)  (*((jfloat *)&topOfStack[-(offset)]) = (value))
+#define SET_STACK_OBJECT(value, offset) (*((oop *)&topOfStack[-(offset)]) = (value))
+#define SET_STACK_DOUBLE(value, offset) (((VMJavaVal64*)&topOfStack[-(offset)])->d = (value))
+#define SET_STACK_DOUBLE_FROM_ADDR(addr, offset) (((VMJavaVal64*)&topOfStack[-(offset)])->d =  \
+                                                 ((VMJavaVal64*)(addr))->d)
+#define SET_STACK_LONG(value, offset)   (((VMJavaVal64*)&topOfStack[-(offset)])->l = (value))
+#define SET_STACK_LONG_FROM_ADDR(addr, offset)   (((VMJavaVal64*)&topOfStack[-(offset)])->l =  \
+                                                 ((VMJavaVal64*)(addr))->l)
+// JavaLocals implementation
+
+#define LOCALS_SLOT(offset)    ((intptr_t*)&locals[-(offset)])
+#define LOCALS_ADDR(offset)    ((address)locals[-(offset)])
+#define LOCALS_INT(offset)     ((jint)(locals[-(offset)]))
+#define LOCALS_FLOAT(offset)   (*((jfloat*)&locals[-(offset)]))
+#define LOCALS_OBJECT(offset)  ((oop)locals[-(offset)])
+#define LOCALS_DOUBLE(offset)  (((VMJavaVal64*)&locals[-((offset) + 1)])->d)
+#define LOCALS_LONG(offset)    (((VMJavaVal64*)&locals[-((offset) + 1)])->l)
+#define LOCALS_LONG_AT(offset) (((address)&locals[-((offset) + 1)]))
+#define LOCALS_DOUBLE_AT(offset) (((address)&locals[-((offset) + 1)]))
+
+#define SET_LOCALS_SLOT(value, offset)    (*(intptr_t*)&locals[-(offset)] = *(intptr_t *)(value))
+#define SET_LOCALS_ADDR(value, offset)    (*((address *)&locals[-(offset)]) = (value))
+#define SET_LOCALS_INT(value, offset)     (*((jint *)&locals[-(offset)]) = (value))
+#define SET_LOCALS_FLOAT(value, offset)   (*((jfloat *)&locals[-(offset)]) = (value))
+#define SET_LOCALS_OBJECT(value, offset)  (*((oop *)&locals[-(offset)]) = (value))
+#define SET_LOCALS_DOUBLE(value, offset)  (((VMJavaVal64*)&locals[-((offset)+1)])->d = (value))
+#define SET_LOCALS_LONG(value, offset)    (((VMJavaVal64*)&locals[-((offset)+1)])->l = (value))
+#define SET_LOCALS_DOUBLE_FROM_ADDR(addr, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->d = \
+                                                  ((VMJavaVal64*)(addr))->d)
+#define SET_LOCALS_LONG_FROM_ADDR(addr, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->l = \
+                                                ((VMJavaVal64*)(addr))->l)
+
+#endif // CPU_AARCH32_VM_BYTECODEINTERPRETER_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/bytecodeInterpreter_aarch32.inline.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_BYTECODEINTERPRETER_AARCH32_INLINE_HPP
+#define CPU_AARCH32_VM_BYTECODEINTERPRETER_AARCH32_INLINE_HPP
+
+// Inline interpreter functions for IA32
+
+inline jfloat BytecodeInterpreter::VMfloatAdd(jfloat op1, jfloat op2) { return op1 + op2; }
+inline jfloat BytecodeInterpreter::VMfloatSub(jfloat op1, jfloat op2) { return op1 - op2; }
+inline jfloat BytecodeInterpreter::VMfloatMul(jfloat op1, jfloat op2) { return op1 * op2; }
+inline jfloat BytecodeInterpreter::VMfloatDiv(jfloat op1, jfloat op2) { return op1 / op2; }
+inline jfloat BytecodeInterpreter::VMfloatRem(jfloat op1, jfloat op2) { return fmod(op1, op2); }
+
+inline jfloat BytecodeInterpreter::VMfloatNeg(jfloat op) { return -op; }
+
+inline int32_t BytecodeInterpreter::VMfloatCompare(jfloat op1, jfloat op2, int32_t direction) {
+  return ( op1 < op2 ? -1 :
+               op1 > op2 ? 1 :
+                   op1 == op2 ? 0 :
+                       (direction == -1 || direction == 1) ? direction : 0);
+
+}
+
+inline void BytecodeInterpreter::VMmemCopy64(uint32_t to[2], const uint32_t from[2]) {
+  // x86 can do unaligned copies but not 64bits at a time
+  to[0] = from[0]; to[1] = from[1];
+}
+
+// The long operations depend on compiler support for "long long" on x86
+
+inline jlong BytecodeInterpreter::VMlongAdd(jlong op1, jlong op2) {
+  return op1 + op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongAnd(jlong op1, jlong op2) {
+  return op1 & op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongDiv(jlong op1, jlong op2) {
+  // QQQ what about check and throw...
+  return op1 / op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongMul(jlong op1, jlong op2) {
+  return op1 * op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongOr(jlong op1, jlong op2) {
+  return op1 | op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongSub(jlong op1, jlong op2) {
+  return op1 - op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongXor(jlong op1, jlong op2) {
+  return op1 ^ op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongRem(jlong op1, jlong op2) {
+  return op1 % op2;
+}
+
+inline jlong BytecodeInterpreter::VMlongUshr(jlong op1, jint op2) {
+  // CVM did this 0x3f mask, is the really needed??? QQQ
+  return ((unsigned long long) op1) >> (op2 & 0x3F);
+}
+
+inline jlong BytecodeInterpreter::VMlongShr(jlong op1, jint op2) {
+  return op1 >> (op2 & 0x3F);
+}
+
+inline jlong BytecodeInterpreter::VMlongShl(jlong op1, jint op2) {
+  return op1 << (op2 & 0x3F);
+}
+
+inline jlong BytecodeInterpreter::VMlongNeg(jlong op) {
+  return -op;
+}
+
+inline jlong BytecodeInterpreter::VMlongNot(jlong op) {
+  return ~op;
+}
+
+inline int32_t BytecodeInterpreter::VMlongLtz(jlong op) {
+  return (op <= 0);
+}
+
+inline int32_t BytecodeInterpreter::VMlongGez(jlong op) {
+  return (op >= 0);
+}
+
+inline int32_t BytecodeInterpreter::VMlongEqz(jlong op) {
+  return (op == 0);
+}
+
+inline int32_t BytecodeInterpreter::VMlongEq(jlong op1, jlong op2) {
+  return (op1 == op2);
+}
+
+inline int32_t BytecodeInterpreter::VMlongNe(jlong op1, jlong op2) {
+  return (op1 != op2);
+}
+
+inline int32_t BytecodeInterpreter::VMlongGe(jlong op1, jlong op2) {
+  return (op1 >= op2);
+}
+
+inline int32_t BytecodeInterpreter::VMlongLe(jlong op1, jlong op2) {
+  return (op1 <= op2);
+}
+
+inline int32_t BytecodeInterpreter::VMlongLt(jlong op1, jlong op2) {
+  return (op1 < op2);
+}
+
+inline int32_t BytecodeInterpreter::VMlongGt(jlong op1, jlong op2) {
+  return (op1 > op2);
+}
+
+inline int32_t BytecodeInterpreter::VMlongCompare(jlong op1, jlong op2) {
+  return (VMlongLt(op1, op2) ? -1 : VMlongGt(op1, op2) ? 1 : 0);
+}
+
+// Long conversions
+
+inline jdouble BytecodeInterpreter::VMlong2Double(jlong val) {
+  return (jdouble) val;
+}
+
+inline jfloat BytecodeInterpreter::VMlong2Float(jlong val) {
+  return (jfloat) val;
+}
+
+inline jint BytecodeInterpreter::VMlong2Int(jlong val) {
+  return (jint) val;
+}
+
+// Double Arithmetic
+
+inline jdouble BytecodeInterpreter::VMdoubleAdd(jdouble op1, jdouble op2) {
+  return op1 + op2;
+}
+
+inline jdouble BytecodeInterpreter::VMdoubleDiv(jdouble op1, jdouble op2) {
+  // Divide by zero... QQQ
+  return op1 / op2;
+}
+
+inline jdouble BytecodeInterpreter::VMdoubleMul(jdouble op1, jdouble op2) {
+  return op1 * op2;
+}
+
+inline jdouble BytecodeInterpreter::VMdoubleNeg(jdouble op) {
+  return -op;
+}
+
+inline jdouble BytecodeInterpreter::VMdoubleRem(jdouble op1, jdouble op2) {
+  return fmod(op1, op2);
+}
+
+inline jdouble BytecodeInterpreter::VMdoubleSub(jdouble op1, jdouble op2) {
+  return op1 - op2;
+}
+
+inline int32_t BytecodeInterpreter::VMdoubleCompare(jdouble op1, jdouble op2, int32_t direction) {
+  return ( op1 < op2 ? -1 :
+               op1 > op2 ? 1 :
+                   op1 == op2 ? 0 :
+                       (direction == -1 || direction == 1) ? direction : 0);
+}
+
+// Double Conversions
+
+inline jfloat BytecodeInterpreter::VMdouble2Float(jdouble val) {
+  return (jfloat) val;
+}
+
+// Float Conversions
+
+inline jdouble BytecodeInterpreter::VMfloat2Double(jfloat op) {
+  return (jdouble) op;
+}
+
+// Integer Arithmetic
+
+inline jint BytecodeInterpreter::VMintAdd(jint op1, jint op2) {
+  return op1 + op2;
+}
+
+inline jint BytecodeInterpreter::VMintAnd(jint op1, jint op2) {
+  return op1 & op2;
+}
+
+inline jint BytecodeInterpreter::VMintDiv(jint op1, jint op2) {
+  /* it's possible we could catch this special case implicitly */
+  if ((juint)op1 == 0x80000000 && op2 == -1) return op1;
+  else return op1 / op2;
+}
+
+inline jint BytecodeInterpreter::VMintMul(jint op1, jint op2) {
+  return op1 * op2;
+}
+
+inline jint BytecodeInterpreter::VMintNeg(jint op) {
+  return -op;
+}
+
+inline jint BytecodeInterpreter::VMintOr(jint op1, jint op2) {
+  return op1 | op2;
+}
+
+inline jint BytecodeInterpreter::VMintRem(jint op1, jint op2) {
+  /* it's possible we could catch this special case implicitly */
+  if ((juint)op1 == 0x80000000 && op2 == -1) return 0;
+  else return op1 % op2;
+}
+
+inline jint BytecodeInterpreter::VMintShl(jint op1, jint op2) {
+  return op1 << op2;
+}
+
+inline jint BytecodeInterpreter::VMintShr(jint op1, jint op2) {
+  return op1 >> (op2 & 0x1f);
+}
+
+inline jint BytecodeInterpreter::VMintSub(jint op1, jint op2) {
+  return op1 - op2;
+}
+
+inline jint BytecodeInterpreter::VMintUshr(jint op1, jint op2) {
+  return ((juint) op1) >> (op2 & 0x1f);
+}
+
+inline jint BytecodeInterpreter::VMintXor(jint op1, jint op2) {
+  return op1 ^ op2;
+}
+
+inline jdouble BytecodeInterpreter::VMint2Double(jint val) {
+  return (jdouble) val;
+}
+
+inline jfloat BytecodeInterpreter::VMint2Float(jint val) {
+  return (jfloat) val;
+}
+
+inline jlong BytecodeInterpreter::VMint2Long(jint val) {
+  return (jlong) val;
+}
+
+inline jchar BytecodeInterpreter::VMint2Char(jint val) {
+  return (jchar) val;
+}
+
+inline jshort BytecodeInterpreter::VMint2Short(jint val) {
+  return (jshort) val;
+}
+
+inline jbyte BytecodeInterpreter::VMint2Byte(jint val) {
+  return (jbyte) val;
+}
+
+#endif // CPU_AARCH32_VM_BYTECODEINTERPRETER_AARCH32_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/bytecodes_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "interpreter/bytecodes.hpp"
+
+void Bytecodes::pd_initialize() {
+  // No AArch32 specific initialization
+}
+
+Bytecodes::Code Bytecodes::pd_base_code_for(Code code) {
+  // No AArch32 specific bytecodes
+  return code;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/bytecodes_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_BYTECODES_AARCH32_HPP
+#define CPU_AARCH32_VM_BYTECODES_AARCH32_HPP
+
+// No AArch32 specific bytecodes
+
+#endif // CPU_AARCH32_VM_BYTECODES_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/bytes_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_BYTES_AARCH32_HPP
+#define CPU_AARCH32_VM_BYTES_AARCH32_HPP
+
+#include "memory/allocation.hpp"
+
+class Bytes: AllStatic {
+ public:
+  // Returns true if the byte ordering used by Java is different from the native byte ordering
+  // of the underlying machine. For example, this is true for Intel x86, but false for Solaris
+  // on Sparc.
+  static inline bool is_Java_byte_ordering_different(){ return true; }
+
+
+  // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering
+  // (no special code is needed since x86 CPUs can access unaligned data)
+  static inline u2   get_native_u2(address p)         { return *(u2*)p; }
+  static inline u4   get_native_u4(address p)         { return *(u4*)p; }
+  static inline u8   get_native_u8(address p)         { return *(u8*)p; }
+
+  static inline void put_native_u2(address p, u2 x)   { *(u2*)p = x; }
+  static inline void put_native_u4(address p, u4 x)   { *(u4*)p = x; }
+  static inline void put_native_u8(address p, u8 x)   { *(u8*)p = x; }
+
+
+  // Efficient reading and writing of unaligned unsigned data in Java
+  // byte ordering (i.e. big-endian ordering). Byte-order reversal is
+  // needed since x86 CPUs use little-endian format.
+  static inline u2   get_Java_u2(address p)           { return swap_u2(get_native_u2(p)); }
+  static inline u4   get_Java_u4(address p)           { return swap_u4(get_native_u4(p)); }
+  static inline u8   get_Java_u8(address p)           { return swap_u8(get_native_u8(p)); }
+
+  static inline void put_Java_u2(address p, u2 x)     { put_native_u2(p, swap_u2(x)); }
+  static inline void put_Java_u4(address p, u4 x)     { put_native_u4(p, swap_u4(x)); }
+  static inline void put_Java_u8(address p, u8 x)     { put_native_u8(p, swap_u8(x)); }
+
+
+  // Efficient swapping of byte ordering
+  static inline u2   swap_u2(u2 x);                   // compiler-dependent implementation
+  static inline u4   swap_u4(u4 x);                   // compiler-dependent implementation
+  static inline u8   swap_u8(u8 x);
+};
+
+
+// The following header contains the implementations of swap_u2, swap_u4, and swap_u8[_base]
+
+#ifdef TARGET_OS_ARCH_linux_aarch32
+# include "bytes_linux_aarch32.inline.hpp"
+#endif
+
+#endif // CPU_AARCH32_VM_BYTES_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/codeBuffer_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_CODEBUFFER_AARCH32_HPP
+#define CPU_AARCH32_VM_CODEBUFFER_AARCH32_HPP
+
+private:
+  void pd_initialize() {}
+
+public:
+  void flush_bundle(bool start_new_bundle) {}
+
+#endif // CPU_AARCH32_VM_CODEBUFFER_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/compiledIC_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
+#include "code/icBuffer.hpp"
+#include "code/nmethod.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
+
+// Release the CompiledICHolder* associated with this call site is there is one.
+void CompiledIC::cleanup_call_site(virtual_call_Relocation* call_site) {
+  // This call site might have become stale so inspect it carefully.
+  NativeCall* call = nativeCall_at(call_site->addr());
+  if (is_icholder_entry(call->destination())) {
+    NativeMovConstReg* value = nativeMovConstReg_at(call_site->cached_value());
+    InlineCacheBuffer::queue_for_release((CompiledICHolder*)value->data());
+  }
+}
+
+bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
+  // This call site might have become stale so inspect it carefully.
+  NativeCall* call = nativeCall_at(call_site->addr());
+  return is_icholder_entry(call->destination());
+}
+
+// ----------------------------------------------------------------------------
+
+#define __ _masm.
+void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+  // Stub is fixed up when the corresponding call is converted from
+  // calling compiled code to calling interpreted code.
+  // mov rmethod, 0
+  // jmp -4 # to self
+
+  address mark = cbuf.insts_mark();  // Get mark within main instrs section.
+
+  // Note that the code buffer's insts_mark is always relative to insts.
+  // That's why we must use the macroassembler to generate a stub.
+  MacroAssembler _masm(&cbuf);
+
+  address base = __ start_a_stub(to_interp_stub_size()*2);
+
+  int offset = __ offset();
+  if (base == NULL)  return;  // CodeBuffer::expand failed
+  // static stub relocation stores the instruction address of the call
+  __ relocate(static_stub_Relocation::spec(mark));
+  // static stub relocation also tags the Method* in the code-stream.
+  __ mov_metadata(rmethod, (Metadata*)NULL);
+  __ movptr(rscratch1, 0);
+  __ b(rscratch1);
+
+  assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big");
+  __ end_a_stub();
+}
+#undef __
+
+int CompiledStaticCall::to_interp_stub_size() {
+  return 7 * NativeInstruction::instruction_size;
+}
+
+// Relocation entries for call stub, compiled java to interpreter.
+int CompiledStaticCall::reloc_to_interp_stub() {
+  return 4; // 3 in emit_to_interp_stub + 1 in emit_call
+}
+
+void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) {
+  address stub = find_stub();
+  guarantee(stub != NULL, "stub not found");
+
+  if (TraceICs) {
+    ResourceMark rm;
+    tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
+                  p2i(instruction_address()),
+                  callee->name_and_sig_as_C_string());
+  }
+
+  // Creation also verifies the object.
+  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
+#ifndef PRODUCT
+  NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
+
+  assert(method_holder->data() == 0 || method_holder->data() == (intptr_t)callee(),
+         "a) MT-unsafe modification of inline cache");
+  assert(method_holder->data() == 0 || jump->jump_destination() == entry,
+         "b) MT-unsafe modification of inline cache");
+#endif
+  // Update stub.
+  method_holder->set_data((intptr_t)callee());
+  NativeGeneralJump::insert_unconditional(method_holder->next_instruction_address(), entry);
+  ICache::invalidate_range(stub, to_interp_stub_size());
+  // Update jump to call.
+  set_destination_mt_safe(stub);
+}
+
+void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+  assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
+  // Reset stub.
+  address stub = static_stub->addr();
+  assert(stub != NULL, "stub not found");
+  // Creation also verifies the object.
+  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
+  method_holder->set_data(0);
+}
+
+//-----------------------------------------------------------------------------
+// Non-product mode code
+#ifndef PRODUCT
+
+void CompiledStaticCall::verify() {
+  // Verify call.
+  NativeCall::verify();
+  if (os::is_MP()) {
+    verify_alignment();
+  }
+
+  // Verify stub.
+  address stub = find_stub();
+  assert(stub != NULL, "no stub found for static call");
+  // Creation also verifies the object.
+  NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
+  NativeJump*        jump          = nativeJump_at(method_holder->next_instruction_address());
+
+  // Verify state.
+  assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
+}
+
+#endif // !PRODUCT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/copy_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_COPY_AARCH32_HPP
+#define CPU_AARCH32_VM_COPY_AARCH32_HPP
+
+// Inline functions for memory copy and fill.
+
+// Contains inline asm implementations
+#ifdef TARGET_OS_ARCH_linux_aarch32
+# include "copy_linux_aarch32.inline.hpp"
+#endif
+
+
+static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
+/*  julong* to = (julong*) tohw;
+  julong  v  = ((julong) value << 32) | value;
+  while (count-- > 0) {
+    *to++ = v;
+  }*/
+  juint *to = (juint*)tohw;
+  while(count-- > 0) {
+    *to++ = value;
+  }
+}
+
+static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) {
+  pd_fill_to_words(tohw, count, value);
+}
+
+static void pd_fill_to_bytes(void* to, size_t count, jubyte value) {
+  (void)memset(to, value, count);
+}
+
+static void pd_zero_to_words(HeapWord* tohw, size_t count) {
+  pd_fill_to_words(tohw, count, 0);
+}
+
+static void pd_zero_to_bytes(void* to, size_t count) {
+  (void)memset(to, 0, count);
+}
+
+#endif // CPU_AARCH32_VM_COPY_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/cppInterpreterGenerator_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_CPPINTERPRETERGENERATOR_AARCH32_HPP
+#define CPU_AARCH32_VM_CPPINTERPRETERGENERATOR_AARCH32_HPP
+
+ protected:
+
+  void generate_more_monitors();
+  void generate_deopt_handling();
+
+#endif // CPU_AARCH32_VM_CPPINTERPRETERGENERATOR_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/cpustate_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef _CPU_STATE_H
+#define _CPU_STATE_H
+
+#include <sys/types.h>
+
+/*
+ * symbolic names used to identify general registers which also match
+ * the registers indices in machine code
+ *
+ * We have 32 general registers which can be read/written as 32 bit or
+ * 64 bit sources/sinks and are appropriately referred to as Wn or Xn
+ * in the assembly code.  Some instructions mix these access modes
+ * (e.g. ADD X0, X1, W2) so the implementation of the instruction
+ * needs to *know* which type of read or write access is required.
+ */
+enum GReg {
+  R0,
+  R1,
+  R2,
+  R3,
+  R4,
+  R5,
+  R6,
+  R7,
+  R8,
+  R9,
+  R10,
+  R11,
+  R12,
+  R13,
+  R14,
+  R15,
+  R16,
+  R17,
+  R18,
+  R19,
+  R20,
+  R21,
+  R22,
+  R23,
+  R24,
+  R25,
+  R26,
+  R27,
+  R28,
+  R29,
+  R30,
+  R31,
+  // and now the aliases
+  RSCRATCH1=R8,
+  RSCRATCH2=R9,
+  RMETHOD=R12,
+  RESP=R20,
+  RDISPATCH=R21,
+  RBCP=R22,
+  RLOCALS=R24,
+  RMONITORS=R25,
+  RCPOOL=R26,
+  RHEAPBASE=R27,
+  RTHREAD=R28,
+  FP = R29,
+  LR = R30,
+  SP = R31,
+  ZR = R31
+};
+
+/*
+ * symbolic names used to refer to floating point registers which also
+ * match the registers indices in machine code
+ *
+ * We have 32 FP registers which can be read/written as 8, 16, 32, 64
+ * and 128 bit sources/sinks and are appropriately referred to as Bn,
+ * Hn, Sn, Dn and Qn in the assembly code. Some instructions mix these
+ * access modes (e.g. FCVT S0, D0) so the implementation of the
+ * instruction needs to *know* which type of read or write access is
+ * required.
+ */
+
+enum VReg {
+  V0,
+  V1,
+  V2,
+  V3,
+  V4,
+  V5,
+  V6,
+  V7,
+  V8,
+  V9,
+  V10,
+  V11,
+  V12,
+  V13,
+  V14,
+  V15,
+  V16,
+  V17,
+  V18,
+  V19,
+  V20,
+  V21,
+  V22,
+  V23,
+  V24,
+  V25,
+  V26,
+  V27,
+  V28,
+  V29,
+  V30,
+  V31,
+};
+
+/**
+ * all the different integer bit patterns for the components of a
+ * general register are overlaid here using a union so as to allow all
+ * reading and writing of the desired bits.
+ *
+ * n.b. the ARM spec says that when you write a 32 bit register you
+ * are supposed to write the low 32 bits and zero the high 32
+ * bits. But we don't actually have to care about this because Java
+ * will only ever consume the 32 bits value as a 64 bit quantity after
+ * an explicit extend.
+ */
+union GRegisterValue
+{
+  int8_t s8;
+  int16_t s16;
+  int32_t s32;
+  int64_t s64;
+  u_int8_t u8;
+  u_int16_t u16;
+  u_int32_t u32;
+  u_int64_t u64;
+};
+
+class GRegister
+{
+public:
+  GRegisterValue value;
+};
+
+/*
+ * float registers provide for storage of a single, double or quad
+ * word format float in the same register. single floats are not
+ * paired within each double register as per 32 bit arm. instead each
+ * 128 bit register Vn embeds the bits for Sn, and Dn in the lower
+ * quarter and half, respectively, of the bits for Qn.
+ *
+ * The upper bits can also be accessed as single or double floats by
+ * the float vector operations using indexing e.g. V1.D[1], V1.S[3]
+ * etc and, for SIMD operations using a horrible index range notation.
+ *
+ * The spec also talks about accessing float registers as half words
+ * and bytes with Hn and Bn providing access to the low 16 and 8 bits
+ * of Vn but it is not really clear what these bits represent. We can
+ * probably ignore this for Java anyway. However, we do need to access
+ * the raw bits at 32 and 64 bit resolution to load to/from integer
+ * registers.
+ */
+
+union FRegisterValue
+{
+  float s;
+  double d;
+  long double q;
+  // eventually we will need to be able to access the data as a vector
+  // the integral array elements allow us to access the bits in s, d,
+  // q, vs and vd at an appropriate level of granularity
+  u_int8_t vb[16];
+  u_int16_t vh[8];
+  u_int32_t vw[4];
+  u_int64_t vx[2];
+  float vs[4];
+  double vd[2];
+};
+
+class FRegister
+{
+public:
+  FRegisterValue value;
+};
+
+/*
+ * CPSR register -- this does not exist as a directly accessible
+ * register but we need to store the flags so we can implement
+ * flag-seting and flag testing operations
+ *
+ * we can possibly use injected x86 asm to report the outcome of flag
+ * setting operations. if so we will need to grab the flags
+ * immediately after the operation in order to ensure we don't lose
+ * them because of the actions of the simulator. so we still need
+ * somewhere to store the condition codes.
+ */
+
+class CPSRRegister
+{
+public:
+  u_int32_t value;
+
+/*
+ * condition register bit select values
+ *
+ * the order of bits here is important because some of
+ * the flag setting conditional instructions employ a
+ * bit field to populate the flags when a false condition
+ * bypasses execution of the operation and we want to
+ * be able to assign the flags register using the
+ * supplied value.
+ */
+
+  enum CPSRIdx {
+    V_IDX,
+    C_IDX,
+    Z_IDX,
+    N_IDX
+  };
+
+  enum CPSRMask {
+    V = 1 << V_IDX,
+    C = 1 << C_IDX,
+    Z = 1 << Z_IDX,
+    N = 1 << N_IDX
+  };
+
+  static const int CPSR_ALL_FLAGS = (V | C | Z | N);
+};
+
+// auxiliary function to assemble the relevant bits from
+// the x86 EFLAGS register into an ARM CPSR value
+
+#define X86_V_IDX 11
+#define X86_C_IDX 0
+#define X86_Z_IDX 6
+#define X86_N_IDX 7
+
+#define X86_V (1 << X86_V_IDX)
+#define X86_C (1 << X86_C_IDX)
+#define X86_Z (1 << X86_Z_IDX)
+#define X86_N (1 << X86_N_IDX)
+
+inline u_int32_t convertX86Flags(u_int32_t x86flags)
+{
+  u_int32_t flags;
+  // set N flag
+  flags = ((x86flags & X86_N) >> X86_N_IDX);
+  // shift then or in Z flag
+  flags <<= 1;
+  flags |= ((x86flags & X86_Z) >> X86_Z_IDX);
+  // shift then or in C flag
+  flags <<= 1;
+  flags |= ((x86flags & X86_C) >> X86_C_IDX);
+  // shift then or in V flag
+  flags <<= 1;
+  flags |= ((x86flags & X86_V) >> X86_V_IDX);
+
+  return flags;
+}
+
+inline u_int32_t convertX86FlagsFP(u_int32_t x86flags)
+{
+  // x86 flags set by fcomi(x,y) are ZF:PF:CF
+  // (yes, that's PF for parity, WTF?)
+  // where
+  // 0) 0:0:0 means x > y
+  // 1) 0:0:1 means x < y
+  // 2) 1:0:0 means x = y
+  // 3) 1:1:1 means x and y are unordered
+  // note that we don't have to check PF so
+  // we really have a simple 2-bit case switch
+  // the corresponding ARM64 flags settings
+  //  in hi->lo bit order are
+  // 0) --C-
+  // 1) N---
+  // 2) -ZC-
+  // 3) --CV
+
+  static u_int32_t armFlags[] = {
+      0b0010,
+      0b1000,
+      0b0110,
+      0b0011
+  };
+  // pick out the ZF and CF bits
+  u_int32_t zc = ((x86flags & X86_Z) >> X86_Z_IDX);
+  zc <<= 1;
+  zc |= ((x86flags & X86_C) >> X86_C_IDX);
+
+  return armFlags[zc];
+}
+
+/*
+ * FPSR register -- floating point status register
+
+ * this register includes IDC, IXC, UFC, OFC, DZC, IOC and QC bits,
+ * and the floating point N, Z, C, V bits but the latter are unused in
+ * aarch32 mode. the sim ignores QC for now.
+ *
+ * bit positions are as per the ARMv7 FPSCR register
+ *
+ * IDC :  7 ==> Input Denormal (cumulative exception bit)
+ * IXC :  4 ==> Inexact
+ * UFC :  3 ==> Underflow
+ * OFC :  2 ==> Overflow
+ * DZC :  1 ==> Division by Zero
+ * IOC :  0 ==> Invalid Operation
+ */
+
+class FPSRRegister
+{
+public:
+  u_int32_t value;
+  // indices for bits in the FPSR register value
+  enum FPSRIdx {
+    IO_IDX = 0,
+    DZ_IDX = 1,
+    OF_IDX = 2,
+    UF_IDX = 3,
+    IX_IDX = 4,
+    ID_IDX = 7
+  };
+  // corresponding bits as numeric values
+  enum FPSRMask {
+    IO = (1 << IO_IDX),
+    DZ = (1 << DZ_IDX),
+    OF = (1 << OF_IDX),
+    UF = (1 << UF_IDX),
+    IX = (1 << IX_IDX),
+    ID = (1 << ID_IDX)
+  };
+  static const int FPSR_ALL_FPSRS = (IO | DZ | OF | UF | IX | ID);
+};
+
+// debugger support
+
+enum PrintFormat
+{
+  FMT_DECIMAL,
+  FMT_HEX,
+  FMT_SINGLE,
+  FMT_DOUBLE,
+  FMT_QUAD,
+  FMT_MULTI
+};
+
+/*
+ * model of the registers and other state associated with the cpu
+ */
+class CPUState
+{
+  friend class AArch64Simulator;
+private:
+  // this is the PC of the instruction being executed
+  u_int64_t pc;
+  // this is the PC of the instruction to be executed next
+  // it is defaulted to pc + 4 at instruction decode but
+  // execute may reset it
+
+  u_int64_t nextpc;
+  GRegister gr[33];             // extra register at index 32 is used
+                                // to hold zero value
+  FRegister fr[32];
+  CPSRRegister cpsr;
+  FPSRRegister fpsr;
+
+public:
+
+  CPUState() {
+    gr[20].value.u64 = 0;  // establish initial condition for
+                           // checkAssertions()
+    trace_counter = 0;
+  }
+
+  // General Register access macros
+
+  // only xreg or xregs can be used as an lvalue in order to update a
+  // register. this ensures that the top part of a register is always
+  // assigned when it is written by the sim.
+
+  inline u_int64_t &xreg(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.u64;
+    } else {
+      return gr[reg].value.u64;
+    }
+  }
+
+  inline int64_t &xregs(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.s64;
+    } else {
+      return gr[reg].value.s64;
+    }
+  }
+
+  inline u_int32_t wreg(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.u32;
+    } else {
+      return gr[reg].value.u32;
+    }
+  }
+
+  inline int32_t wregs(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.s32;
+    } else {
+      return gr[reg].value.s32;
+    }
+  }
+
+  inline u_int32_t hreg(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.u16;
+    } else {
+      return gr[reg].value.u16;
+    }
+  }
+
+  inline int32_t hregs(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.s16;
+    } else {
+      return gr[reg].value.s16;
+    }
+  }
+
+  inline u_int32_t breg(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.u8;
+    } else {
+      return gr[reg].value.u8;
+    }
+  }
+
+  inline int32_t bregs(GReg reg, int r31_is_sp) {
+    if (reg == R31 && !r31_is_sp) {
+      return gr[32].value.s8;
+    } else {
+      return gr[reg].value.s8;
+    }
+  }
+
+  // FP Register access macros
+
+  // all non-vector accessors return a reference so we can both read
+  // and assign
+
+  inline float &sreg(VReg reg) {
+    return fr[reg].value.s;
+  }
+
+  inline double &dreg(VReg reg) {
+    return fr[reg].value.d;
+  }
+
+  inline long double &qreg(VReg reg) {
+    return fr[reg].value.q;
+  }
+
+  // all vector register accessors return a pointer
+
+  inline float *vsreg(VReg reg) {
+    return &fr[reg].value.vs[0];
+  }
+
+  inline double *vdreg(VReg reg) {
+    return &fr[reg].value.vd[0];
+  }
+
+  inline u_int8_t *vbreg(VReg reg) {
+    return &fr[reg].value.vb[0];
+  }
+
+  inline u_int16_t *vhreg(VReg reg) {
+    return &fr[reg].value.vh[0];
+  }
+
+  inline u_int32_t *vwreg(VReg reg) {
+    return &fr[reg].value.vw[0];
+  }
+
+  inline u_int64_t *vxreg(VReg reg) {
+    return &fr[reg].value.vx[0];
+  }
+
+  union GRegisterValue prev_sp, prev_fp;
+
+  static const int trace_size = 256;
+  u_int64_t trace_buffer[trace_size];
+  int trace_counter;
+
+  bool checkAssertions()
+  {
+    // Make sure that SP is 16-aligned
+    // Also make sure that ESP is above SP.
+    // We don't care about checking ESP if it is null, i.e. it hasn't
+    // been used yet.
+    if (gr[31].value.u64 & 0x0f) {
+      asm volatile("nop");
+      return false;
+    }
+    return true;
+  }
+
+  // pc register accessors
+
+  // this instruction can be used to fetch the current PC
+  u_int64_t getPC();
+  // instead of setting the current PC directly you can
+  // first set the next PC (either absolute or PC-relative)
+  // and later copy the next PC into the current PC
+  // this supports a default increment by 4 at instruction
+  // fetch with an optional reset by control instructions
+  u_int64_t getNextPC();
+  void setNextPC(u_int64_t next);
+  void offsetNextPC(int64_t offset);
+  // install nextpc as current pc
+  void updatePC();
+
+  // this instruction can be used to save the next PC to LR
+  // just before installing a branch PC
+  inline void saveLR() { gr[LR].value.u64 = nextpc; }
+
+  // cpsr register accessors
+  u_int32_t getCPSRRegister();
+  void setCPSRRegister(u_int32_t flags);
+  // read a specific subset of the flags as a bit pattern
+  // mask should be composed using elements of enum FlagMask
+  u_int32_t getCPSRBits(u_int32_t mask);
+  // assign a specific subset of the flags as a bit pattern
+  // mask and value should be composed using elements of enum FlagMask
+  void setCPSRBits(u_int32_t mask, u_int32_t value);
+  // test the value of a single flag returned as 1 or 0
+  u_int32_t testCPSR(CPSRRegister::CPSRIdx idx);
+  // set a single flag
+  void setCPSR(CPSRRegister::CPSRIdx idx);
+  // clear a single flag
+  void clearCPSR(CPSRRegister::CPSRIdx idx);
+  // utility method to set ARM CSPR flags from an x86 bit mask generated by integer arithmetic
+  void setCPSRRegisterFromX86(u_int64_t x86Flags);
+  // utility method to set ARM CSPR flags from an x86 bit mask generated by floating compare
+  void setCPSRRegisterFromX86FP(u_int64_t x86Flags);
+
+  // fpsr register accessors
+  u_int32_t getFPSRRegister();
+  void setFPSRRegister(u_int32_t flags);
+  // read a specific subset of the fprs bits as a bit pattern
+  // mask should be composed using elements of enum FPSRRegister::FlagMask
+  u_int32_t getFPSRBits(u_int32_t mask);
+  // assign a specific subset of the flags as a bit pattern
+  // mask and value should be composed using elements of enum FPSRRegister::FlagMask
+  void setFPSRBits(u_int32_t mask, u_int32_t value);
+  // test the value of a single flag returned as 1 or 0
+  u_int32_t testFPSR(FPSRRegister::FPSRIdx idx);
+  // set a single flag
+  void setFPSR(FPSRRegister::FPSRIdx idx);
+  // clear a single flag
+  void clearFPSR(FPSRRegister::FPSRIdx idx);
+
+  // debugger support
+  void printPC(int pending, const char *trailing = "\n");
+  void printInstr(u_int32_t instr, void (*dasm)(u_int64_t), const char *trailing = "\n");
+  void printGReg(GReg reg, PrintFormat format = FMT_HEX, const char *trailing = "\n");
+  void printVReg(VReg reg, PrintFormat format = FMT_HEX, const char *trailing = "\n");
+  void printCPSR(const char *trailing = "\n");
+  void printFPSR(const char *trailing = "\n");
+  void dumpState();
+};
+
+#endif // ifndef _CPU_STATE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/debug_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "code/codeCache.hpp"
+#include "code/nmethod.hpp"
+#include "runtime/frame.hpp"
+#include "runtime/init.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/top.hpp"
+
+void pd_ps(frame f) {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/decode_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef _DECODE_H
+#define _DECODE_H
+
+#include <sys/types.h>
+#include "cpustate_aarch32.hpp"
+
+// bitfield immediate expansion helper
+
+extern int expandLogicalImmediate(u_int32_t immN, u_int32_t immr,
+                                    u_int32_t imms, u_int64_t &bimm);
+
+
+/*
+ * codes used in conditional instructions
+ *
+ * these are passed to conditional operations to identify which
+ * condition to test for
+ */
+enum CondCode {
+  EQ = 0b0000, // meaning Z == 1
+  NE = 0b0001, // meaning Z == 0
+  HS = 0b0010, // meaning C == 1
+  CS = HS,
+  LO = 0b0011, // meaning C == 0
+  CC = LO,
+  MI = 0b0100, // meaning N == 1
+  PL = 0b0101, // meaning N == 0
+  VS = 0b0110, // meaning V == 1
+  VC = 0b0111, // meaning V == 0
+  HI = 0b1000, // meaning C == 1 && Z == 0
+  LS = 0b1001, // meaning !(C == 1 && Z == 0)
+  GE = 0b1010, // meaning N == V
+  LT = 0b1011, // meaning N != V
+  GT = 0b1100, // meaning Z == 0 && N == V
+  LE = 0b1101, // meaning !(Z == 0 && N == V)
+  AL = 0b1110, // meaning ANY
+  NV = 0b1111  // ditto
+};
+
+/*
+ * certain addressing modes for load require pre or post writeback of
+ * the computed address to a base register
+ */
+enum WriteBack {
+  Post = 0,
+  Pre = 1
+};
+
+/*
+ * certain addressing modes for load require an offset to
+ * be optionally scaled so the decode needs to pass that
+ * through to the execute routine
+ */
+enum Scaling {
+  Unscaled = 0,
+  Scaled = 1
+};
+
+/*
+ * when we do have to scale we do so by shifting using
+ * log(bytes in data element - 1) as the shift count.
+ * so we don't have to scale offsets when loading
+ * bytes.
+ */
+enum ScaleShift {
+  ScaleShift16 = 1,
+  ScaleShift32 = 2,
+  ScaleShift64 = 3,
+  ScaleShift128 = 4
+};
+
+/*
+ * one of the addressing modes for load requires a 32-bit register
+ * value to be either zero- or sign-extended for these instructions
+ * UXTW or SXTW should be passed
+ *
+ * arithmetic register data processing operations can optionally
+ * extend a portion of the second register value for these
+ * instructions the value supplied must identify the portion of the
+ * register which is to be zero- or sign-exended
+ */
+enum Extension {
+  UXTB = 0,
+  UXTH = 1,
+  UXTW = 2,
+  UXTX = 3,
+  SXTB = 4,
+  SXTH = 5,
+  SXTW = 6,
+  SXTX = 7
+};
+
+/*
+ * arithmetic and logical register data processing operations
+ * optionally perform a shift on the second register value
+ */
+enum Shift {
+  LSL = 0,
+  LSR = 1,
+  ASR = 2,
+  ROR = 3
+};
+
+/*
+ * bit twiddling helpers for instruction decode
+ */
+
+// 32 bit mask with bits [hi,...,lo] set
+
+static inline u_int32_t mask32(int hi = 31, int lo = 0)
+{
+  int nbits = (hi + 1) - lo;
+  return ((1 << nbits) - 1) << lo;
+}
+
+static inline u_int64_t mask64(int hi = 63, int lo = 0)
+{
+  int nbits = (hi + 1) - lo;
+  return ((1L << nbits) - 1) << lo;
+}
+
+// pick bits [hi,...,lo] from val
+static inline u_int32_t pick32(u_int32_t val, int hi = 31, int lo = 0)
+{
+  return (val & mask32(hi, lo));
+}
+
+// pick bits [hi,...,lo] from val
+static inline u_int64_t pick64(u_int64_t val, int hi = 31, int lo = 0)
+{
+  return (val & mask64(hi, lo));
+}
+
+// pick bits [hi,...,lo] from val and shift to [(hi-(newlo - lo)),newlo]
+static inline u_int32_t pickshift32(u_int32_t val, int hi = 31,
+                                    int lo = 0, int newlo = 0)
+{
+  u_int32_t bits = pick32(val, hi, lo);
+  if (lo < newlo) {
+    return (bits << (newlo - lo));
+  } else {
+    return (bits >> (lo - newlo));
+  }
+}
+// mask [hi,lo] and shift down to start at bit 0
+static inline u_int32_t pickbits32(u_int32_t val, int hi = 31, int lo = 0)
+{
+  return (pick32(val, hi, lo) >> lo);
+}
+
+// mask [hi,lo] and shift down to start at bit 0
+static inline u_int64_t pickbits64(u_int64_t val, int hi = 63, int lo = 0)
+{
+  return (pick64(val, hi, lo) >> lo);
+}
+
+/*
+ * decode registers, immediates and constants of various types
+ */
+
+static inline GReg greg(u_int32_t val, int lo)
+{
+  return (GReg)pickbits32(val, lo + 4, lo);
+}
+
+static inline VReg vreg(u_int32_t val, int lo)
+{
+  return (VReg)pickbits32(val, lo + 4, lo);
+}
+
+static inline u_int32_t uimm(u_int32_t val, int hi, int lo)
+{
+  return pickbits32(val, hi, lo);
+}
+
+static inline int32_t simm(u_int32_t val, int hi = 31, int lo = 0) {
+  union {
+    u_int32_t u;
+    int32_t n;
+  };
+
+  u = val << (31 - hi);
+  n = n >> (31 - hi + lo);
+  return n;
+}
+
+static inline int64_t simm(u_int64_t val, int hi = 63, int lo = 0) {
+  union {
+    u_int64_t u;
+    int64_t n;
+  };
+
+  u = val << (63 - hi);
+  n = n >> (63 - hi + lo);
+  return n;
+}
+
+static inline Shift shift(u_int32_t val, int lo)
+{
+  return (Shift)pickbits32(val, lo+1, lo);
+}
+
+static inline Extension extension(u_int32_t val, int lo)
+{
+  return (Extension)pickbits32(val, lo+2, lo);
+}
+
+static inline Scaling scaling(u_int32_t val, int lo)
+{
+  return (Scaling)pickbits32(val, lo, lo);
+}
+
+static inline WriteBack writeback(u_int32_t val, int lo)
+{
+  return (WriteBack)pickbits32(val, lo, lo);
+}
+
+static inline CondCode condcode(u_int32_t val, int lo)
+{
+  return (CondCode)pickbits32(val, lo+3, lo);
+}
+
+/*
+ * operation decode
+ */
+// bits [28,25] are the primary dispatch vector
+
+static inline u_int32_t dispatchGroup(u_int32_t val)
+{
+  return pickshift32(val, 28, 25, 0);
+}
+
+/*
+ * the 16 possible values for bits [28,25] identified by tags which
+ * map them to the 5 main instruction groups LDST, DPREG, ADVSIMD,
+ * BREXSYS and DPIMM.
+ *
+ * An extra group PSEUDO is included in one of the unallocated ranges
+ * for simulator-specific pseudo-instructions.
+ */
+enum DispatchGroup {
+  GROUP_PSEUDO_0000,
+  GROUP_UNALLOC_0001,
+  GROUP_UNALLOC_0010,
+  GROUP_UNALLOC_0011,
+  GROUP_LDST_0100,
+  GROUP_DPREG_0101,
+  GROUP_LDST_0110,
+  GROUP_ADVSIMD_0111,
+  GROUP_DPIMM_1000,
+  GROUP_DPIMM_1001,
+  GROUP_BREXSYS_1010,
+  GROUP_BREXSYS_1011,
+  GROUP_LDST_1100,
+  GROUP_DPREG_1101,
+  GROUP_LDST_1110,
+  GROUP_ADVSIMD_1111
+};
+
+// bits [31, 29] of a Pseudo are the secondary dispatch vector
+
+static inline u_int32_t dispatchPseudo(u_int32_t val)
+{
+  return pickshift32(val, 31, 29, 0);
+}
+
+/*
+ * the 8 possible values for bits [31,29] in a Pseudo Instruction.
+ * Bits [28,25] are always 0000.
+ */
+
+enum DispatchPseudo {
+  PSEUDO_UNALLOC_000, // unallocated
+  PSEUDO_UNALLOC_001, // ditto
+  PSEUDO_UNALLOC_010, // ditto
+  PSEUDO_UNALLOC_011, // ditto
+  PSEUDO_UNALLOC_100, // ditto
+  PSEUDO_UNALLOC_101, // ditto
+  PSEUDO_CALLOUT_110, // CALLOUT -- bits [24,0] identify call/ret sig
+  PSEUDO_HALT_111     // HALT -- bits [24, 0] identify halt code
+};
+
+// bits [25, 23] of a DPImm are the secondary dispatch vector
+
+static inline u_int32_t dispatchDPImm(u_int32_t instr)
+{
+  return pickshift32(instr, 25, 23, 0);
+}
+
+/*
+ * the 8 possible values for bits [25,23] in a Data Processing Immediate
+ * Instruction. Bits [28,25] are always 100_.
+ */
+
+enum DispatchDPImm {
+  DPIMM_PCADR_000,  // PC-rel-addressing
+  DPIMM_PCADR_001,  // ditto
+  DPIMM_ADDSUB_010,  // Add/Subtract (immediate)
+  DPIMM_ADDSUB_011, // ditto
+  DPIMM_LOG_100,    // Logical (immediate)
+  DPIMM_MOV_101,    // Move Wide (immediate)
+  DPIMM_BITF_110,   // Bitfield
+  DPIMM_EXTR_111    // Extract
+};
+
+// bits [29,28:26] of a LS are the secondary dispatch vector
+
+static inline u_int32_t dispatchLS(u_int32_t instr)
+{
+  return (pickshift32(instr, 29, 28, 1) |
+          pickshift32(instr, 26, 26, 0));
+}
+
+/*
+ * the 8 possible values for bits [29,28:26] in a Load/Store
+ * Instruction. Bits [28,25] are always _1_0
+ */
+
+enum DispatchLS {
+  LS_EXCL_000,    // Load/store exclusive (includes some unallocated)
+  LS_ADVSIMD_001, // AdvSIMD load/store (various -- includes some unallocated)
+  LS_LIT_010,     // Load register literal (includes some unallocated)
+  LS_LIT_011,     // ditto
+  LS_PAIR_100,    // Load/store register pair (various)
+  LS_PAIR_101,    // ditto
+  LS_OTHER_110,   // other load/store formats
+  LS_OTHER_111    // ditto
+};
+
+// bits [28:24:21] of a DPReg are the secondary dispatch vector
+
+static inline u_int32_t dispatchDPReg(u_int32_t instr)
+{
+  return (pickshift32(instr, 28, 28, 2) |
+          pickshift32(instr, 24, 24, 1) |
+          pickshift32(instr, 21, 21, 0));
+}
+
+/*
+ * the 8 possible values for bits [28:24:21] in a Data Processing
+ * Register Instruction. Bits [28,25] are always _101
+ */
+
+enum DispatchDPReg {
+  DPREG_LOG_000,     // Logical (shifted register)
+  DPREG_LOG_001,     // ditto
+  DPREG_ADDSHF_010,  // Add/subtract (shifted register)
+  DPREG_ADDEXT_011,  // Add/subtract (extended register)
+  DPREG_ADDCOND_100, // Add/subtract (with carry) AND
+                     // Cond compare/select AND
+                     // Data Processing (1/2 source)
+  DPREG_UNALLOC_101, // Unallocated
+  DPREG_3SRC_110, // Data Processing (3 source)
+  DPREG_3SRC_111  // Data Processing (3 source)
+};
+
+// bits [31,29] of a BrExSys are the secondary dispatch vector
+
+static inline u_int32_t dispatchBrExSys(u_int32_t instr)
+{
+  return pickbits32(instr, 31, 29);
+}
+
+/*
+ * the 8 possible values for bits [31,29] in a Branch/Exception/System
+ * Instruction. Bits [28,25] are always 101_
+ */
+
+enum DispatchBr {
+  BR_IMM_000,     // Unconditional branch (immediate)
+  BR_IMMCMP_001,  // Compare & branch (immediate) AND
+                  // Test & branch (immediate)
+  BR_IMMCOND_010, // Conditional branch (immediate) AND Unallocated
+  BR_UNALLOC_011, // Unallocated
+  BR_IMM_100,     // Unconditional branch (immediate)
+  BR_IMMCMP_101,  // Compare & branch (immediate) AND
+                  // Test & branch (immediate)
+  BR_REG_110,     // Unconditional branch (register) AND System AND
+                  // Excn gen AND Unallocated
+  BR_UNALLOC_111  // Unallocated
+};
+
+/*
+ * TODO still need to provide secondary decode and dispatch for
+ * AdvSIMD Insructions with instr[28,25] = 0111 or 1111
+ */
+
+#endif // ifndef DECODE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/depChecker_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
+#include "depChecker_aarch32.hpp"
+
+// Nothing to do on aarch32
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/depChecker_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_DEPCHECKER_AARCH32_HPP
+#define CPU_AARCH32_VM_DEPCHECKER_AARCH32_HPP
+
+// Nothing to do on aarch32
+
+#endif // CPU_AARCH32_VM_DEPCHECKER_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/disassembler_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_DISASSEMBLER_AARCH32_HPP
+#define CPU_AARCH32_VM_DISASSEMBLER_AARCH32_HPP
+
+  static int pd_instruction_alignment() {
+    return 1;
+  }
+
+  static const char* pd_cpu_opts() {
+    return "";
+  }
+
+#endif // CPU_AARCH32_VM_DISASSEMBLER_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/frame_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "interpreter/interpreter.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/markOop.hpp"
+#include "oops/method.hpp"
+#include "oops/oop.inline.hpp"
+#include "prims/methodHandles.hpp"
+#include "runtime/frame.inline.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/monitorChunk.hpp"
+#include "runtime/os.hpp"
+#include "runtime/signature.hpp"
+#include "runtime/stubCodeGenerator.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "vmreg_aarch32.inline.hpp"
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#include "runtime/vframeArray.hpp"
+#endif
+
+#ifdef ASSERT
+void RegisterMap::check_location_valid() {
+}
+#endif
+
+
+// Profiling/safepoint support
+
+bool frame::safe_for_sender(JavaThread *thread) {
+  address   sp = (address)_sp;
+  address   fp = (address)_fp;
+  address   unextended_sp = (address)_unextended_sp;
+
+  // consider stack guards when trying to determine "safe" stack pointers
+  static size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackYellowPages + StackRedPages) * os::vm_page_size() : 0;
+  size_t usable_stack_size = thread->stack_size() - stack_guard_size;
+
+  // sp must be within the usable part of the stack (not in guards)
+  bool sp_safe = (sp < thread->stack_base()) &&
+                 (sp >= thread->stack_base() - usable_stack_size);
+
+
+  if (!sp_safe) {
+    return false;
+  }
+
+  // unextended sp must be within the stack and above or equal sp
+  bool unextended_sp_safe = (unextended_sp < thread->stack_base()) &&
+                            (unextended_sp >= sp);
+
+  if (!unextended_sp_safe) {
+    return false;
+  }
+
+  // an fp must be within the stack and above (but not equal) sp
+  // second evaluation on fp+ is added to handle situation where fp is -1
+  bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base())));
+
+  // We know sp/unextended_sp are safe only fp is questionable here
+
+  // If the current frame is known to the code cache then we can attempt to
+  // to construct the sender and do some validation of it. This goes a long way
+  // toward eliminating issues when we get in frame construction code
+
+  if (_cb != NULL ) {
+
+    // First check if frame is complete and tester is reliable
+    // Unfortunately we can only check frame complete for runtime stubs and nmethod
+    // other generic buffer blobs are more problematic so we just assume they are
+    // ok. adapter blobs never have a frame complete and are never ok.
+
+    if (!_cb->is_frame_complete_at(_pc)) {
+      if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) {
+        return false;
+      }
+    }
+
+    // Could just be some random pointer within the codeBlob
+    if (!_cb->code_contains(_pc)) {
+      return false;
+    }
+
+    // Entry frame checks
+    if (is_entry_frame()) {
+      // an entry frame must have a valid fp.
+
+      if (!fp_safe) return false;
+
+      // Validate the JavaCallWrapper an entry frame must have
+
+      address jcw = (address)entry_frame_call_wrapper();
+
+      bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > fp);
+
+      return jcw_safe;
+
+    }
+
+    intptr_t* sender_sp = NULL;
+    intptr_t* sender_unextended_sp = NULL;
+    address   sender_pc = NULL;
+    intptr_t* saved_fp =  NULL;
+
+    if (is_interpreted_frame()) {
+      // fp must be safe
+      if (!fp_safe) {
+        return false;
+      }
+
+      sender_pc = (address) this->fp()[return_addr_offset];
+      // for interpreted frames, the value below is the sender "raw" sp,
+      // which can be different from the sender unextended sp (the sp seen
+      // by the sender) because of current frame local variables
+      sender_sp = (intptr_t*) addr_at(sender_sp_offset);
+      sender_unextended_sp = (intptr_t*) this->fp()[interpreter_frame_sender_sp_offset];
+      saved_fp = (intptr_t*) this->fp()[link_offset];
+
+    } else {
+      // must be some sort of compiled/runtime frame
+      // fp does not have to be safe (although it could be check for c1?)
+
+      // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc
+      if (_cb->frame_size() <= 0) {
+        return false;
+      }
+
+      sender_sp = _unextended_sp + _cb->frame_size();
+      sender_unextended_sp = sender_sp;
+      sender_pc = (address) *(sender_sp-1);
+      // Note: frame::sender_sp_offset is only valid for compiled frame
+      saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset);
+    }
+
+
+    // If the potential sender is the interpreter then we can do some more checking
+    if (Interpreter::contains(sender_pc)) {
+
+      // fp is always saved in a recognizable place in any code we generate. However
+      // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved fp
+      // is really a frame pointer.
+
+      bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp);
+
+      if (!saved_fp_safe) {
+        return false;
+      }
+
+      // construct the potential sender
+
+      frame sender(sender_sp, sender_unextended_sp, saved_fp, sender_pc);
+
+      return sender.is_interpreted_frame_valid(thread);
+
+    }
+
+    // We must always be able to find a recognizable pc
+    CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc);
+    if (sender_pc == NULL ||  sender_blob == NULL) {
+      return false;
+    }
+
+    // Could be a zombie method
+    if (sender_blob->is_zombie() || sender_blob->is_unloaded()) {
+      return false;
+    }
+
+    // Could just be some random pointer within the codeBlob
+    if (!sender_blob->code_contains(sender_pc)) {
+      return false;
+    }
+
+    // We should never be able to see an adapter if the current frame is something from code cache
+    if (sender_blob->is_adapter_blob()) {
+      return false;
+    }
+
+    // Could be the call_stub
+    if (StubRoutines::returns_to_call_stub(sender_pc)) {
+      bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp);
+
+      if (!saved_fp_safe) {
+        return false;
+      }
+
+      // construct the potential sender
+
+      frame sender(sender_sp, sender_unextended_sp, saved_fp, sender_pc);
+
+      // Validate the JavaCallWrapper an entry frame must have
+      address jcw = (address)sender.entry_frame_call_wrapper();
+
+      bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp());
+
+      return jcw_safe;
+    }
+
+    if (sender_blob->is_nmethod()) {
+        nmethod* nm = sender_blob->as_nmethod_or_null();
+        if (nm != NULL) {
+            if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
+                nm->method()->is_method_handle_intrinsic()) {
+                return false;
+            }
+        }
+    }
+
+    // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size
+    // because the return address counts against the callee's frame.
+
+    if (sender_blob->frame_size() <= 0) {
+      assert(!sender_blob->is_nmethod(), "should count return address at least");
+      return false;
+    }
+
+    // We should never be able to see anything here except an nmethod. If something in the
+    // code cache (current frame) is called by an entity within the code cache that entity
+    // should not be anything but the call stub (already covered), the interpreter (already covered)
+    // or an nmethod.
+
+    if (!sender_blob->is_nmethod()) {
+        return false;
+    }
+
+    // Could put some more validation for the potential non-interpreted sender
+    // frame we'd create by calling sender if I could think of any. Wait for next crash in forte...
+
+    // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb
+
+    // We've validated the potential sender that would be created
+    return true;
+  }
+
+  // Must be native-compiled frame. Since sender will try and use fp to find
+  // linkages it must be safe
+
+  if (!fp_safe) {
+    return false;
+  }
+
+  // Will the pc we fetch be non-zero (which we'll find at the oldest frame)
+
+  if ( (address) this->fp()[return_addr_offset] == NULL) return false;
+
+
+  // could try and do some more potential verification of native frame if we could think of some...
+
+  return true;
+
+}
+
+void frame::patch_pc(Thread* thread, address pc) {
+  address* pc_addr = &(((address*) sp())[-1]);
+  if (TracePcPatching) {
+    tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
+                  p2i(pc_addr), p2i(*pc_addr), p2i(pc));
+  }
+  // Either the return address is the original one or we are going to
+  // patch in the same address that's already there.
+  assert(_pc == *pc_addr || pc == *pc_addr, "must be");
+  *pc_addr = pc;
+  _cb = CodeCache::find_blob(pc);
+  address original_pc = nmethod::get_deopt_original_pc(this);
+  if (original_pc != NULL) {
+    assert(original_pc == _pc, "expected original PC to be stored before patching");
+    _deopt_state = is_deoptimized;
+    // leave _pc as is
+  } else {
+    _deopt_state = not_deoptimized;
+    _pc = pc;
+  }
+}
+
+bool frame::is_interpreted_frame() const  {
+  return Interpreter::contains(pc());
+}
+
+int frame::frame_size(RegisterMap* map) const {
+  frame sender = this->sender(map);
+  return sender.sp() - sp();
+}
+
+intptr_t* frame::entry_frame_argument_at(int offset) const {
+  // convert offset to index to deal with tsi
+  int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
+  // Entry frame's arguments are always in relation to unextended_sp()
+  return &unextended_sp()[index];
+}
+
+// sender_sp
+#ifdef CC_INTERP
+intptr_t* frame::interpreter_frame_sender_sp() const {
+  assert(is_interpreted_frame(), "interpreted frame expected");
+  // QQQ why does this specialize method exist if frame::sender_sp() does same thing?
+  // seems odd and if we always know interpreted vs. non then sender_sp() is really
+  // doing too much work.
+  return get_interpreterState()->sender_sp();
+}
+
+// monitor elements
+
+BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
+  return get_interpreterState()->monitor_base();
+}
+
+BasicObjectLock* frame::interpreter_frame_monitor_end() const {
+  return (BasicObjectLock*) get_interpreterState()->stack_base();
+}
+
+#else // CC_INTERP
+
+intptr_t* frame::interpreter_frame_sender_sp() const {
+  assert(is_interpreted_frame(), "interpreted frame expected");
+  return (intptr_t*) at(interpreter_frame_sender_sp_offset);
+}
+
+void frame::set_interpreter_frame_sender_sp(intptr_t* sender_sp) {
+  assert(is_interpreted_frame(), "interpreted frame expected");
+  ptr_at_put(interpreter_frame_sender_sp_offset, (intptr_t) sender_sp);
+}
+
+
+// monitor elements
+
+BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
+  return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset);
+}
+
+BasicObjectLock* frame::interpreter_frame_monitor_end() const {
+  BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset);
+  // make sure the pointer points inside the frame
+  assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
+  assert((intptr_t*) result < fp(),  "monitor end should be strictly below the frame pointer");
+  return result;
+}
+
+void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
+  *((BasicObjectLock**)addr_at(interpreter_frame_monitor_block_top_offset)) = value;
+}
+
+// Used by template based interpreter deoptimization
+void frame::interpreter_frame_set_last_sp(intptr_t* sp) {
+    *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp;
+}
+#endif // CC_INTERP
+
+frame frame::sender_for_entry_frame(RegisterMap* map) const {
+  assert(map != NULL, "map must be set");
+  // Java frame called from C; skip all C frames and return top C
+  // frame of that chunk as the sender
+  JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor();
+  assert(!entry_frame_is_first(), "next Java fp must be non zero");
+  assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
+  map->clear();
+  assert(map->include_argument_oops(), "should be set by clear");
+  if (jfa->last_Java_pc() != NULL ) {
+    frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc());
+    return fr;
+  }
+  frame fr(jfa->last_Java_sp(), jfa->last_Java_fp());
+  return fr;
+}
+
+//------------------------------------------------------------------------------
+// frame::verify_deopt_original_pc
+//
+// Verifies the calculated original PC of a deoptimization PC for the
+// given unextended SP.
+#ifdef ASSERT
+void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
+  frame fr;
+
+  // This is ugly but it's better than to change {get,set}_original_pc
+  // to take an SP value as argument.  And it's only a debugging
+  // method anyway.
+  fr._unextended_sp = unextended_sp;
+
+  address original_pc = nm->get_original_pc(&fr);
+  assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+}
+#endif
+
+//------------------------------------------------------------------------------
+// frame::adjust_unextended_sp
+void frame::adjust_unextended_sp() {
+  // On aarch32, sites calling method handle intrinsics and lambda forms are treated
+  // as any other call site. Therefore, no special action is needed when we are
+  // returning to any of these call sites.
+
+  nmethod* sender_nm = (_cb == NULL) ? NULL : _cb->as_nmethod_or_null();
+  if (sender_nm != NULL) {
+    // If the sender PC is a deoptimization point, get the original PC.
+    if (sender_nm->is_deopt_entry(_pc) ||
+        sender_nm->is_deopt_mh_entry(_pc)) {
+      DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp));
+    }
+  }
+}
+
+//------------------------------------------------------------------------------
+// frame::update_map_with_saved_link
+void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
+  // The interpreter and compiler(s) always save fp in a known
+  // location on entry. We must record where that location is
+  // so that if fp was live on callout from c2 we can find
+  // the saved copy no matter what it called.
+
+  // Since the interpreter always saves fp if we record where it is then
+  // we don't have to always save fp on entry and exit to c2 compiled
+  // code, on entry will be enough.
+  map->set_location(rfp->as_VMReg(), (address) link_addr);
+  // this is weird "H" ought to be at a higher address however the
+  // oopMaps seems to have the "H" regs at the same address and the
+  // vanilla register.
+  // XXXX make this go away
+  if (true) {
+    map->set_location(rfp->as_VMReg()->next(), (address) link_addr);
+  }
+}
+
+
+//------------------------------------------------------------------------------
+// frame::sender_for_interpreter_frame
+frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
+  // SP is the raw SP from the sender after adapter or interpreter
+  // extension.
+  intptr_t* sender_sp = this->sender_sp();
+
+  // This is the sp before any possible extension (adapter/locals).
+  intptr_t* unextended_sp = interpreter_frame_sender_sp();
+
+#ifdef COMPILER2
+  if (map->update_map()) {
+    update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
+  }
+#endif // COMPILER2
+
+  return frame(sender_sp, unextended_sp, link(), sender_pc());
+}
+
+
+//------------------------------------------------------------------------------
+// frame::sender_for_compiled_frame
+/*frame frame::sender_for_compiled_frame(RegisterMap* map) const {
+  // we cannot rely upon the last fp having been saved to the thread
+  // in C2 code but it will have been pushed onto the stack. so we
+  // have to find it relative to the unextended sp
+
+  assert(_cb->frame_size() >= 0, "must have non-zero frame size");
+  intptr_t* l_sender_sp = unextended_sp() + _cb->frame_size();
+  intptr_t* unextended_sp = l_sender_sp;
+
+  // the return_address is always the word on the stack
+  address sender_pc = (address) *(l_sender_sp-1);
+
+  intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset);
+  intptr_t** saved_fp_addr = (intptr_t**)(_fp + link_offset);
+
+  // assert (sender_sp() == l_sender_sp, "should be");
+  // assert (*saved_fp_addr == link(), "should be");
+
+  if (map->update_map()) {
+    // Tell GC to use argument oopmaps for some runtime stubs that need it.
+    // For C1, the runtime stub might not have oop maps, so set this flag
+    // outside of update_register_map.
+    map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
+    if (_cb->oop_maps() != NULL) {
+      OopMapSet::update_register_map(this, map);
+    }
+
+    // Since the prolog does the save and restore of FP there is no
+    // oopmap for it so we must fill in its location as if there was
+    // an oopmap entry since if our caller was compiled code there
+    // could be live jvm state in it.
+    update_map_with_saved_link(map, saved_fp_addr);
+  }
+
+  return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
+}*/
+
+frame frame::sender_for_compiled_frame(RegisterMap* map) const {
+  // we cannot rely upon the last fp having been saved to the thread
+  // in C2 code but it will have been pushed onto the stack. so we
+  // have to find it relative to the unextended sp
+
+  assert(_cb->frame_size() >= 0, "must have non-zero frame size");
+  intptr_t* l_sender_sp = _fp + 1;
+  intptr_t* unextended_sp = l_sender_sp;
+
+  // the return_address is always the word on the stack
+  address sender_pc = (address) *(l_sender_sp-1);
+
+  intptr_t** saved_fp_addr = (intptr_t**)(_fp + link_offset);
+
+  // assert (sender_sp() == l_sender_sp, "should be");
+  // assert (*saved_fp_addr == link(), "should be");
+
+  if (map->update_map()) {
+    // Tell GC to use argument oopmaps for some runtime stubs that need it.
+    // For C1, the runtime stub might not have oop maps, so set this flag
+    // outside of update_register_map.
+    map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
+    if (_cb->oop_maps() != NULL) {
+      OopMapSet::update_register_map(this, map);
+    }
+
+    // Since the prolog does the save and restore of FP there is no
+    // oopmap for it so we must fill in its location as if there was
+    // an oopmap entry since if our caller was compiled code there
+    // could be live jvm state in it.
+    update_map_with_saved_link(map, saved_fp_addr);
+  }
+
+  return frame(l_sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
+}
+
+//------------------------------------------------------------------------------
+// frame::sender
+frame frame::sender(RegisterMap* map) const {
+  // Default is we done have to follow them. The sender_for_xxx will
+  // update it accordingly
+  map->set_include_argument_oops(false);
+  //printf("Called frame::sender\n");
+
+  //printf("fp is %p, _call_stub_return_address is %p\n", _fp, StubRoutines::_call_stub_return_address);
+
+  if (is_entry_frame()) {
+    //printf("Is entry frame\n");
+    return sender_for_entry_frame(map);
+  }
+  if (is_interpreted_frame()) {
+    //printf("Is interpreted frame\n");
+    return sender_for_interpreter_frame(map);
+  }
+  assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
+
+  // This test looks odd: why is it not is_compiled_frame() ?  That's
+  // because stubs also have OOP maps.
+  if (_cb != NULL) {
+    //printf("Is compiled frame\n");
+    return sender_for_compiled_frame(map);
+  }
+
+  //printf("Is default frame\n");
+  // Must be native-compiled frame, i.e. the marshaling code for native
+  // methods that exists in the core system.
+  return frame(sender_sp(), link(), sender_pc());
+}
+
+bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
+  assert(is_interpreted_frame(), "must be interpreter frame");
+  Method* method = interpreter_frame_method();
+  // When unpacking an optimized frame the frame pointer is
+  // adjusted with:
+  int diff = (method->max_locals() - method->size_of_parameters()) *
+             Interpreter::stackElementWords;
+  return _fp == (fp - diff);
+}
+
+void frame::pd_gc_epilog() {
+  // Nothing to do here for now
+}
+
+bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
+// QQQ
+#ifdef CC_INTERP
+#else
+  assert(is_interpreted_frame(), "Not an interpreted frame");
+  // These are reasonable sanity checks
+  if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) {
+    return false;
+  }
+  if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) {
+    return false;
+  }
+  if (fp() + interpreter_frame_initial_sp_offset < sp()) {
+    return false;
+  }
+  // These are hacks to keep us out of trouble.
+  // The problem with these is that they mask other problems
+  if (fp() <= sp()) {        // this attempts to deal with unsigned comparison above
+    return false;
+  }
+
+  // do some validation of frame elements
+
+  // first the method
+
+  Method* m = *interpreter_frame_method_addr();
+
+  // validate the method we'd find in this potential sender
+  if (!m->is_valid_method()) return false;
+
+  // stack frames shouldn't be much larger than max_stack elements
+  // this test requires the use of unextended_sp which is the sp as seen by
+  // the current frame, and not sp which is the "raw" pc which could point
+  // further because of local variables of the callee method inserted after
+  // method arguments
+  if (fp() - unextended_sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) {
+    return false;
+  }
+
+  // Validate bci/bcx
+  intptr_t bcx = interpreter_frame_bcx();
+  if (m->validate_bci_from_bcx(bcx) < 0) {
+    return false;
+  }
+
+  // validate constantPoolCache*
+  ConstantPoolCache* cp = *interpreter_frame_cache_addr();
+  if (cp == NULL || !cp->is_metaspace_object()) return false;
+
+  // validate locals
+
+  address locals =  (address) *interpreter_frame_locals_addr();
+
+  if (locals > thread->stack_base() || locals < (address) fp()) return false;
+
+  // We'd have to be pretty unlucky to be mislead at this point
+
+#endif // CC_INTERP
+  return true;
+}
+
+BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) {
+#ifdef CC_INTERP
+  // Needed for JVMTI. The result should always be in the
+  // interpreterState object
+  interpreterState istate = get_interpreterState();
+#endif // CC_INTERP
+  assert(is_interpreted_frame(), "interpreted frame expected");
+  Method* method = interpreter_frame_method();
+  BasicType type = method->result_type();
+
+  intptr_t* tos_addr;
+  if (method->is_native()) {
+    // TODO : ensure AARCH64 does the same as Intel here i.e. push d0 then r0
+    // Prior to calling into the runtime to report the method_exit the possible
+    // return value is pushed to the native stack. If the result is a jfloat/jdouble
+    // then ST0 is saved before EAX/EDX. See the note in generate_native_result
+    tos_addr = (intptr_t*)sp();
+    if (type == T_FLOAT || type == T_DOUBLE) {
+      // This is times two because we do a push(ltos) after pushing XMM0
+      // and that takes two interpreter stack slots.
+      tos_addr += 2 * Interpreter::stackElementWords;
+    }
+  } else {
+    tos_addr = (intptr_t*)interpreter_frame_tos_address();
+  }
+
+  switch (type) {
+    case T_OBJECT  :
+    case T_ARRAY   : {
+      oop obj;
+      if (method->is_native()) {
+#ifdef CC_INTERP
+        obj = istate->_oop_temp;
+#else
+        obj = cast_to_oop(at(interpreter_frame_oop_temp_offset));
+#endif // CC_INTERP
+      } else {
+        oop* obj_p = (oop*)tos_addr;
+        obj = (obj_p == NULL) ? (oop)NULL : *obj_p;
+      }
+      assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check");
+      *oop_result = obj;
+      break;
+    }
+    case T_BOOLEAN : value_result->z = *(jboolean*)tos_addr; break;
+    case T_BYTE    : value_result->b = *(jbyte*)tos_addr; break;
+    case T_CHAR    : value_result->c = *(jchar*)tos_addr; break;
+    case T_SHORT   : value_result->s = *(jshort*)tos_addr; break;
+    case T_INT     : value_result->i = *(jint*)tos_addr; break;
+    case T_LONG    : value_result->j = *(jlong*)tos_addr; break;
+    case T_FLOAT   : {
+        value_result->f = *(jfloat*)tos_addr;
+      break;
+    }
+    case T_DOUBLE  : value_result->d = *(jdouble*)tos_addr; break;
+    case T_VOID    : /* Nothing to do */ break;
+    default        : ShouldNotReachHere();
+  }
+
+  return type;
+}
+
+
+intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
+  int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
+  return &interpreter_frame_tos_address()[index];
+}
+
+#ifndef PRODUCT
+
+#define DESCRIBE_FP_OFFSET(name) \
+    values.describe(frame_no, fp() + frame::name##_offset, #name)
+
+void frame::describe_pd(FrameValues& values, int frame_no) {
+  if (is_interpreted_frame()) {
+    DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp);
+    DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
+    DESCRIBE_FP_OFFSET(interpreter_frame_method);
+    DESCRIBE_FP_OFFSET(interpreter_frame_mdx);
+    DESCRIBE_FP_OFFSET(interpreter_frame_cache);
+    DESCRIBE_FP_OFFSET(interpreter_frame_locals);
+    DESCRIBE_FP_OFFSET(interpreter_frame_bcx);
+    DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
+  }
+}
+
+#endif // PRODUCT
+
+intptr_t *frame::initial_deoptimization_info() {
+  // Not used on aarch32, but we must return something.
+  return NULL;
+}
+
+intptr_t* frame::real_fp() const {
+  // Currently we have a fp for all frames
+  /*if (_cb != NULL) {
+    // use the frame size if valid
+    int size = _cb->frame_size();
+    if (size > 0) {
+      return unextended_sp() + size;
+    }
+  }*/
+  // else rely on fp()
+  //assert(! is_compiled_frame(), "unknown compiled frame size");
+  return fp();
+}
+
+#undef DESCRIBE_FP_OFFSET
+
+#define DESCRIBE_FP_OFFSET(name)                                        \
+  {                                                                     \
+    unsigned long *p = (unsigned long *)fp;                             \
+    printf("0x%016lx 0x%016lx %s\n", (unsigned long)(p + frame::name##_offset), \
+           p[frame::name##_offset], #name);                             \
+  }
+
+static __thread unsigned long nextfp;
+static __thread unsigned long nextpc;
+static __thread unsigned long nextsp;
+static __thread RegisterMap *reg_map;
+
+static void printbc(Method* m, intptr_t bcx) {
+  const char* name;
+  char buf[16];
+  if (m->validate_bci_from_bcx(bcx) < 0 || !m->contains((address) bcx)) {
+    name = "???";
+    snprintf(buf, sizeof buf, "(bad)");
+  } else {
+    int bci = m->bci_from((address) bcx);
+    snprintf(buf, sizeof buf, "%d", bci);
+    name = Bytecodes::name(m->code_at(bci));
+  }
+  ResourceMark rm;
+  printf("%s : %s ==> %s\n", m->name_and_sig_as_C_string(), buf, name);
+}
+
+void internal_pf(unsigned long sp, unsigned long fp, unsigned long pc, unsigned long bcx) {
+  if (! fp)
+    return;
+
+  DESCRIBE_FP_OFFSET(return_addr);
+  DESCRIBE_FP_OFFSET(link);
+  DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp);
+  DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
+  DESCRIBE_FP_OFFSET(interpreter_frame_method);
+  DESCRIBE_FP_OFFSET(interpreter_frame_mdx);
+  DESCRIBE_FP_OFFSET(interpreter_frame_cache);
+  DESCRIBE_FP_OFFSET(interpreter_frame_locals);
+  DESCRIBE_FP_OFFSET(interpreter_frame_bcx);
+  DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
+
+  unsigned long* p = (unsigned long*) fp;
+
+  // We want to see all frames, native and Java.  For compiled and
+  // interpreted frames we have special information that allows us to
+  // unwind them; for everything else we assume that the native frame
+  // pointer chain is intact.
+  frame this_frame((intptr_t*)sp, (intptr_t*)fp, (address)pc);
+  if (this_frame.is_compiled_frame() ||
+      this_frame.is_interpreted_frame()) {
+    frame sender = this_frame.sender(reg_map);
+    nextfp = (unsigned long)sender.fp();
+    nextpc = (unsigned long)sender.pc();
+    nextsp = (unsigned long)sender.unextended_sp();
+  } else {
+    nextfp = p[frame::link_offset];
+    nextpc = p[frame::return_addr_offset];
+    nextsp = (unsigned long)&p[frame::sender_sp_offset];
+  }
+
+  if (bcx == -1ul) {
+    bcx = p[frame::interpreter_frame_bcx_offset];
+  }
+
+  if (Interpreter::contains((address)pc)) {
+    Method* m = (Method*)p[frame::interpreter_frame_method_offset];
+    if(m && m->is_method()) {
+      printbc(m, bcx);
+    } else
+      printf("not a Method\n");
+  } else {
+    CodeBlob *cb = CodeCache::find_blob((address)pc);
+    if (cb != NULL) {
+      if (cb->is_nmethod()) {
+        ResourceMark rm;
+        nmethod* nm = (nmethod*)cb;
+        printf("nmethod %s\n", nm->method()->name_and_sig_as_C_string());
+      } else if (cb->name()) {
+        printf("CodeBlob %s\n", cb->name());
+      }
+    }
+  }
+}
+
+extern "C" void npf() {
+  CodeBlob *cb = CodeCache::find_blob((address)nextpc);
+  // C2 does not always chain the frame pointers when it can, instead
+  // preferring to use fixed offsets from SP, so a simple leave() does
+  // not work.  Instead, it adds the frame size to SP then pops FP and
+  // LR.  We have to do the same thing to get a good call chain.
+  if (cb && cb->frame_size())
+    nextfp = nextsp + wordSize * (cb->frame_size() - 2);
+  internal_pf (nextsp, nextfp, nextpc, -1);
+}
+
+extern "C" void pf(unsigned long sp, unsigned long fp, unsigned long pc,
+                   unsigned long bcx, unsigned long thread) {
+  RegisterMap map((JavaThread*)thread, false);
+  if (!reg_map) {
+    reg_map = (RegisterMap*)os::malloc(sizeof map, mtNone);
+  }
+  memcpy(reg_map, &map, sizeof map);
+  {
+    CodeBlob *cb = CodeCache::find_blob((address)pc);
+    if (cb && cb->frame_size())
+      fp = sp + wordSize * (cb->frame_size() - 2);
+  }
+  internal_pf(sp, fp, pc, bcx);
+}
+
+// support for printing out where we are in a Java method
+// needs to be passed current fp and bcp register values
+// prints method name, bc index and bytecode name
+extern "C" void pm(unsigned long fp, unsigned long bcx) {
+  DESCRIBE_FP_OFFSET(interpreter_frame_method);
+  unsigned long *p = (unsigned long *)fp;
+  Method* m = (Method*)p[frame::interpreter_frame_method_offset];
+  printbc(m, bcx);
+}
+
+#ifndef PRODUCT
+// This is a generic constructor which is only used by pns() in debug.cpp.
+frame::frame(void* sp, void* fp, void* pc) {
+  init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/frame_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_FRAME_AARCH32_HPP
+#define CPU_AARCH32_VM_FRAME_AARCH32_HPP
+
+#include "runtime/synchronizer.hpp"
+#include "utilities/top.hpp"
+
+// A frame represents a physical stack frame (an activation).  Frames can be
+// C or Java frames, and the Java frames can be interpreted or compiled.
+// In contrast, vframes represent source-level activations, so that one physical frame
+// can correspond to multiple source level frames because of inlining.
+// A frame is comprised of {pc, fp, sp}
+// ------------------------------ Asm interpreter ----------------------------------------
+// Layout of asm interpreter frame:
+//    [expression stack      ] * <- sp
+
+//    [monitors[0]           ]   \
+//     ...                        | monitor block size = k
+//    [monitors[k-1]         ]   /
+//    [frame initial esp     ] ( == &monitors[0], initially here)       initial_sp_offset
+//    [byte code index/pointr]                   = bcx()                bcx_offset
+
+//    [pointer to locals     ]                   = locals()             locals_offset
+//    [constant pool cache   ]                   = cache()              cache_offset
+
+//    [methodData            ]                   = mdp()                mdx_offset
+//    [methodOop             ]                   = method()             method_offset
+
+//    [last esp              ]                   = last_sp()            last_sp_offset
+//    [old stack pointer     ]                     (sender_sp)          sender_sp_offset
+
+//    [old frame pointer     ]                   = link()
+//    [return pc             ]   <- fp
+
+//    [last sp               ]
+//    [oop temp              ]                     (only for native calls)
+
+//    [locals and parameters ]
+//                               <- sender sp
+// ------------------------------ Asm interpreter ----------------------------------------
+
+// ------------------------------ C++ interpreter ----------------------------------------
+//
+// Layout of C++ interpreter frame: (While executing in BytecodeInterpreter::run)
+//
+//                             <- SP (current esp/rsp)
+//    [local variables         ] BytecodeInterpreter::run local variables
+//    ...                        BytecodeInterpreter::run local variables
+//    [local variables         ] BytecodeInterpreter::run local variables
+//    [old frame pointer       ]   fp [ BytecodeInterpreter::run's ebp/rbp ]
+//    [return pc               ]  (return to frame manager)
+//    [interpreter_state*      ]  (arg to BytecodeInterpreter::run)   --------------
+//    [expression stack        ] <- last_Java_sp                           |
+//    [...                     ] * <- interpreter_state.stack              |
+//    [expression stack        ] * <- interpreter_state.stack_base         |
+//    [monitors                ]   \                                       |
+//     ...                          | monitor block size                   |
+//    [monitors                ]   / <- interpreter_state.monitor_base     |
+//    [struct interpretState   ] <-----------------------------------------|
+//    [return pc               ] (return to callee of frame manager [1]
+//    [locals and parameters   ]
+//                               <- sender sp
+
+// [1] When the c++ interpreter calls a new method it returns to the frame
+//     manager which allocates a new frame on the stack. In that case there
+//     is no real callee of this newly allocated frame. The frame manager is
+//     aware of the  additional frame(s) and will pop them as nested calls
+//     complete. Howevers tTo make it look good in the debugger the frame
+//     manager actually installs a dummy pc pointing to RecursiveInterpreterActivation
+//     with a fake interpreter_state* parameter to make it easy to debug
+//     nested calls.
+
+// Note that contrary to the layout for the assembly interpreter the
+// expression stack allocated for the C++ interpreter is full sized.
+// However this is not as bad as it seems as the interpreter frame_manager
+// will truncate the unused space on succesive method calls.
+//
+// ------------------------------ C++ interpreter ----------------------------------------
+
+ public:
+  enum {
+    pc_return_offset                                 =  -1,
+    // All frames
+    link_offset                                      =  -1,
+    return_addr_offset                               =  0,
+    sender_sp_offset                                 =  1,
+
+#ifndef CC_INTERP
+
+    // Interpreter frames
+    interpreter_frame_oop_temp_offset                =  2, // for native calls only
+
+    interpreter_frame_sender_sp_offset               = -2,
+    // outgoing sp before a call to an invoked method
+    interpreter_frame_last_sp_offset                 = interpreter_frame_sender_sp_offset - 1,
+    interpreter_frame_method_offset                  = interpreter_frame_last_sp_offset - 1,
+    interpreter_frame_mdx_offset                     = interpreter_frame_method_offset - 1,
+    interpreter_frame_cache_offset                   = interpreter_frame_mdx_offset - 1,
+    interpreter_frame_locals_offset                  = interpreter_frame_cache_offset - 1,
+    interpreter_frame_bcx_offset                     = interpreter_frame_locals_offset - 1,
+    interpreter_frame_initial_sp_offset              = interpreter_frame_bcx_offset - 1,
+
+    interpreter_frame_monitor_block_top_offset       = interpreter_frame_initial_sp_offset,
+    interpreter_frame_monitor_block_bottom_offset    = interpreter_frame_initial_sp_offset,
+
+#endif // CC_INTERP
+
+    // Entry frames
+    // n.b. these values are determined by the layout defined in
+    // stubGenerator for the Java call stub
+    entry_frame_after_call_words                     = 13,
+    entry_frame_call_wrapper_offset                  = -12,
+
+    // we don't need a save area
+    arg_reg_save_area_bytes                          =  0,
+
+    // This is the offset from the rfp beyond the space taken up by
+    // frame variables
+    offset_from_rfp_bytes                            =  4
+
+  };
+
+  intptr_t ptr_at(int offset) const {
+    return *ptr_at_addr(offset);
+  }
+
+  void ptr_at_put(int offset, intptr_t value) {
+    *ptr_at_addr(offset) = value;
+  }
+
+ private:
+  // an additional field beyond _sp and _pc:
+  intptr_t*   _fp; // frame pointer
+  // The interpreter and adapters will extend the frame of the caller.
+  // Since oopMaps are based on the sp of the caller before extension
+  // we need to know that value. However in order to compute the address
+  // of the return address we need the real "raw" sp. Since sparc already
+  // uses sp() to mean "raw" sp and unextended_sp() to mean the caller's
+  // original sp we use that convention.
+
+  intptr_t*     _unextended_sp;
+  void adjust_unextended_sp();
+
+  intptr_t* ptr_at_addr(int offset) const {
+    return (intptr_t*) addr_at(offset);
+  }
+
+#ifdef ASSERT
+  // Used in frame::sender_for_{interpreter,compiled}_frame
+  static void verify_deopt_original_pc(   nmethod* nm, intptr_t* unextended_sp);
+#endif
+
+ public:
+  // Constructors
+
+  frame(intptr_t* sp, intptr_t* fp, address pc);
+
+  frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc);
+
+  frame(intptr_t* sp, intptr_t* fp);
+
+  void init(intptr_t* sp, intptr_t* fp, address pc);
+
+  // accessors for the instance variables
+  // Note: not necessarily the real 'frame pointer' (see real_fp)
+  intptr_t*   fp() const { return _fp; }
+
+  inline address* sender_pc_addr() const;
+
+  // expression stack tos if we are nested in a java call
+  intptr_t* interpreter_frame_last_sp() const;
+
+  // helper to update a map with callee-saved RBP
+  static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr);
+
+#ifndef CC_INTERP
+  // deoptimization support
+  void interpreter_frame_set_last_sp(intptr_t* sp);
+#endif // CC_INTERP
+
+#ifdef CC_INTERP
+  inline interpreterState get_interpreterState() const;
+#endif // CC_INTERP
+
+#endif // CPU_AARCH32_VM_FRAME_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/frame_aarch32.inline.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_FRAME_AARCH32_INLINE_HPP
+#define CPU_AARCH32_VM_FRAME_AARCH32_INLINE_HPP
+
+#include "code/codeCache.hpp"
+
+// Inline functions for AArch64 frames:
+
+// Constructors:
+
+inline frame::frame() {
+  _pc = NULL;
+  _sp = NULL;
+  _unextended_sp = NULL;
+  _fp = NULL;
+  _cb = NULL;
+  _deopt_state = unknown;
+}
+
+static int spin;
+
+inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
+  intptr_t a = intptr_t(sp);
+  intptr_t b = intptr_t(fp);
+  _sp = sp;
+  _unextended_sp = sp;
+  _fp = fp;
+  _pc = pc;
+  assert(pc != NULL, "no pc?");
+  _cb = CodeCache::find_blob(pc);
+  adjust_unextended_sp();
+
+  address original_pc = nmethod::get_deopt_original_pc(this);
+  if (original_pc != NULL) {
+    _pc = original_pc;
+    _deopt_state = is_deoptimized;
+  } else {
+    _deopt_state = not_deoptimized;
+  }
+}
+
+inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
+  init(sp, fp, pc);
+}
+
+inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
+  intptr_t a = intptr_t(sp);
+  intptr_t b = intptr_t(fp);
+  _sp = sp;
+  _unextended_sp = unextended_sp;
+  _fp = fp;
+  _pc = pc;
+  assert(pc != NULL, "no pc?");
+  _cb = CodeCache::find_blob(pc);
+  adjust_unextended_sp();
+
+  address original_pc = nmethod::get_deopt_original_pc(this);
+  if (original_pc != NULL) {
+    _pc = original_pc;
+    assert(((nmethod*)_cb)->insts_contains(_pc), "original PC must be in nmethod");
+    _deopt_state = is_deoptimized;
+  } else {
+    _deopt_state = not_deoptimized;
+  }
+}
+
+inline frame::frame(intptr_t* sp, intptr_t* fp) {
+  intptr_t a = intptr_t(sp);
+  intptr_t b = intptr_t(fp);
+  _sp = sp;
+  _unextended_sp = sp;
+  _fp = fp;
+  _pc = (address)(sp[-1]);
+
+  // Here's a sticky one. This constructor can be called via AsyncGetCallTrace
+  // when last_Java_sp is non-null but the pc fetched is junk. If we are truly
+  // unlucky the junk value could be to a zombied method and we'll die on the
+  // find_blob call. This is also why we can have no asserts on the validity
+  // of the pc we find here. AsyncGetCallTrace -> pd_get_top_frame_for_signal_handler
+  // -> pd_last_frame should use a specialized version of pd_last_frame which could
+  // call a specilaized frame constructor instead of this one.
+  // Then we could use the assert below. However this assert is of somewhat dubious
+  // value.
+  // assert(_pc != NULL, "no pc?");
+
+  _cb = CodeCache::find_blob(_pc);
+  adjust_unextended_sp();
+
+  address original_pc = nmethod::get_deopt_original_pc(this);
+  if (original_pc != NULL) {
+    _pc = original_pc;
+    _deopt_state = is_deoptimized;
+  } else {
+    _deopt_state = not_deoptimized;
+  }
+}
+
+// Accessors
+
+inline bool frame::equal(frame other) const {
+  bool ret =  sp() == other.sp()
+              && unextended_sp() == other.unextended_sp()
+              && fp() == other.fp()
+              && pc() == other.pc();
+  assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction");
+  return ret;
+}
+
+// Return unique id for this frame. The id must have a value where we can distinguish
+// identity and younger/older relationship. NULL represents an invalid (incomparable)
+// frame.
+inline intptr_t* frame::id(void) const { return unextended_sp(); }
+
+// Relationals on frames based
+// Return true if the frame is younger (more recent activation) than the frame represented by id
+inline bool frame::is_younger(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id");
+                                                    return this->id() < id ; }
+
+// Return true if the frame is older (less recent activation) than the frame represented by id
+inline bool frame::is_older(intptr_t* id) const   { assert(this->id() != NULL && id != NULL, "NULL frame id");
+                                                    return this->id() > id ; }
+
+
+
+inline intptr_t* frame::link() const              { return (intptr_t*) *(intptr_t **)addr_at(link_offset); }
+
+
+inline intptr_t* frame::unextended_sp() const     { return _unextended_sp; }
+
+// Return address:
+
+inline address* frame::sender_pc_addr()      const { return (address*) addr_at( return_addr_offset); }
+inline address  frame::sender_pc()           const { return *sender_pc_addr(); }
+
+#ifdef CC_INTERP
+
+inline interpreterState frame::get_interpreterState() const {
+  return ((interpreterState)addr_at( -((int)sizeof(BytecodeInterpreter))/wordSize ));
+}
+
+inline intptr_t*    frame::sender_sp()        const {
+  // Hmm this seems awfully expensive QQQ, is this really called with interpreted frames?
+  if (is_interpreted_frame()) {
+    assert(false, "should never happen");
+    return get_interpreterState()->sender_sp();
+  } else {
+    return            addr_at(sender_sp_offset);
+  }
+}
+
+inline intptr_t** frame::interpreter_frame_locals_addr() const {
+  assert(is_interpreted_frame(), "must be interpreted");
+  return &(get_interpreterState()->_locals);
+}
+
+inline intptr_t* frame::interpreter_frame_bcx_addr() const {
+  assert(is_interpreted_frame(), "must be interpreted");
+  return (intptr_t*) &(get_interpreterState()->_bcp);
+}
+
+
+// Constant pool cache
+
+inline constantPoolCacheOop* frame::interpreter_frame_cache_addr() const {
+  assert(is_interpreted_frame(), "must be interpreted");
+  return &(get_interpreterState()->_constants);
+}
+
+// Method
+
+inline methodOop* frame::interpreter_frame_method_addr() const {
+  assert(is_interpreted_frame(), "must be interpreted");
+  return &(get_interpreterState()->_method);
+}
+
+inline intptr_t* frame::interpreter_frame_mdx_addr() const {
+  assert(is_interpreted_frame(), "must be interpreted");
+  return (intptr_t*) &(get_interpreterState()->_mdx);
+}
+
+// top of expression stack
+inline intptr_t* frame::interpreter_frame_tos_address() const {
+  assert(is_interpreted_frame(), "wrong frame type");
+  return get_interpreterState()->_stack + 1;
+}
+
+#else /* asm interpreter */
+inline intptr_t*    frame::sender_sp()        const { return            addr_at(   sender_sp_offset); }
+
+inline intptr_t** frame::interpreter_frame_locals_addr() const {
+  return (intptr_t**)addr_at(interpreter_frame_locals_offset);
+}
+
+inline intptr_t* frame::interpreter_frame_last_sp() const {
+  return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset);
+}
+
+inline intptr_t* frame::interpreter_frame_bcx_addr() const {
+  return (intptr_t*) addr_at(interpreter_frame_bcx_offset);
+}
+
+inline intptr_t* frame::interpreter_frame_mdx_addr() const {
+  return (intptr_t*) addr_at(interpreter_frame_mdx_offset);
+}
+
+
+// Constant pool cache
+
+inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const {
+  return (ConstantPoolCache**)addr_at(interpreter_frame_cache_offset);
+}
+
+// Method
+
+inline Method** frame::interpreter_frame_method_addr() const {
+  return (Method**)addr_at(interpreter_frame_method_offset);
+}
+
+// top of expression stack
+inline intptr_t* frame::interpreter_frame_tos_address() const {
+  intptr_t* last_sp = interpreter_frame_last_sp();
+  if (last_sp == NULL) {
+    return sp();
+  } else {
+    // sp() may have been extended or shrunk by an adapter.  At least
+    // check that we don't fall behind the legal region.
+    // For top deoptimized frame last_sp == interpreter_frame_monitor_end.
+    assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos");
+    return last_sp;
+  }
+}
+
+inline oop* frame::interpreter_frame_temp_oop_addr() const {
+  return (oop *)(fp() + interpreter_frame_oop_temp_offset);
+}
+
+#endif /* CC_INTERP */
+
+inline int frame::pd_oop_map_offset_adjustment() const {
+  return 0;
+}
+
+inline int frame::interpreter_frame_monitor_size() {
+  return BasicObjectLock::size();
+}
+
+
+// expression stack
+// (the max_stack arguments are used by the GC; see class FrameClosure)
+
+inline intptr_t* frame::interpreter_frame_expression_stack() const {
+  intptr_t* monitor_end = (intptr_t*) interpreter_frame_monitor_end();
+  return monitor_end-1;
+}
+
+
+inline jint frame::interpreter_frame_expression_stack_direction() { return -1; }
+
+
+// Entry frames
+
+inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
+ return (JavaCallWrapper**)addr_at(entry_frame_call_wrapper_offset);
+}
+
+
+// Compiled frames
+
+inline int frame::local_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors) {
+  return (nof_args - local_index + (local_index < nof_args ? 1: -1));
+}
+
+inline int frame::monitor_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors) {
+  return local_offset_for_compiler(local_index, nof_args, max_nof_locals, max_nof_monitors);
+}
+
+inline int frame::min_local_offset_for_compiler(int nof_args, int max_nof_locals, int max_nof_monitors) {
+  return (nof_args - (max_nof_locals + max_nof_monitors*2) - 1);
+}
+
+inline bool frame::volatile_across_calls(Register reg) {
+  return true;
+}
+
+
+
+inline oop frame::saved_oop_result(RegisterMap* map) const {
+  oop* result_adr = (oop *)map->location(r0->as_VMReg());
+  guarantee(result_adr != NULL, "bad register save location");
+
+  return (*result_adr);
+}
+
+inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
+  oop* result_adr = (oop *)map->location(r0->as_VMReg());
+  guarantee(result_adr != NULL, "bad register save location");
+
+  *result_adr = obj;
+}
+
+#endif // CPU_AARCH32_VM_FRAME_AARCH32_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/globalDefinitions_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_GLOBALDEFINITIONS_AARCH32_HPP
+#define CPU_AARCH32_VM_GLOBALDEFINITIONS_AARCH32_HPP
+
+const int StackAlignmentInBytes = 4;
+
+// Indicates whether the C calling conventions require that
+// 32-bit integer argument values are properly extended to 64 bits.
+// If set, SharedRuntime::c_calling_convention() must adapt
+// signatures accordingly.
+const bool CCallingConventionRequiresIntsAsLongs = false;
+
+#define SUPPORTS_NATIVE_CX8
+
+// The maximum B/BL offset range on AArch32 is 32MB.
+#undef CODE_CACHE_DEFAULT_LIMIT
+#define CODE_CACHE_DEFAULT_LIMIT (32*M)
+
+// According to the ARMv8 ARM, "Concurrent modification and execution
+// of instructions can lead to the resulting instruction performing
+// any behavior that can be achieved by executing any sequence of
+// instructions that can be executed from the same Exception level,
+// except where the instruction before modification and the
+// instruction after modification is a B, BL, NOP, BKPT, SVC, HVC, or
+// SMC instruction."
+//
+// This makes the games we play when patching difficult, so when we
+// come across an access that needs patching we deoptimize.  There are
+// ways we can avoid this, but these would slow down C1-compiled code
+// in the defauilt case.  We could revisit this decision if we get any
+// evidence that it's worth doing.
+#define DEOPTIMIZE_WHEN_PATCHING
+
+#endif // CPU_AARCH32_VM_GLOBALDEFINITIONS_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/globals_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_GLOBALS_AARCH32_HPP
+#define CPU_AARCH32_VM_GLOBALS_AARCH32_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// Sets the default values for platform dependent flags used by the runtime system.
+// (see globals.hpp)
+
+define_pd_global(bool, ConvertSleepToYield,      true);
+define_pd_global(bool, ShareVtableStubs,         true);
+define_pd_global(bool, CountInterpCalls,         true);
+define_pd_global(bool, NeedsDeoptSuspend,       false); // only register window machines need this
+
+define_pd_global(bool, ImplicitNullChecks,       true);  // Generate code for implicit null checks
+define_pd_global(bool, TrapBasedNullChecks,     false);
+define_pd_global(bool, UncommonNullCast,         true);  // Uncommon-trap NULLs past to check cast
+
+// See 4827828 for this change. There is no globals_core_i486.hpp. I can't
+// assign a different value for C2 without touching a number of files. Use
+// #ifdef to minimize the change as it's late in Mantis. -- FIXME.
+// c1 doesn't have this problem because the fix to 4858033 assures us
+// the the vep is aligned at CodeEntryAlignment whereas c2 only aligns
+// the uep and the vep doesn't get real alignment but just slops on by
+// only assured that the entry instruction meets the 5 byte size requirement.
+//#ifdef COMPILER2
+//define_pd_global(intx, CodeEntryAlignment,       64);
+//#else
+define_pd_global(intx, CodeEntryAlignment,       32);
+//#endif // COMPILER2
+define_pd_global(intx, OptoLoopAlignment,        32);
+define_pd_global(intx, InlineFrequencyCount,     100);
+
+define_pd_global(intx, StackYellowPages, 2);
+define_pd_global(intx, StackRedPages, 1);
+
+define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
+
+define_pd_global(intx, PreInflateSpin,           10);
+
+define_pd_global(bool, RewriteBytecodes,     true);
+define_pd_global(bool, RewriteFrequentPairs, true);
+
+define_pd_global(bool, UseMembar,            true);
+
+define_pd_global(bool, PreserveFramePointer, false);
+
+// GC Ergo Flags
+define_pd_global(uintx, CMSYoungGenPerWorker, 64*M);  // default max size of CMS young gen, per GC worker thread
+
+define_pd_global(uintx, TypeProfileLevel, 111);
+
+// avoid biased locking while we are bootstrapping the aarch32 build
+define_pd_global(bool, UseBiasedLocking, false);
+
+// FIXME this turned out to be needed for the core build too?
+//#if defined(COMPILER1) || defined(COMPILER2)
+define_pd_global(intx, InlineSmallCode,          1000);
+//#endif
+
+#define UseBuiltinSim           false
+#define NotifySimulator         false
+#define UseSimulatorCache       false
+#define DisableBCCheck          true
+#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
+                                                                        \
+  product(bool, NearCpool, true,                                        \
+         "constant pool is close to instructions")                      \
+                                                                        \
+  product(bool, UseBarriersForVolatile, false,                          \
+          "Use memory barriers to implement volatile accesses")         \
+  product(bool, TraceTraps, false, "Trace all traps the signal handler")
+
+
+#endif // CPU_AARCH32_VM_GLOBALS_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/icBuffer_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/icBuffer.hpp"
+#include "gc_interface/collectedHeap.inline.hpp"
+#include "interpreter/bytecodes.hpp"
+#include "memory/resourceArea.hpp"
+#include "nativeInst_aarch32.hpp"
+#include "oops/oop.inline.hpp"
+
+int InlineCacheBuffer::ic_stub_code_size() {
+  return (MacroAssembler::far_branches() ? 6 : 4) * NativeInstruction::instruction_size;
+}
+
+#define __ masm->
+
+void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
+  ResourceMark rm;
+  CodeBuffer      code(code_begin, ic_stub_code_size());
+  MacroAssembler* masm            = new MacroAssembler(&code);
+  // note: even though the code contains an embedded value, we do not need reloc info
+  // because
+  // (1) the value is old (i.e., doesn't matter for scavenges)
+  // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
+  // assert(cached_value == NULL || cached_oop->is_perm(), "must be perm oop");
+
+  address start = __ pc();
+  Label l;
+  __ ldr(rscratch2, l);
+  __ far_jump(ExternalAddress(entry_point));
+  __ align(wordSize);
+  __ bind(l);
+  __ emit_int64((int64_t)cached_value);
+  // Only need to invalidate the 1st two instructions - not the whole ic stub
+  ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size());
+  assert(__ pc() - start == ic_stub_code_size(), "must be");
+}
+
+address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
+  NativeMovConstReg* move = nativeMovConstReg_at(code_begin);   // creation also verifies the object
+  NativeJump* jump = nativeJump_at(code_begin + 4);
+  return jump->jump_destination();
+}
+
+
+void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
+  // The word containing the cached value is at the end of this IC buffer
+  uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize);
+  void* o = (void*)*p;
+  return o;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/icache_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.hpp"
+#include "runtime/icache.hpp"
+
+extern void aarch32TestHook();
+
+void ICacheStubGenerator::generate_icache_flush(
+                ICache::flush_icache_stub_t* flush_icache_stub) {
+  // Give anyone who calls this a surprise
+  *flush_icache_stub = (ICache::flush_icache_stub_t)NULL;
+}
+
+void ICache::initialize() {
+  aarch32TestHook();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/icache_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH32_VM_ICACHE_AARCH32_HPP
+#define CPU_AARCH32_VM_ICACHE_AARCH32_HPP
+
+// Interface for updating the instruction cache.  Whenever the VM
+// modifies code, part of the processor instruction cache potentially
+// has to be flushed.
+
+class ICache : public AbstractICache {
+ public:
+  static void initialize();
+  static void invalidate_word(address addr) {
+    __clear_cache((char *)addr, (char *)(addr + 3));
+  }
+  static void invalidate_range(address start, int nbytes) {
+    __clear_cache((char *)start, (char *)(start + nbytes));
+  }
+};
+
+#endif // CPU_AARCH32_VM_ICACHE_AARCH32_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/immediate_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdlib.h>
+#include "decode_aarch32.hpp"
+#include "immediate_aarch32.hpp"
+/*
+// there are at most 2^13 possible logical immediate encodings
+// however, some combinations of immr and imms are invalid
+static const unsigned  LI_TABLE_SIZE = (1 << 13);
+
+static int li_table_entry_count;
+
+// for forward lookup we just use a direct array lookup
+// and assume that the cient has supplied a valid encoding
+// table[encoding] = immediate
+static u_int64_t LITable[LI_TABLE_SIZE];
+
+// for reverse lookup we need a sparse map so we store a table of
+// immediate and encoding pairs sorted by immediate value
+
+struct li_pair {
+  u_int64_t immediate;
+  u_int32_t encoding;
+};
+
+static struct li_pair InverseLITable[LI_TABLE_SIZE];
+
+// comparator to sort entries in the inverse table
+int compare_immediate_pair(const void *i1, const void *i2)
+{
+  struct li_pair *li1 = (struct li_pair *)i1;
+  struct li_pair *li2 = (struct li_pair *)i2;
+  if (li1->immediate < li2->immediate) {
+    return -1;
+  }
+  if (li1->immediate > li2->immediate) {
+    return 1;
+  }
+  return 0;
+}
+
+// helper functions used by expandLogicalImmediate
+
+// for i = 1, ... N result<i-1> = 1 other bits are zero
+static inline u_int64_t ones(int N)
+{
+  return (N == 64 ? (u_int64_t)-1UL : ((1UL << N) - 1));
+}
+
+// result<0> to val<N>
+static inline u_int64_t pickbit(u_int64_t val, int N)
+{
+  return pickbits64(val, N, N);
+}
+
+
+// SPEC bits(M*N) Replicate(bits(M) x, integer N);
+// this is just an educated guess
+
+u_int64_t replicate(u_int64_t bits, int nbits, int count)
+{
+  u_int64_t result = 0;
+  // nbits may be 64 in which case we want mask to be -1
+  u_int64_t mask = ones(nbits);
+  for (int i = 0; i < count ; i++) {
+    result <<= nbits;
+    result |= (bits & mask);
+  }
+  return result;
+}
+
+// this function writes the supplied bimm reference and returns a
+// boolean to indicate success (1) or fail (0) because an illegal
+// encoding must be treated as an UNALLOC instruction
+
+// construct a 32 bit immediate value for a logical immediate operation
+int expandLogicalImmediate(u_int32_t immN, u_int32_t immr,
+                            u_int32_t imms, u_int64_t &bimm)
+{
+  int len;                  // ought to be <= 6
+  u_int32_t levels;         // 6 bits
+  u_int32_t tmask_and;      // 6 bits
+  u_int32_t wmask_and;      // 6 bits
+  u_int32_t tmask_or;       // 6 bits
+  u_int32_t wmask_or;       // 6 bits
+  u_int64_t imm64;          // 64 bits
+  u_int64_t tmask, wmask;   // 64 bits
+  u_int32_t S, R, diff;     // 6 bits?
+
+  if (immN == 1) {
+    len = 6; // looks like 7 given the spec above but this cannot be!
+  } else {
+    len = 0;
+    u_int32_t val = (~imms & 0x3f);
+    for (int i = 5; i > 0; i--) {
+      if (val & (1 << i)) {
+        len = i;
+        break;
+      }
+    }
+    if (len < 1) {
+      return 0;
+    }
+    // for valid inputs leading 1s in immr must be less than leading
+    // zeros in imms
+    int len2 = 0;                   // ought to be < len
+    u_int32_t val2 = (~immr & 0x3f);
+    for (int i = 5; i > 0; i--) {
+      if (!(val2 & (1 << i))) {
+        len2 = i;
+        break;
+      }
+    }
+    if (len2 >= len) {
+      return 0;
+    }
+  }
+
+  levels = (1 << len) - 1;
+
+  if ((imms & levels) == levels) {
+    return 0;
+  }
+
+  S = imms & levels;
+  R = immr & levels;
+
+ // 6 bit arithmetic!
+  diff = S - R;
+  tmask_and = (diff | ~levels) & 0x3f;
+  tmask_or = (diff & levels) & 0x3f;
+  tmask = 0xffffffffffffffffULL;
+
+  for (int i = 0; i < 6; i++) {
+    int nbits = 1 << i;
+    u_int64_t and_bit = pickbit(tmask_and, i);
+    u_int64_t or_bit = pickbit(tmask_or, i);
+    u_int64_t and_bits_sub = replicate(and_bit, 1, nbits);
+    u_int64_t or_bits_sub = replicate(or_bit, 1, nbits);
+    u_int64_t and_bits_top = (and_bits_sub << nbits) | ones(nbits);
+    u_int64_t or_bits_top = (0 << nbits) | or_bits_sub;
+
+    tmask = ((tmask
+              & (replicate(and_bits_top, 2 * nbits, 32 / nbits)))
+             | replicate(or_bits_top, 2 * nbits, 32 / nbits));
+  }
+
+  wmask_and = (immr | ~levels) & 0x3f;
+  wmask_or = (immr & levels) & 0x3f;
+
+  wmask = 0;
+
+  for (int i = 0; i < 6; i++) {
+    int nbits = 1 << i;
+    u_int64_t and_bit = pickbit(wmask_and, i);
+    u_int64_t or_bit = pickbit(wmask_or, i);
+    u_int64_t and_bits_sub = replicate(and_bit, 1, nbits);
+    u_int64_t or_bits_sub = replicate(or_bit, 1, nbits);
+    u_int64_t and_bits_top = (ones(nbits) << nbits) | and_bits_sub;
+    u_int64_t or_bits_top = (or_bits_sub << nbits) | 0;
+
+    wmask = ((wmask
+              & (replicate(and_bits_top, 2 * nbits, 32 / nbits)))
+             | replicate(or_bits_top, 2 * nbits, 32 / nbits));
+  }
+
+  if (diff & (1U << 6)) {
+    imm64 = tmask & wmask;
+  } else {
+    imm64 = tmask | wmask;
+  }
+
+
+  bimm = imm64;
+  return 1;
+}
+
+// constructor to initialise the lookup tables
+
+//static void initLITables() __attribute__ ((constructor));
+static void initLITables()
+{
+  li_table_entry_count = 0;
+  for (unsigned index = 0; index < LI_TABLE_SIZE; index++) {
+    u_int32_t N = uimm(index, 12, 12);
+    u_int32_t immr = uimm(index, 11, 6);
+    u_int32_t imms = uimm(index, 5, 0);
+    if (expandLogicalImmediate(N, immr, imms, LITable[index])) {
+      InverseLITable[li_table_entry_count].immediate = LITable[index];
+      InverseLITable[li_table_entry_count].encoding = index;
+      li_table_entry_count++;
+    }
+  }
+  // now sort the inverse table
+  qsort(InverseLITable, li_table_entry_count,
+        sizeof(InverseLITable[0]), compare_immediate_pair);
+}
+
+// public APIs provided for logical immediate lookup and reverse lookup
+
+u_int64_t logical_immediate_for_encoding(u_int32_t encoding)
+{
+  return LITable[encoding];
+}
+
+u_int32_t encoding_for_logical_immediate(u_int64_t immediate)
+{
+  struct li_pair pair;
+  struct li_pair *result;
+
+  pair.immediate = immediate;
+
+  result = (struct li_pair *)
+    bsearch(&pair, InverseLITable, li_table_entry_count,
+            sizeof(InverseLITable[0]), compare_immediate_pair);
+
+  if (result) {
+    return result->encoding;
+  }
+
+  return 0xffffffff;
+}
+
+// floating point immediates are encoded in 8 bits
+// fpimm[7] = sign bit
+// fpimm[6:4] = signed exponent
+// fpimm[3:0] = fraction (assuming leading 1)
+// i.e. F = s * 1.f * 2^(e - b)
+
+u_int64_t fp_immediate_for_encoding(u_int32_t imm8, int is_dp)
+{
+  union {
+    float fpval;
+    double dpval;
+    u_int64_t val;
+  };
+
+  u_int32_t s, e, f;
+  s = (imm8 >> 7 ) & 0x1;
+  e = (imm8 >> 4) & 0x7;
+  f = imm8 & 0xf;
+  // the fp value is s * n/16 * 2r where n is 16+e
+  fpval = (16.0 + f) / 16.0;
+  // n.b. exponent is signed
+  if (e < 4) {
+    int epos = e;
+    for (int i = 0; i <= epos; i++) {
+      fpval *= 2.0;
+    }
+  } else {
+    int eneg = 7 - e;
+    for (int i = 0; i < eneg; i++) {
+      fpval /= 2.0;
+    }
+  }
+
+  if (s) {
+    fpval = -fpval;
+  }
+  if (is_dp) {
+    dpval = (double)fpval;
+  }
+  return val;
+}
+
+u_int32_t encoding_for_fp_immediate(float immediate)
+{
+  // given a float which is of the form
+  //
+  //     s * n/16 * 2r
+  //
+  // where n is 16+f and imm1:s, imm4:f, simm3:r
+  // return the imm8 result [s:r:f]
+  //
+
+  union {
+    float fpval;
+    u_int32_t val;
+  };
+  fpval = immediate;
+  u_int32_t s, r, f, res;
+  // sign bit is 31
+  s = (val >> 31) & 0x1;
+  // exponent is bits 30-23 but we only want the bottom 3 bits
+  // strictly we ought to check that the bits bits 30-25 are
+  // either all 1s or all 0s
+  r = (val >> 23) & 0x7;
+  // fraction is bits 22-0
+  f = (val >> 19) & 0xf;
+  res = (s << 7) | (r << 4) | f;
+  return res;
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/immediate_aarch32.hpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef _IMMEDIATE_H
+#define _IMMEDIATE_H
+
+#include <sys/types.h>
+
+/*
+ * functions to map backwards and forwards between logical or floating
+ * point immediates and their corresponding encodings. the mapping
+ * from encoding to immediate is required by the simulator. the reverse
+ * mapping is required by the OpenJDK assembler.
+ *
+ * a logical immediate value supplied to or returned from a map lookup
+ * is always 64 bits. this is sufficient for looking up 32 bit
+ * immediates or their encodings since a 32 bit immediate has the same
+ * encoding as the 64 bit immediate produced by concatenating the
+ * immediate with itself.
+ *
+ * a logical immediate encoding is 13 bits N:immr:imms (3 fields of
+ * widths 1:6:6 -- see the arm spec). they appear as bits [22:10] of a
+ * logical immediate instruction. encodings are supplied and returned
+ * as 32 bit values. if a given 13 bit immediate has no corresponding
+ * encoding then a map lookup will return 0xffffffff.
+ */
+
+//u_int64_t logical_immediate_for_encoding(u_int32_t encoding);
+//u_int32_t encoding_for_logical_immediate(u_int64_t immediate);
+//u_int64_t fp_immediate_for_encoding(u_int32_t imm8, int is_dp);
+//u_int32_t encoding_for_fp_immediate(float immediate);
+
+#endif // _IMMEDIATE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpu/aarch32/vm/interp_masm_aarch32.cpp	Wed Dec 30 09:24:57 2015 +0000
@@ -0,0 +1,1765 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "interp_masm_aarch32.hpp"
+#include "interpreter/interpreter.hpp"
+#include "interpreter/interpreterRuntime.hpp"
+#include "oops/arrayOop.hpp"
+#include "oops/markOop.hpp"
+#include "oops/methodData.hpp"
+#include "oops/method.hpp"
+#include "prims/jvmtiExport.hpp"
+#include "prims/jvmtiRedefineClassesTrace.hpp"
+#include "prims/jvmtiThreadState.hpp"
+#include "runtime/basicLock.hpp"
+#include "runtime/biasedLocking.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/thread.inline.hpp"
+
+
+// Implementation of InterpreterMacroAssembler
+
+#ifndef CC_INTERP
+
+void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) {
+  if (JvmtiExport::can_pop_frame()) {
+    Label L;
+    // Initiate popframe handling only if it is not already being
+    // processed.  If the flag has the popframe_processing bit set, it
+    // means that this code is called *during* popframe handling - we
+    // don't want to reenter.
+    // This method is only called just after the call into the vm in
+    // call_VM_base, so the arg registers are available.
+    ldr(rscratch1, Address(rthread, JavaThread::popframe_condition_offset()));
+    tst(rscratch1, JavaThread::popframe_pending_bit);
+    b(L, Assembler::EQ);
+    tst(rscratch1, JavaThread::popframe_processing_bit);
+    b(L, Assembler::NE);
+    // Call Interpreter::remove_activation_preserving_args_entry() to get the
+    // address of the same-named entrypoint in the generated interpreter code.
+    call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry));
+    b(r0);
+    bind(L);
+  }
+}
+
+
+void InterpreterMacroAssembler::load_earlyret_value(TosState state) {
+  ldr(r2, Address(rthread, JavaThread::jvmti_thread_state_offset()));
+  const Address tos_addr(r2, JvmtiThreadState::earlyret_tos_offset());
+  const Address oop_addr(r2, JvmtiThreadState::earlyret_oop_offset());
+  const Address val_addr(r2, JvmtiThreadState::earlyret_value_offset());
+  switch (state) {
+    case atos: ldr(r0, oop_addr);
+               mov(rscratch1, 0);
+               str(rscratch1, oop_addr);
+               verify_oop(r0, state);               break;
+    case ltos: ldrd(r0, val_addr);                  break;
+    case btos:                                   // fall through
+    case ctos:                                   // fall through
+    case stos:                                   // fall through
+    case itos: ldr(r0, val_addr);                   break;
+    case ftos: vldr_f32(d0, val_addr);              break;
+    case dtos: vldr_f64(d0, val_addr);              break;
+    case vtos: /* nothing to do */                  break;
+    default  : ShouldNotReachHere();
+  }
+  // Clean up tos value in the thread object
+  mov(rscratch1, (int) ilgl);
+  str(rscratch1, tos_addr);
+  mov(rscratch1, 0);
+  str(rscratch1, val_addr);
+}
+
+
+void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) {
+  if (JvmtiExport::can_force_early_return()) {
+    Label L;
+    ldr(rscratch1, Address(rthread, JavaThread::jvmti_thread_state_offset()));
+    cbz(rscratch1, L); // if (thread->jvmti_thread_state() == NULL) exit;
+
+    // Initiate earlyret handling only if it is not already being processed.
+    // If the flag has the earlyret_processing bit set, it means that this code
+    // is called *during* earlyret handling - we don't want to reenter.
+    ldr(rscratch1, Address(rscratch1, JvmtiThreadState::earlyret_state_offset()));
+    cmp(rscratch1, JvmtiThreadState::earlyret_pending);
+    b(L, Assembler::NE);
+
+    // Call Interpreter::remove_activation_early_entry() to get the address of the
+    // same-named entrypoint in the generated interpreter code.
+    ldr(rscratch1, Address(rthread, JavaThread::jvmti_thread_state_offset()));
+    ldr(rscratch1, Address(rscratch1, JvmtiThreadState::earlyret_tos_offset()));
+    call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), rscratch1);
+    b(r0);
+    bind(L);
+  }
+}
+
+void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(
+  Register reg,
+  int bcp_offset) {
+  assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode");
+  ldrh(reg, Address(rbcp, bcp_offset));
+  rev16(reg, reg);
+}
+
+void InterpreterMacroAssembler::get_dispatch() {
+  mov(rdispatch, ExternalAddress((address)Interpreter::dispatch_table()));
+}
+
+void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
+                                                       int bcp_offset,
+                                                       size_t index_size) {
+  assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+  if (index_size == sizeof(u2)) {
+    load_unsigned_short(index, Address(rbcp, bcp_offset));
+  } else if (index_size == sizeof(u4)) {
+    // assert(EnableInvokeDynamic, "giant index used only for JSR 292");
+    ldr(index, Address(rbcp, bcp_offset));
+    // Check if the secondary index definition is still ~x, otherwise
+    // we have to change the following assembler code to calculate the
+    // plain index.
+    assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line");
+    inv(index, index);  // convert to plain index
+  } else if (index_size == sizeof(u1)) {
+    load_unsigned_byte(index, Address(rbcp, bcp_offset));
+  } else {
+    ShouldNotReachHere();
+  }
+}
+
+// Return
+// Rindex: index into constant pool
+// Rcache: address of cache entry - ConstantPoolCache::base_offset()
+//
+// A caller must add ConstantPoolCache::base_offset() to Rcache to get
+// the true address of the cache entry.
+//
+void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
+                                                           Register index,
+                                                           int bcp_offset,
+                                                           size_t index_size) {
+  assert_different_registers(cache, index);
+  assert_different_registers(cache, rcpool);
+  get_cache_index_at_bcp(index, bcp_offset, index_size);
+  assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
+  // convert from field index to ConstantPoolCacheEntry
+  // aarch32 already has the cache in rcpool so there is no need to
+  // install it in cache. instead we pre-add the indexed offset to
+  // rcpool and return it in cache. All clients of this method need to
+  // be modified accordingly.
+  add(cache, rcpool, index, lsl( exact_log2(4) + exact_log2(wordSize)));
+}
+
+
+void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
+                                                                        Register index,
+                                                                        Register bytecode,
+                                                                        int byte_no,
+                                                                        int bcp_offset,
+                                                                        size_t index_size) {
+  get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size);
+  // We use a 32-bit load here since the layout of 64-bit words on
+  // little-endian machines allow us that.
+  // n.b. unlike x86 cache alreeady includes the index offset
+  ldr(bytecode, Address(cache,
+                        ConstantPoolCache::base_offset()
+                        + ConstantPoolCacheEntry::indices_offset()));
+  const int shift_count = (1 + byte_no) * BitsPerByte;
+  //ubfx(bytecode, bytecode, shift_count, BitsPerByte);
+  assert(shift_count >= 0 && shift_count <= 24 && 0 == (shift_count & 7), "Invalid shift count");
+  uxtb(bytecode, bytecode, ror(shift_count));
+}
+
+void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
+                                                               Register tmp,
+                                                               int bcp_offset,
+                                                               size_t index_size) {
+  assert(cache != tmp, "must use different register");
+  get_cache_index_at_bcp(tmp, bcp_offset, index_size);
+  assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
+  // convert from field index to ConstantPoolCacheEntry index
+  // and from word offset to byte offset
+  assert(exact_log2(in_bytes(ConstantPoolCacheEntry::size_in_bytes())) == 2 + LogBytesPerWord, "else change next line");
+  ldr(cache, Address(rfp, frame::interpreter_frame_cache_offset * wordSize));
+  // skip past the header
+  add(cache, cache, in_bytes(ConstantPoolCache::base_offset()));
+  add(cache, cache, tmp, lsl(2 + LogBytesPerWord));  // construct pointer to cache entry
+}
+
+void InterpreterMacroAssembler::get_method_counters(Register method,
+                                                    Register mcs, Label& skip) {
+  Label has_counters;
+  ldr(mcs, Address(method, Method::method_counters_offset()));
+  cbnz(mcs, has_counters);
+  call_VM(noreg, CAST_FROM_FN_PTR(address,
+          InterpreterRuntime::build_method_counters), method);
+  ldr(mcs, Address(method, Method::method_counters_offset()));
+  cbz(mcs, skip); // No MethodCounters allocated, OutOfMemory
+  bind(has_counters);
+}
+
+// Load object from cpool->resolved_references(index)
+void InterpreterMacroAssembler::load_resolved_reference_at_index(
+                                           Register result, Register index) {
+  assert_different_registers(result, index);
+  // convert from field index to resolved_references() index and from
+  // word index to byte offset. Since this is a java object, it can be compressed
+  Register tmp = index;  // reuse
+  //lsl(tmp, tmp, LogBytesPerHeapOop);
+  //FIXME Rolled into add - does it work?
+
+  get_constant_pool(result);
+  // load pointer for resolved_references[] objArray
+  ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
+  // JNIHandles::resolve(obj);
+  ldr(result, Address(result, 0));
+  // Add in the index
+  add(result, result, tmp, lsl(LogBytesPerHeapOop));
+  load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+}
+
+// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
+// subtype of super_klass.
+//
+// Args:
+//      r0: superklass
+//      Rsub_klass: subklass
+//
+// Kills:
+//      r2, r5
+void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
+                                                  Label& ok_is_subtype) {
+  assert(Rsub_klass != r0, "r0 holds superklass");
+  assert(Rsub_klass != r2, "r2 holds 2ndary super array length");
+  assert(Rsub_klass != r14, "r14 holds 2ndary super array scan ptr");
+
+  // Profile the not-null value's klass.
+  profile_typecheck(r2, Rsub_klass, r14); // blows r2
+
+  // Do the check.
+  check_klass_subtype(Rsub_klass, r0, r2, ok_is_subtype); // blows r2
+
+  // Profile the failure of the check.
+  profile_typecheck_failed(r2); // blows r2
+}
+
+// Java Expression Stack
+
+void InterpreterMacroAssembler::pop_ptr(Register r) {
+  ldr(r, post(sp, wordSize));
+}
+
+void InterpreterMacroAssembler::pop_i(Register r) {
+  ldr(r, post(sp, wordSize));
+}
+
+void InterpreterMacroAssembler::pop_l(Register r) {
+  //Now implicitly loads two consecutive registers
+  ldrd(r, post(sp, 2 * Interpreter::stackElementSize));
+}
+
+void InterpreterMacroAssembler::push_ptr(Register r) {
+  str(r, pre(sp, -wordSize));
+}
+
+void InterpreterMacroAssembler::push_i(Register r) {
+  str(r, pre(sp, -wordSize));
+}
+
+void InterpreterMacroAssembler::push_l(Register r) {
+  strd(r, pre(sp, -2 * wordSize));
+}
+
+void InterpreterMacroAssembler::pop_f(FloatRegister r) {
+  //vldr_f32(r, post(esp, wordSize));
+  vldmia_f32(sp, FloatRegSet(r).bits());
+  str(rscratch1, Address(pre(sp, -wordSize)));
+  vmov_f32(rscratch1, r);
+  reg_printf(" pop_f 0x%08x\n", rscratch1);
+  ldr(rscratch1, Address(post(sp, wordSize)));
+}
+
+void InterpreterMacroAssembler::pop_d(FloatRegister r) {
+  //vldr_f64(r, post(esp, 2 * Interpreter::stackElementSize));
+  vldmia_f64(sp, FloatRegSet(r).bits());
+}
+
+void InterpreterMacroAssembler::push_f(FloatRegister r) {
+  //vstr_f32(r, pre(esp, -wordSize));
+  vstmdb_f32(sp, FloatRegSet(r).bits());
+  str(rscratch1, Address(pre(sp, -wordSize)));
+  vmov_f32(rscratch1, r);
+  reg_printf("push_f 0x%08x\n", rscratch1);
+  ldr(rscratch1, Address(post(sp, wordSize)));
+}
+
+void InterpreterMacroAssembler::push_d(FloatRegister r) {
+  //vstr_f64(r, pre(esp, 2* -wordSize));
+  vstmdb_f64(sp, FloatRegSet(r).bits());
+}
+
+void InterpreterMacroAssembler::pop(TosState state) {
+  switch (state) {
+  case atos: pop_ptr();                 break;
+  case btos:
+  case ctos:
+  case stos:
+  case itos: pop_i();                   break;
+  case ltos: pop_l();                   break;
+  case ftos: pop_f();                   break;
+  case dtos: pop_d();                   break;
+  case vtos: /* nothing to do */        break;
+  default:   ShouldNotReachHere();
+  }
+  verify_oop(r0, state);
+}
+
+void InterpreterMacroAssembler::push(TosState state) {
+  verify_oop(r0, state);
+  switch (state) {
+  case atos: push_ptr();                break;
+  case btos:
+  case ctos:
+  case stos:
+  case itos: push_i();                  break;
+  case ltos: push_l();                  break;
+  case ftos: push_f();                  break;
+  case dtos: push_d();                  break;
+  case vtos: /* nothing to do */        break;
+  default  : ShouldNotReachHere();
+  }
+}
+
+// Helpers for swap and dup
+void InterpreterMacroAssembler::load_ptr(int n, Register val) {
+  ldr(val, Address(esp, Interpreter::expr_offset_in_bytes(n)));
+}
+
+void InterpreterMacroAssembler::store_ptr(int n, Register val) {
+  str(val, Address(esp, Interpreter::expr_offset_in_bytes(n)));
+}
+
+
+void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
+  // record last_sp
+  str(sp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+}
+
+void print_method_name(Method* m, char * msg) {
+  if(MacroAssembler::enable_debug) {
+    printf("%s", msg);
+    fflush(stdout);
+    m->print_short_name();
+    printf("\n");
+    fflush(stdout);
+  }
+}
+
+// Jump to from_interpreted entry of a call unless single stepping is possible
+// in this thread in which case we must call the i2i entry
+void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
+  prepare_to_jump_from_interpreted();
+
+  if (JvmtiExport::can_post_interpreter_events()) {
+    Label run_compiled_code;
+    // JVMTI events, such as single-stepping, are implemented partly by avoiding running
+    // compiled code in threads for which the event is enabled.  Check here for
+    // interp_only_mode if these events CAN be enabled.
+    // interp_only is an int, on little endian it is sufficient to test the byte only
+    // Is a cmpl faster?
+    ldr(temp, Address(rthread, JavaThread::interp_only_mode_offset()));
+    cbz(temp, run_compiled_code);
+    ldr(temp, Address(method, Method::interpreter_entry_offset()));
+    b(temp);
+    bind(run_compiled_code);
+  }
+
+  ldr(temp, Address(method, Method::from_interpreted_offset()));
+  b(temp);
+}
+
+// The following two routines provide a hook so that an implementation
+// can schedule the dispatch in two parts.  amd64 does not do this.
+void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) {
+}
+
+void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) {
+    dispatch_next(state, step);
+}
+
+void InterpreterMacroAssembler::dispatch_base(TosState state,
+                                              address* table,
+                                              bool verifyoop) {
+  if (VerifyActivationFrameSize) {
+    Unimplemented();
+  }
+  if (verifyoop) {
+    verify_oop(r0, state);
+  }
+
+        /* Debugging code */
+        bytecode_seen(rscratch1, r3);
+
+        /*{
+                Label skip;
+
+                mov(r3, (address)&MacroAssembler::bytecodes_executed);
+                ldr(r2, r3);
+                add(r2, r2, 1);
+                str(r2, r3);
+                // Print out every 16384 (needs to be a power of two).
+                mov(r3, 16384 - 1);
+                tst(r2, r3);
+                b(skip, Assembler::NE);
+                reg_printf_important("Executed %d bytecodes.\n", r2);
+                bind(skip);
+        }*/
+
+
+        /*mov(r3, (address)&MacroAssembler::bytecodes_until_print);
+        ldr(r2, Address(r3));
+        cmp(r2, 0);
+
+        sub(r2, r2, 1, Assembler::NE);
+        str(r2, Address(r3), Assembler::NE);
+
+        mov(r2, 1, Assembler::EQ);
+        mov(r3, (address)&MacroAssembler::enable_debug, Assembler::EQ);
+        str(r2, Address(r3), Assembler::EQ);
+
+        mov(r3, (address)&MacroAssembler::enable_method_debug, Assembler::EQ);
+        str(r2, Address(r3), Assembler::EQ);*/
+
+        /*Label end;
+        cmp(r2, 0);
+        b(end, Assembler::NE);
+        stop("got to end of bytecodes");
+        bind(end);*/
+
+        get_bytecode(r14, rscratch1);
+        reg_printf("Dispatching bytecode %s (%d) @ BCP = %p\n", r14, rscratch1, rbcp);
+        /* End debugging code */
+
+
+  if (table == Interpreter::dispatch_table(state)) {
+    add(rscratch2, rscratch1, Interpreter::distance_from_dispatch_table(state));
+    ldr(r15_pc, Address(rdispatch, rscratch2, lsl(2)));
+  } else {
+    mov(rscratch2, (address)table);
+    ldr(r15_pc, Address(rscratch2, rscratch1, lsl(2)));
+  }
+}
+
+void InterpreterMacroAssembler::dispatch_only(TosState state) {
+  dispatch_base(state, Interpreter::dispatch_table(state));
+}
+
+void InterpreterMacroAssembler::dispatch_only_normal(TosState state) {
+  dispatch_base(state, Interpreter::normal_table(state));
+}
+
+void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) {
+  dispatch_base(state, Interpreter::normal_table(state), false);
+}
+
+
+void InterpreterMacroAssembler::dispatch_next(TosState state, int step) {
+  // load next bytecode
+  ldrb(rscratch1, Address(pre(rbcp, step)));
+  dispatch_base(state, Interpreter::dispatch_table(state));
+}
+
+void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) {
+  // load current bytecode
+  ldrb(rscratch1, Address(rbcp, 0));
+  dispatch_base(state, table);
+}
+
+// remove activation
+//
+// Unlock the receiver if this is a synchronized method.
+// Unlock any Java monitors from syncronized blocks.
+// Remove the activation from the stack.
+//
+// If there are locked Java monitors
+//    If throw_monitor_exception
+//       throws IllegalMonitorStateException
+//    Else if install_monitor_exception
+//       installs IllegalMonitorStateException
+//    Else
+//       no error processing
+void InterpreterMacroAssembler::remove_activation(
+        TosState state,
+        bool throw_monitor_exception,
+        bool install_monitor_exception,
+        bool notify_jvmdi) {
+  // Note: Registers r3 xmm0 may be in use for the
+  // result check if synchronized method
+  Label unlocked, unlock, no_unlock;
+
+  // get the value of _do_not_unlock_if_synchronized into r3
+  const Address do_not_unlock_if_synchronized(rthread,
+    in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
+  ldrb(r3, do_not_unlock_if_synchronized);
+  mov(rscratch1, 0);
+  strb(rscratch1, do_not_unlock_if_synchronized); // reset the flag
+
+ // get method access flags
+  ldr(rscratch1, Address(rfp, frame::interpreter_frame_method_offset * wordSize));
+  ldr(r2, Address(rscratch1, Method::access_flags_offset()));
+  tst(r2, JVM_ACC_SYNCHRONIZED);
+  b(unlocked, Assembler::EQ);
+
+  // Don't unlock anything if the _do_not_unlock_if_synchronized flag
+  // is set.
+  cbnz(r3, no_unlock);
+
+  // unlock monitor
+  push(state); // save result
+
+  // BasicObjectLock will be first in list, since this is a
+  // synchronized method. However, need to check that the object has
+  // not been unlocked by an explicit monitorexit bytecode.
+  const Address monitor(rfp, frame::interpreter_frame_initial_sp_offset *
+                        wordSize - (int) sizeof(BasicObjectLock));
+  // We use c_rarg1 so that if we go slow path it will be the correct
+  // register for unlock_object to pass to VM directly
+  lea(c_rarg1, monitor); // address of first monitor
+
+  ldr(r0, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()));
+  cbnz(r0, unlock);
+
+  pop(state);
+  if (throw_monitor_exception) {
+    // Entry already unlocked, need to throw exception
+    call_VM(noreg, CAST_FROM_FN_PTR(address,
+                   InterpreterRuntime::throw_illegal_monitor_state_exception));
+    should_not_reach_here();
+  } else {
+    // Monitor already unlocked during a stack unroll. If requested,
+    // install an illegal_monitor_state_exception.  Continue with
+    // stack unrolling.
+    if (install_monitor_exception) {
+      call_VM(noreg, CAST_FROM_FN_PTR(address,
+                     InterpreterRuntime::new_illegal_monitor_state_exception));
+    }
+    b(unlocked);
+  }
+
+  bind(unlock);
+  unlock_object(c_rarg1);
+  pop(state);
+
+  // Check that for block-structured locking (i.e., that all locked
+  // objects has been unlocked)
+  bind(unlocked);
+
+  // r0: Might contain return value
+        // FIXME r1 : Might contain the value too
+
+  // Check that all monitors are unlocked
+  {
+    Label loop, exception, entry, restart;
+    const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
+    const Address monitor_block_top(
+        rfp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
+    const Address monitor_block_bot(
+        rfp, frame::interpreter_frame_initial_sp_offset * wordSize);
+
+    bind(restart);
+    // We can't use c_rarg1 as it might contain a result
+    ldr(c_rarg2, monitor_block_top); // points to current entry, starting
+                                     // with top-most entry
+    lea(r14, monitor_block_bot);  // points to word before bottom of
+                                  // monitor block
+    b(entry);
+
+    // Entry already locked, need to throw exception
+    bind(exception);
+
+    if (throw_monitor_exception) {
+      // Throw exception
+      MacroAssembler::call_VM(noreg,
+                              CAST_FROM_FN_PTR(address, InterpreterRuntime::
+                                   throw_illegal_monitor_state_exception));
+      should_not_reach_here();
+    } else {
+      // Stack unrolling. Unlock object and install illegal_monitor_exception.
+      // Unlock does not block, so don't have to worry about the frame.
+      // We don't have to preserve c_rarg1 since we are going to throw an exception.
+
+      push(state);
+      mov(c_rarg1, c_rarg2);
+      unlock_object(c_rarg1);
+      pop(state);
+
+      if (install_monitor_exception) {
+        call_VM(noreg, CAST_FROM_FN_PTR(address,
+                                        InterpreterRuntime::
+                                        new_illegal_monitor_state_exception));
+      }
+
+      b(restart);
+    }
+
+    bind(loop);
+    // check if current entry is used
+    ldr(rscratch1, Address(c_rarg2, BasicObjectLock::obj_offset_in_bytes()));
+    cbnz(rscratch1, exception);
+
+    add(c_rarg2, c_rarg2, entry_size); // otherwise advance to next entry
+    bind(entry);
+    cmp(c_rarg2, r14); // check if bottom reached
+    b(loop, Assembler::NE); // if not at bottom then check this entry
+  }
+
+  bind(no_unlock);
+
+  // jvmti support
+  if (notify_jvmdi) {
+    notify_method_exit(state, NotifyJVMTI);    // preserve TOSCA
+  } else {
+    notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA
+  }
+
+  // remove activation
+  // get sender esp
+  ldr(rscratch1,
+      Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize));
+  // remove frame anchor
+  leave();
+  // If we're returning to interpreted code we will shortly be
+  // adjusting SP to allow some space for ESP.  If we're returning to
+  // compiled code the saved sender SP was saved in sender_sp, so this
+  // restores it.
+  //bic(sp, rscratch1, 0xf); changed to not drop it as this is the esp
+  mov(sp, rscratch1);
+}
+
+#endif // C_INTERP
+
+// Lock object
+//
+// Args:
+//      c_rarg1: BasicObjectLock to be used for locking
+//
+// Kills:
+//      r0
+//      c_rarg0, c_rarg1, c_rarg2, c_rarg3, .. (param regs)
+//      rscratch1, rscratch2 (scratch regs)
+void InterpreterMacroAssembler::lock_object(Register lock_reg)
+{
+  reg_printf("LOCK:\n");
+  assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1");
+  if (UseHeavyMonitors) {
+    call_VM(noreg,
+            CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
+            lock_reg);
+  } else {
+    Label done;
+
+    const Register swap_reg = r0;
+    const Register obj_reg = c_rarg3; // Will contain the oop
+
+    const int obj_offset = BasicObjectLock::obj_offset_in_bytes();
+    const int lock_offset = BasicObjectLock::lock_offset_in_bytes ();
+    const int mark_offset = lock_offset +
+                            BasicLock::displaced_header_offset_in_bytes();
+
+    Label slow_case;
+
+    // Load object pointer into obj_reg %c_rarg3
+    ldr(obj_reg, Address(lock_reg, obj_offset));
+
+    if (UseBiasedLocking) {
+      biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch2, false, done, &slow_case);
+    }
+
+    // Load (object->mark() | 1) into swap_reg
+    ldr(rscratch1, Address(obj_reg, 0));
+    orr(swap_reg, rscratch1, 1);
+
+    // Save (object->mark() | 1) into BasicLock's displaced header
+    str(swap_reg, Address(lock_reg, mark_offset));
+
+    assert(lock_offset == 0,
+           "displached header must be first word in BasicObjectLock");
+
+    Label fail;
+    if (PrintBiasedLockingStatistics) {
+      Label fast;
+      cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, fast, &fail);
+      bind(fast);
+      atomic_inc(Address((address)BiasedLocking::fast_path_entry_count_addr()),
+                  rscratch2, rscratch1);
+      b(done);
+      bind(fail);
+    } else {
+      cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL);
+    }
+
+    // Test if the oopMark is an obvious stack pointer, i.e.,
+    //  1) (mark & 7) == 0, and
+    //  2) rsp <= mark < mark + os::pagesize()
+    //
+    // These 3 tests can be done by evaluating the following
+    // expression: ((mark - rsp) & (7 - os::vm_page_size())),