All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
@ 2013-09-11 12:54 Claudio Fontana
  2013-09-11 12:59 ` [Qemu-devel] [RFC 1/4] configure: add c++ compiler support Claudio Fontana
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Claudio Fontana @ 2013-09-11 12:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell


This is the aarch64 libvixl support patchset in the current state.
It provides (limited) support for disassembly output on aarch64.
Only host disassembly is enabled, since target for aarch64 is not in yet.

An external objdump solution as exemplified before by R.H. seems preferable
to me, even if it means giving up the monitor support.
I'd rather have correct output from -d.
The run time need for debugging assembly is already fulfilled by gdb better
than the monitor.

libvixl does not support many opcodes right now, is C++, and it is documented
as working only for a 64bit host with a LP64 memory model.

Claudio Fontana (4):
  configure: add c++ compiler support
  rules.mak: support C++ compiling and linking
  disas: add libvixl source code for aarch64
  disas: implement host disassembly output for aarch64

 configure                                    |   21 +
 disas.c                                      |    2 +
 disas/Makefile.objs                          |    7 +
 disas/aarch64-cxx.cc                         |   53 +
 disas/aarch64.c                              |   45 +
 disas/libvixl/LICENCE                        |   30 +
 disas/libvixl/Makefile.objs                  |    6 +
 disas/libvixl/README.md                      |  128 ++
 disas/libvixl/doc/changelog.md               |   12 +
 disas/libvixl/doc/supported-instructions.md  | 1133 ++++++++++++++
 disas/libvixl/src/a64/assembler-a64.cc       | 2172 ++++++++++++++++++++++++++
 disas/libvixl/src/a64/assembler-a64.h        | 1784 +++++++++++++++++++++
 disas/libvixl/src/a64/constants-a64.h        | 1104 +++++++++++++
 disas/libvixl/src/a64/cpu-a64.cc             |  148 ++
 disas/libvixl/src/a64/cpu-a64.h              |   56 +
 disas/libvixl/src/a64/debugger-a64.cc        | 1511 ++++++++++++++++++
 disas/libvixl/src/a64/debugger-a64.h         |  188 +++
 disas/libvixl/src/a64/decoder-a64.cc         |  712 +++++++++
 disas/libvixl/src/a64/decoder-a64.h          |  198 +++
 disas/libvixl/src/a64/disasm-a64.cc          | 1678 ++++++++++++++++++++
 disas/libvixl/src/a64/disasm-a64.h           |  109 ++
 disas/libvixl/src/a64/instructions-a64.cc    |  238 +++
 disas/libvixl/src/a64/instructions-a64.h     |  344 ++++
 disas/libvixl/src/a64/instrument-a64.cc      |  638 ++++++++
 disas/libvixl/src/a64/instrument-a64.h       |  108 ++
 disas/libvixl/src/a64/macro-assembler-a64.cc | 1108 +++++++++++++
 disas/libvixl/src/a64/macro-assembler-a64.h  | 1175 ++++++++++++++
 disas/libvixl/src/a64/simulator-a64.cc       | 2077 ++++++++++++++++++++++++
 disas/libvixl/src/a64/simulator-a64.h        |  576 +++++++
 disas/libvixl/src/globals.h                  |   66 +
 disas/libvixl/src/platform.h                 |   43 +
 disas/libvixl/src/utils.cc                   |  120 ++
 disas/libvixl/src/utils.h                    |  126 ++
 include/disas/bfd.h                          |    1 +
 rules.mak                                    |   24 +-
 35 files changed, 17737 insertions(+), 4 deletions(-)
 create mode 100644 disas/aarch64-cxx.cc
 create mode 100644 disas/aarch64.c
 create mode 100644 disas/libvixl/LICENCE
 create mode 100644 disas/libvixl/Makefile.objs
 create mode 100644 disas/libvixl/README.md
 create mode 100644 disas/libvixl/doc/changelog.md
 create mode 100644 disas/libvixl/doc/supported-instructions.md
 create mode 100644 disas/libvixl/src/a64/assembler-a64.cc
 create mode 100644 disas/libvixl/src/a64/assembler-a64.h
 create mode 100644 disas/libvixl/src/a64/constants-a64.h
 create mode 100644 disas/libvixl/src/a64/cpu-a64.cc
 create mode 100644 disas/libvixl/src/a64/cpu-a64.h
 create mode 100644 disas/libvixl/src/a64/debugger-a64.cc
 create mode 100644 disas/libvixl/src/a64/debugger-a64.h
 create mode 100644 disas/libvixl/src/a64/decoder-a64.cc
 create mode 100644 disas/libvixl/src/a64/decoder-a64.h
 create mode 100644 disas/libvixl/src/a64/disasm-a64.cc
 create mode 100644 disas/libvixl/src/a64/disasm-a64.h
 create mode 100644 disas/libvixl/src/a64/instructions-a64.cc
 create mode 100644 disas/libvixl/src/a64/instructions-a64.h
 create mode 100644 disas/libvixl/src/a64/instrument-a64.cc
 create mode 100644 disas/libvixl/src/a64/instrument-a64.h
 create mode 100644 disas/libvixl/src/a64/macro-assembler-a64.cc
 create mode 100644 disas/libvixl/src/a64/macro-assembler-a64.h
 create mode 100644 disas/libvixl/src/a64/simulator-a64.cc
 create mode 100644 disas/libvixl/src/a64/simulator-a64.h
 create mode 100644 disas/libvixl/src/globals.h
 create mode 100644 disas/libvixl/src/platform.h
 create mode 100644 disas/libvixl/src/utils.cc
 create mode 100644 disas/libvixl/src/utils.h

-- 
1.8.1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 1/4] configure: add c++ compiler support
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
@ 2013-09-11 12:59 ` Claudio Fontana
  2013-09-11 13:02 ` [Qemu-devel] [RFC 2/4] rules.mak: support C++ compiling and linking Claudio Fontana
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Claudio Fontana @ 2013-09-11 12:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell


This patch is similar to Tomoki Sekiyama's
[PATCH v9 01/10] configure: Support configuring C++ compile,
with the main differences being:

not using "c++" as default compiler, instead do not enable by default
(requires explicit CXX env, --cxx option  or cross-compilation prefix)

separate CFLAGS and CXXFLAGS in the default way.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
---
 configure | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/configure b/configure
index 0a55c20..6b73d99 100755
--- a/configure
+++ b/configure
@@ -252,6 +252,8 @@ for opt do
   ;;
   --cc=*) CC="$optarg"
   ;;
+  --cxx=*) CXX="$optarg"
+  ;;
   --source-path=*) source_path="$optarg"
   ;;
   --cpu=*) cpu="$optarg"
@@ -282,6 +284,12 @@ else
   cc="${CC-${cross_prefix}gcc}"
 fi
 
+if test -z "${CXX}${cross_prefix}"; then
+  cxx=""
+else
+  cxx="${CXX-${cross_prefix}g++}"
+fi
+
 ar="${AR-${cross_prefix}ar}"
 as="${AS-${cross_prefix}as}"
 cpp="${CPP-$cc -E}"
@@ -305,6 +313,7 @@ QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLA
 QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include"
 if test "$debug_info" = "yes"; then
     CFLAGS="-g $CFLAGS"
+    CXXFLAGS="-g $CXXFLAGS"
     LDFLAGS="-g $LDFLAGS"
 fi
 
@@ -622,6 +631,8 @@ for opt do
   ;;
   --host-cc=*) host_cc="$optarg"
   ;;
+  --cxx=*)
+  ;;
   --objcc=*) objcc="$optarg"
   ;;
   --make=*) make="$optarg"
@@ -1023,6 +1034,7 @@ echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
 echo "  --cc=CC                  use C compiler CC [$cc]"
 echo "  --host-cc=CC             use C compiler CC [$host_cc] for code run at"
 echo "                           build time"
+echo "  --cxx=CXX                use C++ compiler CXX [$cxx]"
 echo "  --objcc=OBJCC            use Objective-C compiler OBJCC [$objcc]"
 echo "  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS"
 echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
@@ -3553,6 +3565,7 @@ fi
 echo "Source path       $source_path"
 echo "C compiler        $cc"
 echo "Host C compiler   $host_cc"
+echo "C++ compiler      $cxx"
 echo "Objective-C compiler $objcc"
 echo "CFLAGS            $CFLAGS"
 echo "QEMU_CFLAGS       $QEMU_CFLAGS"
@@ -4140,6 +4153,7 @@ echo "PYTHON=$python" >> $config_host_mak
 echo "CC=$cc" >> $config_host_mak
 echo "CC_I386=$cc_i386" >> $config_host_mak
 echo "HOST_CC=$host_cc" >> $config_host_mak
+echo "CXX=$cxx" >> $config_host_mak
 echo "OBJCC=$objcc" >> $config_host_mak
 echo "AR=$ar" >> $config_host_mak
 echo "AS=$as" >> $config_host_mak
@@ -4149,6 +4163,7 @@ echo "LD=$ld" >> $config_host_mak
 echo "WINDRES=$windres" >> $config_host_mak
 echo "LIBTOOL=$libtool" >> $config_host_mak
 echo "CFLAGS=$CFLAGS" >> $config_host_mak
+echo "CXXFLAGS=$CXXFLAGS" >> $config_host_mak
 echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
 echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
 if test "$sparse" = "yes" ; then
-- 
1.8.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 2/4] rules.mak: support C++ compiling and linking
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
  2013-09-11 12:59 ` [Qemu-devel] [RFC 1/4] configure: add c++ compiler support Claudio Fontana
@ 2013-09-11 13:02 ` Claudio Fontana
  2013-09-11 13:05 ` [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64 Claudio Fontana
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Claudio Fontana @ 2013-09-11 13:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

support compilation of .cc and .cpp files,
and if C++ is enabled always link with C++ in the non-libtool case.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
---
 rules.mak | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/rules.mak b/rules.mak
index 4499745..d2f1b1f 100644
--- a/rules.mak
+++ b/rules.mak
@@ -8,9 +8,14 @@ MAKEFLAGS += -rR
 %.d:
 %.h:
 %.c:
+%.cc:
+%.cpp:
 %.m:
 %.mak:
 
+# Flags for C++ compilation
+QEMU_CXXFLAGS = -D__STDC_LIMIT_MACROS $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls, $(QEMU_CFLAGS))
+
 # Flags for dependency generation
 QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
 
@@ -21,11 +26,21 @@ QEMU_INCLUDES += -I$(<D) -I$(@D)
 	$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  CC    $(TARGET_DIR)$@")
 %.o: %.rc
 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
+%.o: %.cc
+	$(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CXXFLAGS) -c -o $@ $<, "  CXX    $(TARGET_DIR)$@")
+%.o: %.cpp
+	$(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CXXFLAGS) -c -o $@ $<, "  CXX    $(TARGET_DIR)$@")
 
 ifeq ($(LIBTOOL),)
-LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
-       $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
-       $(LIBS),"  LINK  $(TARGET_DIR)$@")
+  ifeq ($(CXX),)
+  LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
+         $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+         $(LIBS),"  LINK  $(TARGET_DIR)$@")
+  else
+  LINK = $(call quiet-command,$(CXX) $(QEMU_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ \
+         $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+         $(LIBS),"  LINK  $(TARGET_DIR)$@")
+  endif
 else
 LIBTOOL += $(if $(V),,--quiet)
 %.lo: %.c
@@ -70,7 +85,8 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh %.rc
+VPATH_SUFFIXES = %.c %.h %.S %.cpp %.cc %.m %.mak %.texi %.sh %.rc
+
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path
-- 
1.8.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
  2013-09-11 12:59 ` [Qemu-devel] [RFC 1/4] configure: add c++ compiler support Claudio Fontana
  2013-09-11 13:02 ` [Qemu-devel] [RFC 2/4] rules.mak: support C++ compiling and linking Claudio Fontana
@ 2013-09-11 13:05 ` Claudio Fontana
  2013-09-11 13:08 ` [Qemu-devel] [RFC 4/4] disas: implement host disassembly output " Claudio Fontana
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Claudio Fontana @ 2013-09-11 13:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

this just adds the libvixl source code verbatim from ARM,
including the source code itself (src/), license and readmes.
Examples, the scons build system etc, are excluded.
Not yet bound to QEMU's build system.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
---
 disas/libvixl/LICENCE                        |   30 +
 disas/libvixl/README.md                      |  128 ++
 disas/libvixl/doc/changelog.md               |   12 +
 disas/libvixl/doc/supported-instructions.md  | 1133 ++++++++++++++
 disas/libvixl/src/a64/assembler-a64.cc       | 2172 ++++++++++++++++++++++++++
 disas/libvixl/src/a64/assembler-a64.h        | 1784 +++++++++++++++++++++
 disas/libvixl/src/a64/constants-a64.h        | 1104 +++++++++++++
 disas/libvixl/src/a64/cpu-a64.cc             |  148 ++
 disas/libvixl/src/a64/cpu-a64.h              |   56 +
 disas/libvixl/src/a64/debugger-a64.cc        | 1511 ++++++++++++++++++
 disas/libvixl/src/a64/debugger-a64.h         |  188 +++
 disas/libvixl/src/a64/decoder-a64.cc         |  712 +++++++++
 disas/libvixl/src/a64/decoder-a64.h          |  198 +++
 disas/libvixl/src/a64/disasm-a64.cc          | 1678 ++++++++++++++++++++
 disas/libvixl/src/a64/disasm-a64.h           |  109 ++
 disas/libvixl/src/a64/instructions-a64.cc    |  238 +++
 disas/libvixl/src/a64/instructions-a64.h     |  344 ++++
 disas/libvixl/src/a64/instrument-a64.cc      |  638 ++++++++
 disas/libvixl/src/a64/instrument-a64.h       |  108 ++
 disas/libvixl/src/a64/macro-assembler-a64.cc | 1108 +++++++++++++
 disas/libvixl/src/a64/macro-assembler-a64.h  | 1175 ++++++++++++++
 disas/libvixl/src/a64/simulator-a64.cc       | 2077 ++++++++++++++++++++++++
 disas/libvixl/src/a64/simulator-a64.h        |  576 +++++++
 disas/libvixl/src/globals.h                  |   66 +
 disas/libvixl/src/platform.h                 |   43 +
 disas/libvixl/src/utils.cc                   |  120 ++
 disas/libvixl/src/utils.h                    |  126 ++
 27 files changed, 17582 insertions(+)
 create mode 100644 disas/libvixl/LICENCE
 create mode 100644 disas/libvixl/README.md
 create mode 100644 disas/libvixl/doc/changelog.md
 create mode 100644 disas/libvixl/doc/supported-instructions.md
 create mode 100644 disas/libvixl/src/a64/assembler-a64.cc
 create mode 100644 disas/libvixl/src/a64/assembler-a64.h
 create mode 100644 disas/libvixl/src/a64/constants-a64.h
 create mode 100644 disas/libvixl/src/a64/cpu-a64.cc
 create mode 100644 disas/libvixl/src/a64/cpu-a64.h
 create mode 100644 disas/libvixl/src/a64/debugger-a64.cc
 create mode 100644 disas/libvixl/src/a64/debugger-a64.h
 create mode 100644 disas/libvixl/src/a64/decoder-a64.cc
 create mode 100644 disas/libvixl/src/a64/decoder-a64.h
 create mode 100644 disas/libvixl/src/a64/disasm-a64.cc
 create mode 100644 disas/libvixl/src/a64/disasm-a64.h
 create mode 100644 disas/libvixl/src/a64/instructions-a64.cc
 create mode 100644 disas/libvixl/src/a64/instructions-a64.h
 create mode 100644 disas/libvixl/src/a64/instrument-a64.cc
 create mode 100644 disas/libvixl/src/a64/instrument-a64.h
 create mode 100644 disas/libvixl/src/a64/macro-assembler-a64.cc
 create mode 100644 disas/libvixl/src/a64/macro-assembler-a64.h
 create mode 100644 disas/libvixl/src/a64/simulator-a64.cc
 create mode 100644 disas/libvixl/src/a64/simulator-a64.h
 create mode 100644 disas/libvixl/src/globals.h
 create mode 100644 disas/libvixl/src/platform.h
 create mode 100644 disas/libvixl/src/utils.cc
 create mode 100644 disas/libvixl/src/utils.h

diff --git a/disas/libvixl/LICENCE b/disas/libvixl/LICENCE
new file mode 100644
index 0000000..b7e160a
--- /dev/null
+++ b/disas/libvixl/LICENCE
@@ -0,0 +1,30 @@
+LICENCE
+=======
+
+The software in this repository is covered by the following licence.
+
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/disas/libvixl/README.md b/disas/libvixl/README.md
new file mode 100644
index 0000000..e3c3a0a
--- /dev/null
+++ b/disas/libvixl/README.md
@@ -0,0 +1,128 @@
+VIXL: AArch64 Runtime Code Generation Library Version 1.1
+=========================================================
+
+Contents:
+
+ * Requirements
+ * Overview
+ * Known limitations
+ * Usage
+
+
+Requirements
+============
+
+To build VIXL the following software is required:
+
+ 1. Python 2.7
+ 2. SCons 2.0
+ 3. GCC 4.4
+
+A 64-bit host machine is required, implementing an LP64 data model. VIXL has
+only been tested using GCC on Ubuntu systems.
+
+To run the linter stage of the tests, the following software is also required:
+
+ 1. Git
+ 2. [Google's `cpplint.py`][cpplint]
+
+Refer to the 'Usage' section for details.
+
+
+Overview
+========
+
+VIXL is made of three components.
+
+ 1. A programmatic assembler to generate A64 code at runtime. The assembler
+    abstracts some of the constraints of the A64 ISA, for example most
+    instructions support any immediate.
+ 2. A disassembler which can print any instruction emitted by the assembler.
+ 3. A simulator which can simulate any instruction emitted by the assembler.
+    The simulator allows generated code to be run on another architecture
+    without the need for a full ISA model.
+
+The VIXL git repository can be found [on GitHub][vixl]. Changes from previous
+versions of VIXL can be found in the [Changelog](doc/changelog.md).
+
+
+Known Limitations
+=================
+
+VIXL was developed to target JavaScript engines so a number of features from A64
+were deemed unnecessary:
+
+ * No Advanced SIMD support.
+ * Limited rounding mode support for floating point.
+ * No support for synchronisation instructions.
+ * Limited support for system instructions.
+ * A few miscellaneous integer and floating point instructions are missing.
+
+The VIXL simulator supports only those instructions that the VIXL assembler can
+generate. The `doc` directory contains a
+[list of supported instructions](doc/supported-instructions.md).
+
+
+Usage
+=====
+
+
+Running all Tests
+-----------------
+
+The helper script `tools/presubmit.py` will build and run every test that is
+provided with VIXL, in both release and debug mode. It is a useful script for
+verifying that all of VIXL's dependencies are in place and that VIXL is working
+as it should.
+
+By default, the `tools/presubmit.py` script runs a linter to check that the
+source code conforms with the code style guide, and to detect several common
+errors that the compiler may not warn about. This is most useful for VIXL
+developers. The linter has the following dependencies:
+
+ 1. Git must be installed, and the VIXL project must be in a valid Git
+    repository, such as one produced using `git clone`.
+ 2. `cpplint.py`, [as provided by Google][cpplint], must be available (and
+    executable) on the `PATH`. Only revision 104 has been tested with VIXL.
+
+It is possible to tell `tools/presubmit.py` to skip the linter stage by passing
+`--nolint`. This removes the dependency on `cpplint.py` and Git. The `--nolint`
+option is implied if the VIXL project is a snapshot (with no `.git` directory).
+
+
+Building and Running Specific Tests
+-----------------------------------
+
+The helper script `tools/test.py` will build and run all the tests for the
+assembler and disassembler in release mode. Add `--mode=debug` to build and run
+in debug mode. The tests can be built separately using SCons: `scons
+target=cctest`.
+
+
+Building and Running the Benchmarks
+-----------------------------------
+
+There are two very basic benchmarks provided with VIXL:
+
+ 1. bench\_dataop, emitting adds
+ 2. bench\_branch, emitting branches
+
+To build one benchmark: `scons target=bench_xxx`, then run it as
+`./bench_xxx_sim <number of iterations>`. The benchmarks do not report a
+figure; they should be timed using the `time` command.
+
+
+Getting Started
+---------------
+
+A short introduction to using VIXL can be found [here](doc/getting-started.md).
+Example source code is provided in the `examples` directory. Build this using
+`scons target=examples` from the root directory.
+
+
+
+[cpplint]: https://google-styleguide.googlecode.com/svn-history/r104/trunk/cpplint/cpplint.py
+           "Google's cpplint.py script."
+
+[vixl]: https://github.com/armvixl/vixl
+        "The VIXL repository on GitHub."
diff --git a/disas/libvixl/doc/changelog.md b/disas/libvixl/doc/changelog.md
new file mode 100644
index 0000000..8bab932
--- /dev/null
+++ b/disas/libvixl/doc/changelog.md
@@ -0,0 +1,12 @@
+VIXL Change Log
+===============
+
+* 1.1
+    + Improved robustness of instruction decoder and disassembler.
+    + Added support for double-to-float conversions using `fcvt`.
+    + Added support for more fixed-point to floating-point conversions (`ucvtf`
+      and `scvtf`).
+    + Added instruction statistics collection class `instrument-a64.cc`.
+
+* 1.0
+    + Initial release.
diff --git a/disas/libvixl/doc/supported-instructions.md b/disas/libvixl/doc/supported-instructions.md
new file mode 100644
index 0000000..90d63ec
--- /dev/null
+++ b/disas/libvixl/doc/supported-instructions.md
@@ -0,0 +1,1133 @@
+VIXL Supported Instruction List
+===============================
+
+This is a list of the AArch64 instructions supported by the VIXL assembler,
+disassembler and simulator. The simulator may not support all floating point
+operations to the precision required by AArch64 - please check the simulator
+source code for details.
+
+AArch64 integer instructions
+----------------------------
+
+### adc ###
+
+Add with carry bit.
+
+    void adc(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### add ###
+
+Add.
+
+    void add(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### adr ###
+
+Calculate the address of a PC offset.
+
+    void adr(const Register& rd, int imm21)
+
+
+### adr ###
+
+Calculate the address of a label.
+
+    void adr(const Register& rd, Label* label)
+
+
+### asr ###
+
+Arithmetic shift right.
+
+    inline void asr(const Register& rd, const Register& rn, unsigned shift)
+
+
+### asrv ###
+
+Arithmetic shift right by variable.
+
+    void asrv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### b ###
+
+Branch to PC offset.
+
+    void b(int imm26, Condition cond = al)
+
+
+### b ###
+
+Branch to label.
+
+    void b(Label* label, Condition cond = al)
+
+
+### bfi ###
+
+Bitfield insert.
+
+    inline void bfi(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width)
+
+
+### bfm ###
+
+Bitfield move.
+
+    void bfm(const Register& rd,
+             const Register& rn,
+             unsigned immr,
+             unsigned imms)
+
+
+### bfxil ###
+
+Bitfield extract and insert low.
+
+    inline void bfxil(const Register& rd,
+                      const Register& rn,
+                      unsigned lsb,
+                      unsigned width)
+
+
+### bic ###
+
+Bit clear (A & ~B).
+
+    void bic(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### bl ###
+
+Branch with link to PC offset.
+
+    void bl(int imm26)
+
+
+### bl ###
+
+Branch with link to label.
+
+    void bl(Label* label)
+
+
+### blr ###
+
+Branch with link to register.
+
+    void blr(const Register& xn)
+
+
+### br ###
+
+Branch to register.
+
+    void br(const Register& xn)
+
+
+### brk ###
+
+Monitor debug-mode breakpoint.
+
+    void brk(int code)
+
+
+### cbnz ###
+
+Compare and branch to PC offset if not zero.
+
+    void cbnz(const Register& rt, int imm19)
+
+
+### cbnz ###
+
+Compare and branch to label if not zero.
+
+    void cbnz(const Register& rt, Label* label)
+
+
+### cbz ###
+
+Compare and branch to PC offset if zero.
+
+    void cbz(const Register& rt, int imm19)
+
+
+### cbz ###
+
+Compare and branch to label if zero.
+
+    void cbz(const Register& rt, Label* label)
+
+
+### ccmn ###
+
+Conditional compare negative.
+
+    void ccmn(const Register& rn,
+              const Operand& operand,
+              StatusFlags nzcv,
+              Condition cond)
+
+
+### ccmp ###
+
+Conditional compare.
+
+    void ccmp(const Register& rn,
+              const Operand& operand,
+              StatusFlags nzcv,
+              Condition cond)
+
+
+### cinc ###
+
+Conditional increment: rd = cond ? rn + 1 : rn.
+
+    void cinc(const Register& rd, const Register& rn, Condition cond)
+
+
+### cinv ###
+
+Conditional invert: rd = cond ? ~rn : rn.
+
+    void cinv(const Register& rd, const Register& rn, Condition cond)
+
+
+### cls ###
+
+Count leading sign bits.
+
+    void cls(const Register& rd, const Register& rn)
+
+
+### clz ###
+
+Count leading zeroes.
+
+    void clz(const Register& rd, const Register& rn)
+
+
+### cmn ###
+
+Compare negative.
+
+    void cmn(const Register& rn, const Operand& operand)
+
+
+### cmp ###
+
+Compare.
+
+    void cmp(const Register& rn, const Operand& operand)
+
+
+### cneg ###
+
+Conditional negate: rd = cond ? -rn : rn.
+
+    void cneg(const Register& rd, const Register& rn, Condition cond)
+
+
+### csel ###
+
+Conditional select: rd = cond ? rn : rm.
+
+    void csel(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              Condition cond)
+
+
+### cset ###
+
+Conditional set: rd = cond ? 1 : 0.
+
+    void cset(const Register& rd, Condition cond)
+
+
+### csetm ###
+
+Conditional set mask: rd = cond ? -1 : 0.
+
+    void csetm(const Register& rd, Condition cond)
+
+
+### csinc ###
+
+Conditional select increment: rd = cond ? rn : rm + 1.
+
+    void csinc(const Register& rd,
+               const Register& rn,
+               const Register& rm,
+               Condition cond)
+
+
+### csinv ###
+
+Conditional select inversion: rd = cond ? rn : ~rm.
+
+    void csinv(const Register& rd,
+               const Register& rn,
+               const Register& rm,
+               Condition cond)
+
+
+### csneg ###
+
+Conditional select negation: rd = cond ? rn : -rm.
+
+    void csneg(const Register& rd,
+               const Register& rn,
+               const Register& rm,
+               Condition cond)
+
+
+### eon ###
+
+Bitwise enor/xnor (A ^ ~B).
+
+    void eon(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### eor ###
+
+Bitwise eor/xor (A ^ B).
+
+    void eor(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### extr ###
+
+Extract.
+
+    void extr(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              unsigned lsb)
+
+
+### hint ###
+
+System hint.
+
+    void hint(SystemHint code)
+
+
+### hlt ###
+
+Halting debug-mode breakpoint.
+
+    void hlt(int code)
+
+
+### ldnp ###
+
+Load integer or FP register pair, non-temporal.
+
+    void ldnp(const CPURegister& rt, const CPURegister& rt2,
+              const MemOperand& src)
+
+
+### ldp ###
+
+Load integer or FP register pair.
+
+    void ldp(const CPURegister& rt, const CPURegister& rt2,
+             const MemOperand& src)
+
+
+### ldpsw ###
+
+Load word pair with sign extension.
+
+    void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src)
+
+
+### ldr ###
+
+Load integer or FP register.
+
+    void ldr(const CPURegister& rt, const MemOperand& src)
+
+
+### ldr ###
+
+Load literal to FP register.
+
+    void ldr(const FPRegister& ft, double imm)
+
+
+### ldr ###
+
+Load literal to register.
+
+    void ldr(const Register& rt, uint64_t imm)
+
+
+### ldrb ###
+
+Load byte.
+
+    void ldrb(const Register& rt, const MemOperand& src)
+
+
+### ldrh ###
+
+Load half-word.
+
+    void ldrh(const Register& rt, const MemOperand& src)
+
+
+### ldrsb ###
+
+Load byte with sign extension.
+
+    void ldrsb(const Register& rt, const MemOperand& src)
+
+
+### ldrsh ###
+
+Load half-word with sign extension.
+
+    void ldrsh(const Register& rt, const MemOperand& src)
+
+
+### ldrsw ###
+
+Load word with sign extension.
+
+    void ldrsw(const Register& rt, const MemOperand& src)
+
+
+### lsl ###
+
+Logical shift left.
+
+    inline void lsl(const Register& rd, const Register& rn, unsigned shift)
+
+
+### lslv ###
+
+Logical shift left by variable.
+
+    void lslv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### lsr ###
+
+Logical shift right.
+
+    inline void lsr(const Register& rd, const Register& rn, unsigned shift)
+
+
+### lsrv ###
+
+Logical shift right by variable.
+
+    void lsrv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### madd ###
+
+Multiply and accumulate.
+
+    void madd(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra)
+
+
+### mneg ###
+
+Negated multiply.
+
+    void mneg(const Register& rd, const Register& rn, const Register& rm)
+
+
+### mov ###
+
+Move register to register.
+
+    void mov(const Register& rd, const Register& rn)
+
+
+### movk ###
+
+Move immediate and keep.
+
+    void movk(const Register& rd, uint64_t imm, int shift = -1)
+
+
+### movn ###
+
+Move inverted immediate.
+
+    void movn(const Register& rd, uint64_t imm, int shift = -1)
+
+
+### movz ###
+
+Move immediate.
+
+    void movz(const Register& rd, uint64_t imm, int shift = -1)
+
+
+### mrs ###
+
+Move to register from system register.
+
+    void mrs(const Register& rt, SystemRegister sysreg)
+
+
+### msr ###
+
+Move from register to system register.
+
+    void msr(SystemRegister sysreg, const Register& rt)
+
+
+### msub ###
+
+Multiply and subtract.
+
+    void msub(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra)
+
+
+### mul ###
+
+Multiply.
+
+    void mul(const Register& rd, const Register& rn, const Register& rm)
+
+
+### mvn ###
+
+Move inverted operand to register.
+
+    void mvn(const Register& rd, const Operand& operand)
+
+
+### neg ###
+
+Negate.
+
+    void neg(const Register& rd,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### ngc ###
+
+Negate with carry bit.
+
+    void ngc(const Register& rd,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### nop ###
+
+No-op.
+
+    void nop()
+
+
+### orn ###
+
+Bitwise nor (A | ~B).
+
+    void orn(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### orr ###
+
+Bitwise or (A | B).
+
+    void orr(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### rbit ###
+
+Bit reverse.
+
+    void rbit(const Register& rd, const Register& rn)
+
+
+### ret ###
+
+Branch to register with return hint.
+
+    void ret(const Register& xn = lr)
+
+
+### rev ###
+
+Reverse bytes.
+
+    void rev(const Register& rd, const Register& rn)
+
+
+### rev16 ###
+
+Reverse bytes in 16-bit half words.
+
+    void rev16(const Register& rd, const Register& rn)
+
+
+### rev32 ###
+
+Reverse bytes in 32-bit words.
+
+    void rev32(const Register& rd, const Register& rn)
+
+
+### ror ###
+
+Rotate right.
+
+    inline void ror(const Register& rd, const Register& rs, unsigned shift)
+
+
+### rorv ###
+
+Rotate right by variable.
+
+    void rorv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### sbc ###
+
+Subtract with carry bit.
+
+    void sbc(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### sbfiz ###
+
+Signed bitfield insert with zero at right.
+
+    inline void sbfiz(const Register& rd,
+                      const Register& rn,
+                      unsigned lsb,
+                      unsigned width)
+
+
+### sbfm ###
+
+Signed bitfield move.
+
+    void sbfm(const Register& rd,
+              const Register& rn,
+              unsigned immr,
+              unsigned imms)
+
+
+### sbfx ###
+
+Signed bitfield extract.
+
+    inline void sbfx(const Register& rd,
+                     const Register& rn,
+                     unsigned lsb,
+                     unsigned width)
+
+
+### scvtf ###
+
+Convert signed integer or fixed point to FP.
+
+    void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0)
+
+
+### sdiv ###
+
+Signed integer divide.
+
+    void sdiv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### smaddl ###
+
+Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+
+    void smaddl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### smsubl ###
+
+Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+
+    void smsubl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### smulh ###
+
+Signed multiply high: 64 x 64 -> 64-bit <127:64>.
+
+    void smulh(const Register& xd, const Register& xn, const Register& xm)
+
+
+### smull ###
+
+Signed long multiply: 32 x 32 -> 64-bit.
+
+    void smull(const Register& rd, const Register& rn, const Register& rm)
+
+
+### stnp ###
+
+Store integer or FP register pair, non-temporal.
+
+    void stnp(const CPURegister& rt, const CPURegister& rt2,
+              const MemOperand& dst)
+
+
+### stp ###
+
+Store integer or FP register pair.
+
+    void stp(const CPURegister& rt, const CPURegister& rt2,
+             const MemOperand& dst)
+
+
+### str ###
+
+Store integer or FP register.
+
+    void str(const CPURegister& rt, const MemOperand& dst)
+
+
+### strb ###
+
+Store byte.
+
+    void strb(const Register& rt, const MemOperand& dst)
+
+
+### strh ###
+
+Store half-word.
+
+    void strh(const Register& rt, const MemOperand& dst)
+
+
+### sub ###
+
+Subtract.
+
+    void sub(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### sxtb ###
+
+Signed extend byte.
+
+    inline void sxtb(const Register& rd, const Register& rn)
+
+
+### sxth ###
+
+Signed extend halfword.
+
+    inline void sxth(const Register& rd, const Register& rn)
+
+
+### sxtw ###
+
+Signed extend word.
+
+    inline void sxtw(const Register& rd, const Register& rn)
+
+
+### tbnz ###
+
+Test bit and branch to PC offset if not zero.
+
+    void tbnz(const Register& rt, unsigned bit_pos, int imm14)
+
+
+### tbnz ###
+
+Test bit and branch to label if not zero.
+
+    void tbnz(const Register& rt, unsigned bit_pos, Label* label)
+
+
+### tbz ###
+
+Test bit and branch to PC offset if zero.
+
+    void tbz(const Register& rt, unsigned bit_pos, int imm14)
+
+
+### tbz ###
+
+Test bit and branch to label if zero.
+
+    void tbz(const Register& rt, unsigned bit_pos, Label* label)
+
+
+### tst ###
+
+Bit test and set flags.
+
+    void tst(const Register& rn, const Operand& operand)
+
+
+### ubfiz ###
+
+Unsigned bitfield insert with zero at right.
+
+    inline void ubfiz(const Register& rd,
+                      const Register& rn,
+                      unsigned lsb,
+                      unsigned width)
+
+
+### ubfm ###
+
+Unsigned bitfield move.
+
+    void ubfm(const Register& rd,
+              const Register& rn,
+              unsigned immr,
+              unsigned imms)
+
+
+### ubfx ###
+
+Unsigned bitfield extract.
+
+    inline void ubfx(const Register& rd,
+                     const Register& rn,
+                     unsigned lsb,
+                     unsigned width)
+
+
+### ucvtf ###
+
+Convert unsigned integer or fixed point to FP.
+
+    void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0)
+
+
+### udiv ###
+
+Unsigned integer divide.
+
+    void udiv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### umaddl ###
+
+Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+
+    void umaddl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### umsubl ###
+
+Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+
+    void umsubl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### uxtb ###
+
+Unsigned extend byte.
+
+    inline void uxtb(const Register& rd, const Register& rn)
+
+
+### uxth ###
+
+Unsigned extend halfword.
+
+    inline void uxth(const Register& rd, const Register& rn)
+
+
+### uxtw ###
+
+Unsigned extend word.
+
+    inline void uxtw(const Register& rd, const Register& rn)
+
+
+
+AArch64 floating point instructions
+-----------------------------------
+
+### fabs ###
+
+FP absolute.
+
+    void fabs(const FPRegister& fd, const FPRegister& fn)
+
+
+### fadd ###
+
+FP add.
+
+    void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fccmp ###
+
+FP conditional compare.
+
+    void fccmp(const FPRegister& fn,
+               const FPRegister& fm,
+               StatusFlags nzcv,
+               Condition cond)
+
+
+### fcmp ###
+
+FP compare immediate.
+
+    void fcmp(const FPRegister& fn, double value)
+
+
+### fcmp ###
+
+FP compare registers.
+
+    void fcmp(const FPRegister& fn, const FPRegister& fm)
+
+
+### fcsel ###
+
+FP conditional select.
+
+    void fcsel(const FPRegister& fd,
+               const FPRegister& fn,
+               const FPRegister& fm,
+               Condition cond)
+
+
+### fcvt ###
+
+FP convert single to double precision.
+
+    void fcvt(const FPRegister& fd, const FPRegister& fn)
+
+
+### fcvtms ###
+
+Convert FP to signed integer (round towards -infinity).
+
+    void fcvtms(const Register& rd, const FPRegister& fn)
+
+
+### fcvtmu ###
+
+Convert FP to unsigned integer (round towards -infinity).
+
+    void fcvtmu(const Register& rd, const FPRegister& fn)
+
+
+### fcvtns ###
+
+Convert FP to signed integer (nearest with ties to even).
+
+    void fcvtns(const Register& rd, const FPRegister& fn)
+
+
+### fcvtnu ###
+
+Convert FP to unsigned integer (nearest with ties to even).
+
+    void fcvtnu(const Register& rd, const FPRegister& fn)
+
+
+### fcvtzs ###
+
+Convert FP to signed integer (round towards zero).
+
+    void fcvtzs(const Register& rd, const FPRegister& fn)
+
+
+### fcvtzu ###
+
+Convert FP to unsigned integer (round towards zero).
+
+    void fcvtzu(const Register& rd, const FPRegister& fn)
+
+
+### fdiv ###
+
+FP divide.
+
+    void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fmax ###
+
+FP maximum.
+
+    void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fmin ###
+
+FP minimum.
+
+    void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fmov ###
+
+Move FP register to FP register.
+
+    void fmov(FPRegister fd, FPRegister fn)
+
+
+### fmov ###
+
+Move FP register to register.
+
+    void fmov(Register rd, FPRegister fn)
+
+
+### fmov ###
+
+Move immediate to FP register.
+
+    void fmov(FPRegister fd, double imm)
+
+
+### fmov ###
+
+Move register to FP register.
+
+    void fmov(FPRegister fd, Register rn)
+
+
+### fmsub ###
+
+FP multiply and subtract.
+
+    void fmsub(const FPRegister& fd,
+               const FPRegister& fn,
+               const FPRegister& fm,
+               const FPRegister& fa)
+
+
+### fmul ###
+
+FP multiply.
+
+    void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fneg ###
+
+FP negate.
+
+    void fneg(const FPRegister& fd, const FPRegister& fn)
+
+
+### frintn ###
+
+FP round to integer (nearest with ties to even).
+
+    void frintn(const FPRegister& fd, const FPRegister& fn)
+
+
+### frintz ###
+
+FP round to integer (towards zero).
+
+    void frintz(const FPRegister& fd, const FPRegister& fn)
+
+
+### fsqrt ###
+
+FP square root.
+
+    void fsqrt(const FPRegister& fd, const FPRegister& fn)
+
+
+### fsub ###
+
+FP subtract.
+
+    void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+
+Additional or pseudo instructions
+---------------------------------
+
+### bind ###
+
+Bind a label to the current PC.
+
+    void bind(Label* label)
+
+
+### dc32 ###
+
+Emit 32 bits of data into the instruction stream.
+
+    inline void dc32(uint32_t data)
+
+
+### dc64 ###
+
+Emit 64 bits of data into the instruction stream.
+
+    inline void dc64(uint64_t data)
+
+
+### dci ###
+
+Emit raw instructions into the instruction stream.
+
+    inline void dci(Instr raw_inst)
+
+
+### debug ###
+
+Debug control pseudo instruction, only supported by the debugger.
+
+    void debug(const char* message, uint32_t code, Instr params = BREAK)
+
+
+
diff --git a/disas/libvixl/src/a64/assembler-a64.cc b/disas/libvixl/src/a64/assembler-a64.cc
new file mode 100644
index 0000000..89f7406
--- /dev/null
+++ b/disas/libvixl/src/a64/assembler-a64.cc
@@ -0,0 +1,2172 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#include <cmath>
+#include "a64/assembler-a64.h"
+
+namespace vixl {
+
+// CPURegList utilities.
+CPURegister CPURegList::PopLowestIndex() {
+  if (IsEmpty()) {
+    return NoCPUReg;
+  }
+  int index = CountTrailingZeros(list_, kRegListSizeInBits);
+  ASSERT((1 << index) & list_);
+  Remove(index);
+  return CPURegister(index, size_, type_);
+}
+
+
+CPURegister CPURegList::PopHighestIndex() {
+  ASSERT(IsValid());
+  if (IsEmpty()) {
+    return NoCPUReg;
+  }
+  int index = CountLeadingZeros(list_, kRegListSizeInBits);
+  index = kRegListSizeInBits - 1 - index;
+  ASSERT((1 << index) & list_);
+  Remove(index);
+  return CPURegister(index, size_, type_);
+}
+
+
+bool CPURegList::IsValid() const {
+  if ((type_ == CPURegister::kRegister) ||
+      (type_ == CPURegister::kFPRegister)) {
+    bool is_valid = true;
+    // Try to create a CPURegister for each element in the list.
+    for (int i = 0; i < kRegListSizeInBits; i++) {
+      if (((list_ >> i) & 1) != 0) {
+        is_valid &= CPURegister(i, size_, type_).IsValid();
+      }
+    }
+    return is_valid;
+  } else if (type_ == CPURegister::kNoRegister) {
+    // We can't use IsEmpty here because that asserts IsValid().
+    return list_ == 0;
+  } else {
+    return false;
+  }
+}
+
+
+void CPURegList::RemoveCalleeSaved() {
+  if (type() == CPURegister::kRegister) {
+    Remove(GetCalleeSaved(RegisterSizeInBits()));
+  } else if (type() == CPURegister::kFPRegister) {
+    Remove(GetCalleeSavedFP(RegisterSizeInBits()));
+  } else {
+    ASSERT(type() == CPURegister::kNoRegister);
+    ASSERT(IsEmpty());
+    // The list must already be empty, so do nothing.
+  }
+}
+
+
+CPURegList CPURegList::GetCalleeSaved(unsigned size) {
+  return CPURegList(CPURegister::kRegister, size, 19, 29);
+}
+
+
+CPURegList CPURegList::GetCalleeSavedFP(unsigned size) {
+  return CPURegList(CPURegister::kFPRegister, size, 8, 15);
+}
+
+
+CPURegList CPURegList::GetCallerSaved(unsigned size) {
+  // Registers x0-x18 and lr (x30) are caller-saved.
+  CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18);
+  list.Combine(lr);
+  return list;
+}
+
+
+CPURegList CPURegList::GetCallerSavedFP(unsigned size) {
+  // Registers d0-d7 and d16-d31 are caller-saved.
+  CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7);
+  list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31));
+  return list;
+}
+
+
+const CPURegList kCalleeSaved = CPURegList::GetCalleeSaved();
+const CPURegList kCalleeSavedFP = CPURegList::GetCalleeSavedFP();
+const CPURegList kCallerSaved = CPURegList::GetCallerSaved();
+const CPURegList kCallerSavedFP = CPURegList::GetCallerSavedFP();
+
+
+// Registers.
+#define WREG(n) w##n,
+const Register Register::wregisters[] = {
+REGISTER_CODE_LIST(WREG)
+};
+#undef WREG
+
+#define XREG(n) x##n,
+const Register Register::xregisters[] = {
+REGISTER_CODE_LIST(XREG)
+};
+#undef XREG
+
+#define SREG(n) s##n,
+const FPRegister FPRegister::sregisters[] = {
+REGISTER_CODE_LIST(SREG)
+};
+#undef SREG
+
+#define DREG(n) d##n,
+const FPRegister FPRegister::dregisters[] = {
+REGISTER_CODE_LIST(DREG)
+};
+#undef DREG
+
+
+const Register& Register::WRegFromCode(unsigned code) {
+  // This function returns the zero register when code = 31. The stack pointer
+  // can not be returned.
+  ASSERT(code < kNumberOfRegisters);
+  return wregisters[code];
+}
+
+
+const Register& Register::XRegFromCode(unsigned code) {
+  // This function returns the zero register when code = 31. The stack pointer
+  // can not be returned.
+  ASSERT(code < kNumberOfRegisters);
+  return xregisters[code];
+}
+
+
+const FPRegister& FPRegister::SRegFromCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return sregisters[code];
+}
+
+
+const FPRegister& FPRegister::DRegFromCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return dregisters[code];
+}
+
+
+const Register& CPURegister::W() const {
+  ASSERT(IsValidRegister());
+  ASSERT(Is64Bits());
+  return Register::WRegFromCode(code_);
+}
+
+
+const Register& CPURegister::X() const {
+  ASSERT(IsValidRegister());
+  ASSERT(Is32Bits());
+  return Register::XRegFromCode(code_);
+}
+
+
+const FPRegister& CPURegister::S() const {
+  ASSERT(IsValidFPRegister());
+  ASSERT(Is64Bits());
+  return FPRegister::SRegFromCode(code_);
+}
+
+
+const FPRegister& CPURegister::D() const {
+  ASSERT(IsValidFPRegister());
+  ASSERT(Is32Bits());
+  return FPRegister::DRegFromCode(code_);
+}
+
+
+// Operand.
+Operand::Operand(int64_t immediate)
+    : immediate_(immediate),
+      reg_(NoReg),
+      shift_(NO_SHIFT),
+      extend_(NO_EXTEND),
+      shift_amount_(0) {}
+
+
+Operand::Operand(Register reg, Shift shift, unsigned shift_amount)
+    : reg_(reg),
+      shift_(shift),
+      extend_(NO_EXTEND),
+      shift_amount_(shift_amount) {
+  ASSERT(reg.Is64Bits() || (shift_amount < kWRegSize));
+  ASSERT(reg.Is32Bits() || (shift_amount < kXRegSize));
+  ASSERT(!reg.IsSP());
+}
+
+
+Operand::Operand(Register reg, Extend extend, unsigned shift_amount)
+    : reg_(reg),
+      shift_(NO_SHIFT),
+      extend_(extend),
+      shift_amount_(shift_amount) {
+  ASSERT(reg.IsValid());
+  ASSERT(shift_amount <= 4);
+  ASSERT(!reg.IsSP());
+}
+
+
+bool Operand::IsImmediate() const {
+  return reg_.Is(NoReg);
+}
+
+
+bool Operand::IsShiftedRegister() const {
+  return reg_.IsValid() && (shift_ != NO_SHIFT);
+}
+
+
+bool Operand::IsExtendedRegister() const {
+  return reg_.IsValid() && (extend_ != NO_EXTEND);
+}
+
+
+Operand Operand::ToExtendedRegister() const {
+  ASSERT(IsShiftedRegister());
+  ASSERT((shift_ == LSL) && (shift_amount_ <= 4));
+  return Operand(reg_, reg_.Is64Bits() ? UXTX : UXTW, shift_amount_);
+}
+
+
+// MemOperand
+MemOperand::MemOperand(Register base, ptrdiff_t offset, AddrMode addrmode)
+  : base_(base), regoffset_(NoReg), offset_(offset), addrmode_(addrmode) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+}
+
+
+MemOperand::MemOperand(Register base,
+                       Register regoffset,
+                       Extend extend,
+                       unsigned shift_amount)
+  : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset),
+    shift_(NO_SHIFT), extend_(extend), shift_amount_(shift_amount) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+  ASSERT(!regoffset.IsSP());
+  ASSERT((extend == UXTW) || (extend == SXTW) || (extend == SXTX));
+}
+
+
+MemOperand::MemOperand(Register base,
+                       Register regoffset,
+                       Shift shift,
+                       unsigned shift_amount)
+  : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset),
+    shift_(shift), extend_(NO_EXTEND), shift_amount_(shift_amount) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+  ASSERT(!regoffset.IsSP());
+  ASSERT(shift == LSL);
+}
+
+
+MemOperand::MemOperand(Register base, const Operand& offset, AddrMode addrmode)
+  : base_(base), regoffset_(NoReg), addrmode_(addrmode) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+
+  if (offset.IsImmediate()) {
+    offset_ = offset.immediate();
+  } else if (offset.IsShiftedRegister()) {
+    ASSERT(addrmode == Offset);
+
+    regoffset_ = offset.reg();
+    shift_= offset.shift();
+    shift_amount_ = offset.shift_amount();
+
+    extend_ = NO_EXTEND;
+    offset_ = 0;
+
+    // These assertions match those in the shifted-register constructor.
+    ASSERT(!regoffset_.IsSP());
+    ASSERT(shift_ == LSL);
+  } else {
+    ASSERT(offset.IsExtendedRegister());
+    ASSERT(addrmode == Offset);
+
+    regoffset_ = offset.reg();
+    extend_ = offset.extend();
+    shift_amount_ = offset.shift_amount();
+
+    shift_= NO_SHIFT;
+    offset_ = 0;
+
+    // These assertions match those in the extended-register constructor.
+    ASSERT(!regoffset_.IsSP());
+    ASSERT((extend_ == UXTW) || (extend_ == SXTW) || (extend_ == SXTX));
+  }
+}
+
+
+bool MemOperand::IsImmediateOffset() const {
+  return (addrmode_ == Offset) && regoffset_.Is(NoReg);
+}
+
+
+bool MemOperand::IsRegisterOffset() const {
+  return (addrmode_ == Offset) && !regoffset_.Is(NoReg);
+}
+
+
+bool MemOperand::IsPreIndex() const {
+  return addrmode_ == PreIndex;
+}
+
+
+bool MemOperand::IsPostIndex() const {
+  return addrmode_ == PostIndex;
+}
+
+
+// Assembler
+Assembler::Assembler(byte* buffer, unsigned buffer_size)
+    : buffer_size_(buffer_size), literal_pool_monitor_(0) {
+  // Assert that this is an LP64 system.
+  ASSERT(sizeof(int) == sizeof(int32_t));     // NOLINT(runtime/sizeof)
+  ASSERT(sizeof(long) == sizeof(int64_t));    // NOLINT(runtime/int)
+  ASSERT(sizeof(void *) == sizeof(int64_t));  // NOLINT(runtime/sizeof)
+  ASSERT(sizeof(1) == sizeof(int32_t));       // NOLINT(runtime/sizeof)
+  ASSERT(sizeof(1L) == sizeof(int64_t));      // NOLINT(runtime/sizeof)
+
+  buffer_ = reinterpret_cast<Instruction*>(buffer);
+  pc_ = buffer_;
+  Reset();
+}
+
+
+Assembler::~Assembler() {
+  ASSERT(finalized_ || (pc_ == buffer_));
+  ASSERT(literals_.empty());
+}
+
+
+void Assembler::Reset() {
+#ifdef DEBUG
+  ASSERT((pc_ >= buffer_) && (pc_ < buffer_ + buffer_size_));
+  ASSERT(literal_pool_monitor_ == 0);
+  memset(buffer_, 0, pc_ - buffer_);
+  finalized_ = false;
+#endif
+  pc_ = buffer_;
+  literals_.clear();
+  next_literal_pool_check_ = pc_ + kLiteralPoolCheckInterval;
+}
+
+
+void Assembler::FinalizeCode() {
+  EmitLiteralPool();
+#ifdef DEBUG
+  finalized_ = true;
+#endif
+}
+
+
+void Assembler::bind(Label* label) {
+  label->is_bound_ = true;
+  label->target_ = pc_;
+  while (label->IsLinked()) {
+    // Get the address of the following instruction in the chain.
+    Instruction* next_link = label->link_->ImmPCOffsetTarget();
+    // Update the instruction target.
+    label->link_->SetImmPCOffsetTarget(label->target_);
+    // Update the label's link.
+    // If the offset of the branch we just updated was 0 (kEndOfChain) we are
+    // done.
+    label->link_ = (label->link_ != next_link) ? next_link : NULL;
+  }
+}
+
+
+int Assembler::UpdateAndGetByteOffsetTo(Label* label) {
+  int offset;
+  ASSERT(sizeof(*pc_) == 1);
+  if (label->IsBound()) {
+    offset = label->target() - pc_;
+  } else if (label->IsLinked()) {
+    offset = label->link() - pc_;
+  } else {
+    offset = Label::kEndOfChain;
+  }
+  label->set_link(pc_);
+  return offset;
+}
+
+
+// Code generation.
+void Assembler::br(const Register& xn) {
+  ASSERT(xn.Is64Bits());
+  Emit(BR | Rn(xn));
+}
+
+
+void Assembler::blr(const Register& xn) {
+  ASSERT(xn.Is64Bits());
+  Emit(BLR | Rn(xn));
+}
+
+
+void Assembler::ret(const Register& xn) {
+  ASSERT(xn.Is64Bits());
+  Emit(RET | Rn(xn));
+}
+
+
+void Assembler::b(int imm26) {
+  Emit(B | ImmUncondBranch(imm26));
+}
+
+
+void Assembler::b(int imm19, Condition cond) {
+  Emit(B_cond | ImmCondBranch(imm19) | cond);
+}
+
+
+void Assembler::b(Label* label) {
+  b(UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::b(Label* label, Condition cond) {
+  b(UpdateAndGetInstructionOffsetTo(label), cond);
+}
+
+
+void Assembler::bl(int imm26) {
+  Emit(BL | ImmUncondBranch(imm26));
+}
+
+
+void Assembler::bl(Label* label) {
+  bl(UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::cbz(const Register& rt,
+                    int imm19) {
+  Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
+}
+
+
+void Assembler::cbz(const Register& rt,
+                    Label* label) {
+  cbz(rt, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::cbnz(const Register& rt,
+                     int imm19) {
+  Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
+}
+
+
+void Assembler::cbnz(const Register& rt,
+                     Label* label) {
+  cbnz(rt, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::tbz(const Register& rt,
+                    unsigned bit_pos,
+                    int imm14) {
+  ASSERT(rt.Is64Bits());
+  Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
+}
+
+
+void Assembler::tbz(const Register& rt,
+                    unsigned bit_pos,
+                    Label* label) {
+  tbz(rt, bit_pos, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::tbnz(const Register& rt,
+                     unsigned bit_pos,
+                     int imm14) {
+  ASSERT(rt.Is64Bits());
+  Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
+}
+
+
+void Assembler::tbnz(const Register& rt,
+                     unsigned bit_pos,
+                     Label* label) {
+  tbnz(rt, bit_pos, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::adr(const Register& rd, int imm21) {
+  ASSERT(rd.Is64Bits());
+  Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd));
+}
+
+
+void Assembler::adr(const Register& rd, Label* label) {
+  adr(rd, UpdateAndGetByteOffsetTo(label));
+}
+
+
+void Assembler::add(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSub(rd, rn, operand, S, ADD);
+}
+
+
+void Assembler::cmn(const Register& rn,
+                    const Operand& operand) {
+  Register zr = AppropriateZeroRegFor(rn);
+  add(zr, rn, operand, SetFlags);
+}
+
+
+void Assembler::sub(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSub(rd, rn, operand, S, SUB);
+}
+
+
+void Assembler::cmp(const Register& rn, const Operand& operand) {
+  Register zr = AppropriateZeroRegFor(rn);
+  sub(zr, rn, operand, SetFlags);
+}
+
+
+void Assembler::neg(const Register& rd, const Operand& operand, FlagsUpdate S) {
+  Register zr = AppropriateZeroRegFor(rd);
+  sub(rd, zr, operand, S);
+}
+
+
+void Assembler::adc(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSubWithCarry(rd, rn, operand, S, ADC);
+}
+
+
+void Assembler::sbc(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSubWithCarry(rd, rn, operand, S, SBC);
+}
+
+
+void Assembler::ngc(const Register& rd, const Operand& operand, FlagsUpdate S) {
+  Register zr = AppropriateZeroRegFor(rd);
+  sbc(rd, zr, operand, S);
+}
+
+
+// Logical instructions.
+void Assembler::and_(const Register& rd,
+                     const Register& rn,
+                     const Operand& operand,
+                     FlagsUpdate S) {
+  Logical(rd, rn, operand, (S == SetFlags) ? ANDS : AND);
+}
+
+
+void Assembler::tst(const Register& rn,
+                    const Operand& operand) {
+  and_(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void Assembler::bic(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  Logical(rd, rn, operand, (S == SetFlags) ? BICS : BIC);
+}
+
+
+void Assembler::orr(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, ORR);
+}
+
+
+void Assembler::orn(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, ORN);
+}
+
+
+void Assembler::eor(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, EOR);
+}
+
+
+void Assembler::eon(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, EON);
+}
+
+
+void Assembler::lslv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::lsrv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::asrv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::rorv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+// Bitfield operations.
+void Assembler::bfm(const Register& rd,
+                     const Register& rn,
+                     unsigned immr,
+                     unsigned imms) {
+  ASSERT(rd.size() == rn.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | BFM | N |
+       ImmR(immr, rd.size()) | ImmS(imms, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::sbfm(const Register& rd,
+                     const Register& rn,
+                     unsigned immr,
+                     unsigned imms) {
+  ASSERT(rd.size() == rn.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | SBFM | N |
+       ImmR(immr, rd.size()) | ImmS(imms, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::ubfm(const Register& rd,
+                     const Register& rn,
+                     unsigned immr,
+                     unsigned imms) {
+  ASSERT(rd.size() == rn.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | UBFM | N |
+       ImmR(immr, rd.size()) | ImmS(imms, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::extr(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     unsigned lsb) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | EXTR | N | Rm(rm) | ImmS(lsb, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::csel(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSEL);
+}
+
+
+void Assembler::csinc(const Register& rd,
+                      const Register& rn,
+                      const Register& rm,
+                      Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSINC);
+}
+
+
+void Assembler::csinv(const Register& rd,
+                      const Register& rn,
+                      const Register& rm,
+                      Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSINV);
+}
+
+
+void Assembler::csneg(const Register& rd,
+                      const Register& rn,
+                      const Register& rm,
+                      Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSNEG);
+}
+
+
+void Assembler::cset(const Register &rd, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  Register zr = AppropriateZeroRegFor(rd);
+  csinc(rd, zr, zr, InvertCondition(cond));
+}
+
+
+void Assembler::csetm(const Register &rd, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  Register zr = AppropriateZeroRegFor(rd);
+  csinv(rd, zr, zr, InvertCondition(cond));
+}
+
+
+void Assembler::cinc(const Register &rd, const Register &rn, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  csinc(rd, rn, rn, InvertCondition(cond));
+}
+
+
+void Assembler::cinv(const Register &rd, const Register &rn, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  csinv(rd, rn, rn, InvertCondition(cond));
+}
+
+
+void Assembler::cneg(const Register &rd, const Register &rn, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  csneg(rd, rn, rn, InvertCondition(cond));
+}
+
+
+void Assembler::ConditionalSelect(const Register& rd,
+                                  const Register& rn,
+                                  const Register& rm,
+                                  Condition cond,
+                                  ConditionalSelectOp op) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::ccmn(const Register& rn,
+                     const Operand& operand,
+                     StatusFlags nzcv,
+                     Condition cond) {
+  ConditionalCompare(rn, operand, nzcv, cond, CCMN);
+}
+
+
+void Assembler::ccmp(const Register& rn,
+                     const Operand& operand,
+                     StatusFlags nzcv,
+                     Condition cond) {
+  ConditionalCompare(rn, operand, nzcv, cond, CCMP);
+}
+
+
+void Assembler::DataProcessing3Source(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     const Register& ra,
+                     DataProcessing3SourceOp op) {
+  Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::mul(const Register& rd,
+                    const Register& rn,
+                    const Register& rm) {
+  ASSERT(AreSameSizeAndType(rd, rn, rm));
+  DataProcessing3Source(rd, rn, rm, AppropriateZeroRegFor(rd), MADD);
+}
+
+
+void Assembler::madd(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     const Register& ra) {
+  DataProcessing3Source(rd, rn, rm, ra, MADD);
+}
+
+
+void Assembler::mneg(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(AreSameSizeAndType(rd, rn, rm));
+  DataProcessing3Source(rd, rn, rm, AppropriateZeroRegFor(rd), MSUB);
+}
+
+
+void Assembler::msub(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     const Register& ra) {
+  DataProcessing3Source(rd, rn, rm, ra, MSUB);
+}
+
+
+void Assembler::umaddl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, UMADDL_x);
+}
+
+
+void Assembler::smaddl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, SMADDL_x);
+}
+
+
+void Assembler::umsubl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x);
+}
+
+
+void Assembler::smsubl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x);
+}
+
+
+void Assembler::smull(const Register& rd,
+                      const Register& rn,
+                      const Register& rm) {
+  ASSERT(rd.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x);
+}
+
+
+void Assembler::sdiv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::smulh(const Register& xd,
+                      const Register& xn,
+                      const Register& xm) {
+  ASSERT(xd.Is64Bits() && xn.Is64Bits() && xm.Is64Bits());
+  DataProcessing3Source(xd, xn, xm, xzr, SMULH_x);
+}
+
+void Assembler::udiv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::rbit(const Register& rd,
+                     const Register& rn) {
+  DataProcessing1Source(rd, rn, RBIT);
+}
+
+
+void Assembler::rev16(const Register& rd,
+                      const Register& rn) {
+  DataProcessing1Source(rd, rn, REV16);
+}
+
+
+void Assembler::rev32(const Register& rd,
+                      const Register& rn) {
+  ASSERT(rd.Is64Bits());
+  DataProcessing1Source(rd, rn, REV);
+}
+
+
+void Assembler::rev(const Register& rd,
+                    const Register& rn) {
+  DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w);
+}
+
+
+void Assembler::clz(const Register& rd,
+                    const Register& rn) {
+  DataProcessing1Source(rd, rn, CLZ);
+}
+
+
+void Assembler::cls(const Register& rd,
+                    const Register& rn) {
+  DataProcessing1Source(rd, rn, CLS);
+}
+
+
+void Assembler::ldp(const CPURegister& rt,
+                    const CPURegister& rt2,
+                    const MemOperand& src) {
+  LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2));
+}
+
+
+void Assembler::stp(const CPURegister& rt,
+                    const CPURegister& rt2,
+                    const MemOperand& dst) {
+  LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2));
+}
+
+
+void Assembler::ldpsw(const Register& rt,
+                      const Register& rt2,
+                      const MemOperand& src) {
+  ASSERT(rt.Is64Bits());
+  LoadStorePair(rt, rt2, src, LDPSW_x);
+}
+
+
+void Assembler::LoadStorePair(const CPURegister& rt,
+                              const CPURegister& rt2,
+                              const MemOperand& addr,
+                              LoadStorePairOp op) {
+  // 'rt' and 'rt2' can only be aliased for stores.
+  ASSERT(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2));
+  ASSERT(AreSameSizeAndType(rt, rt2));
+
+  Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
+                ImmLSPair(addr.offset(), CalcLSPairDataSize(op));
+
+  Instr addrmodeop;
+  if (addr.IsImmediateOffset()) {
+    addrmodeop = LoadStorePairOffsetFixed;
+  } else {
+    ASSERT(addr.offset() != 0);
+    if (addr.IsPreIndex()) {
+      addrmodeop = LoadStorePairPreIndexFixed;
+    } else {
+      ASSERT(addr.IsPostIndex());
+      addrmodeop = LoadStorePairPostIndexFixed;
+    }
+  }
+  Emit(addrmodeop | memop);
+}
+
+
+void Assembler::ldnp(const CPURegister& rt,
+                     const CPURegister& rt2,
+                     const MemOperand& src) {
+  LoadStorePairNonTemporal(rt, rt2, src,
+                           LoadPairNonTemporalOpFor(rt, rt2));
+}
+
+
+void Assembler::stnp(const CPURegister& rt,
+                     const CPURegister& rt2,
+                     const MemOperand& dst) {
+  LoadStorePairNonTemporal(rt, rt2, dst,
+                           StorePairNonTemporalOpFor(rt, rt2));
+}
+
+
+void Assembler::LoadStorePairNonTemporal(const CPURegister& rt,
+                                         const CPURegister& rt2,
+                                         const MemOperand& addr,
+                                         LoadStorePairNonTemporalOp op) {
+  ASSERT(!rt.Is(rt2));
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  ASSERT(addr.IsImmediateOffset());
+
+  LSDataSize size = CalcLSPairDataSize(
+    static_cast<LoadStorePairOp>(op & LoadStorePairMask));
+  Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
+       ImmLSPair(addr.offset(), size));
+}
+
+
+// Memory instructions.
+void Assembler::ldrb(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, LDRB_w);
+}
+
+
+void Assembler::strb(const Register& rt, const MemOperand& dst) {
+  LoadStore(rt, dst, STRB_w);
+}
+
+
+void Assembler::ldrsb(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w);
+}
+
+
+void Assembler::ldrh(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, LDRH_w);
+}
+
+
+void Assembler::strh(const Register& rt, const MemOperand& dst) {
+  LoadStore(rt, dst, STRH_w);
+}
+
+
+void Assembler::ldrsh(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w);
+}
+
+
+void Assembler::ldr(const CPURegister& rt, const MemOperand& src) {
+  LoadStore(rt, src, LoadOpFor(rt));
+}
+
+
+void Assembler::str(const CPURegister& rt, const MemOperand& src) {
+  LoadStore(rt, src, StoreOpFor(rt));
+}
+
+
+void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
+  ASSERT(rt.Is64Bits());
+  LoadStore(rt, src, LDRSW_x);
+}
+
+
+void Assembler::ldr(const Register& rt, uint64_t imm) {
+  LoadLiteral(rt, imm, rt.Is64Bits() ? LDR_x_lit : LDR_w_lit);
+}
+
+
+void Assembler::ldr(const FPRegister& ft, double imm) {
+  uint64_t rawbits = 0;
+  LoadLiteralOp op;
+
+  if (ft.Is64Bits()) {
+    rawbits = double_to_rawbits(imm);
+    op = LDR_d_lit;
+  } else {
+    ASSERT(ft.Is32Bits());
+    float float_imm = static_cast<float>(imm);
+    rawbits = float_to_rawbits(float_imm);
+    op = LDR_s_lit;
+  }
+
+  LoadLiteral(ft, rawbits, op);
+}
+
+
+void Assembler::mov(const Register& rd, const Register& rm) {
+  // Moves involving the stack pointer are encoded as add immediate with
+  // second operand of zero. Otherwise, orr with first operand zr is
+  // used.
+  if (rd.IsSP() || rm.IsSP()) {
+    add(rd, rm, 0);
+  } else {
+    orr(rd, AppropriateZeroRegFor(rd), rm);
+  }
+}
+
+
+void Assembler::mvn(const Register& rd, const Operand& operand) {
+  orn(rd, AppropriateZeroRegFor(rd), operand);
+}
+
+
+void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
+  ASSERT(rt.Is64Bits());
+  Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
+}
+
+
+void Assembler::msr(SystemRegister sysreg, const Register& rt) {
+  ASSERT(rt.Is64Bits());
+  Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
+}
+
+
+void Assembler::hint(SystemHint code) {
+  Emit(HINT | ImmHint(code) | Rt(xzr));
+}
+
+
+void Assembler::fmov(FPRegister fd, double imm) {
+  if (fd.Is64Bits() && IsImmFP64(imm)) {
+    Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
+  } else if (fd.Is32Bits() && IsImmFP32(imm)) {
+    Emit(FMOV_s_imm | Rd(fd) | ImmFP32(static_cast<float>(imm)));
+  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
+    Register zr = AppropriateZeroRegFor(fd);
+    fmov(fd, zr);
+  } else {
+    ldr(fd, imm);
+  }
+}
+
+
+void Assembler::fmov(Register rd, FPRegister fn) {
+  ASSERT(rd.size() == fn.size());
+  FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd;
+  Emit(op | Rd(rd) | Rn(fn));
+}
+
+
+void Assembler::fmov(FPRegister fd, Register rn) {
+  ASSERT(fd.size() == rn.size());
+  FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx;
+  Emit(op | Rd(fd) | Rn(rn));
+}
+
+
+void Assembler::fmov(FPRegister fd, FPRegister fn) {
+  ASSERT(fd.size() == fn.size());
+  Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn));
+}
+
+
+void Assembler::fadd(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FADD);
+}
+
+
+void Assembler::fsub(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FSUB);
+}
+
+
+void Assembler::fmul(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FMUL);
+}
+
+
+void Assembler::fmsub(const FPRegister& fd,
+                      const FPRegister& fn,
+                      const FPRegister& fm,
+                      const FPRegister& fa) {
+  FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d);
+}
+
+
+void Assembler::fdiv(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FDIV);
+}
+
+
+void Assembler::fmax(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FMAX);
+}
+
+
+void Assembler::fmin(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FMIN);
+}
+
+
+void Assembler::fabs(const FPRegister& fd,
+                     const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FABS);
+}
+
+
+void Assembler::fneg(const FPRegister& fd,
+                     const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FNEG);
+}
+
+
+void Assembler::fsqrt(const FPRegister& fd,
+                      const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FSQRT);
+}
+
+
+void Assembler::frintn(const FPRegister& fd,
+                       const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FRINTN);
+}
+
+
+void Assembler::frintz(const FPRegister& fd,
+                       const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FRINTZ);
+}
+
+
+void Assembler::fcmp(const FPRegister& fn,
+                     const FPRegister& fm) {
+  ASSERT(fn.size() == fm.size());
+  Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
+}
+
+
+void Assembler::fcmp(const FPRegister& fn,
+                     double value) {
+  USE(value);
+  // Although the fcmp instruction can strictly only take an immediate value of
+  // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
+  // affect the result of the comparison.
+  ASSERT(value == 0.0);
+  Emit(FPType(fn) | FCMP_zero | Rn(fn));
+}
+
+
+void Assembler::fccmp(const FPRegister& fn,
+                      const FPRegister& fm,
+                      StatusFlags nzcv,
+                      Condition cond) {
+  ASSERT(fn.size() == fm.size());
+  Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
+}
+
+
+void Assembler::fcsel(const FPRegister& fd,
+                      const FPRegister& fn,
+                      const FPRegister& fm,
+                      Condition cond) {
+  ASSERT(fd.size() == fn.size());
+  ASSERT(fd.size() == fm.size());
+  Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
+}
+
+
+void Assembler::FPConvertToInt(const Register& rd,
+                               const FPRegister& fn,
+                               FPIntegerConvertOp op) {
+  Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd));
+}
+
+
+void Assembler::fcvt(const FPRegister& fd,
+                     const FPRegister& fn) {
+  if (fd.Is64Bits()) {
+    // Convert float to double.
+    ASSERT(fn.Is32Bits());
+    FPDataProcessing1Source(fd, fn, FCVT_ds);
+  } else {
+    // Convert double to float.
+    ASSERT(fn.Is64Bits());
+    FPDataProcessing1Source(fd, fn, FCVT_sd);
+  }
+}
+
+
+void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTMU);
+}
+
+
+void Assembler::fcvtms(const Register& rd, const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTMS);
+}
+
+
+void Assembler::fcvtnu(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTNU);
+}
+
+
+void Assembler::fcvtns(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTNS);
+}
+
+
+void Assembler::fcvtzu(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTZU);
+}
+
+
+void Assembler::fcvtzs(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTZS);
+}
+
+
+void Assembler::scvtf(const FPRegister& fd,
+                      const Register& rn,
+                      unsigned fbits) {
+  if (fbits == 0) {
+    Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd));
+  } else {
+    Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
+         Rd(fd));
+  }
+}
+
+
+void Assembler::ucvtf(const FPRegister& fd,
+                      const Register& rn,
+                      unsigned fbits) {
+  if (fbits == 0) {
+    Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
+  } else {
+    Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
+         Rd(fd));
+  }
+}
+
+
+// Note:
+// Below, a difference in case for the same letter indicates a
+// negated bit.
+// If b is 1, then B is 0.
+Instr Assembler::ImmFP32(float imm) {
+  ASSERT(IsImmFP32(imm));
+  // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
+  uint32_t bits = float_to_rawbits(imm);
+  // bit7: a000.0000
+  uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
+  // bit6: 0b00.0000
+  uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
+  // bit5_to_0: 00cd.efgh
+  uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
+
+  return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
+}
+
+
+Instr Assembler::ImmFP64(double imm) {
+  ASSERT(IsImmFP64(imm));
+  // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
+  //       0000.0000.0000.0000.0000.0000.0000.0000
+  uint64_t bits = double_to_rawbits(imm);
+  // bit7: a000.0000
+  uint32_t bit7 = ((bits >> 63) & 0x1) << 7;
+  // bit6: 0b00.0000
+  uint32_t bit6 = ((bits >> 61) & 0x1) << 6;
+  // bit5_to_0: 00cd.efgh
+  uint32_t bit5_to_0 = (bits >> 48) & 0x3f;
+
+  return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
+}
+
+
+// Code generation helpers.
+void Assembler::MoveWide(const Register& rd,
+                         uint64_t imm,
+                         int shift,
+                         MoveWideImmediateOp mov_op) {
+  if (shift >= 0) {
+    // Explicit shift specified.
+    ASSERT((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
+    ASSERT(rd.Is64Bits() || (shift == 0) || (shift == 16));
+    shift /= 16;
+  } else {
+    // Calculate a new immediate and shift combination to encode the immediate
+    // argument.
+    shift = 0;
+    if ((imm & ~0xffffUL) == 0) {
+      // Nothing to do.
+    } else if ((imm & ~(0xffffUL << 16)) == 0) {
+      imm >>= 16;
+      shift = 1;
+    } else if ((imm & ~(0xffffUL << 32)) == 0) {
+      ASSERT(rd.Is64Bits());
+      imm >>= 32;
+      shift = 2;
+    } else if ((imm & ~(0xffffUL << 48)) == 0) {
+      ASSERT(rd.Is64Bits());
+      imm >>= 48;
+      shift = 3;
+    }
+  }
+
+  ASSERT(is_uint16(imm));
+
+  Emit(SF(rd) | MoveWideImmediateFixed | mov_op |
+       Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift));
+}
+
+
+void Assembler::AddSub(const Register& rd,
+                       const Register& rn,
+                       const Operand& operand,
+                       FlagsUpdate S,
+                       AddSubOp op) {
+  ASSERT(rd.size() == rn.size());
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    ASSERT(IsImmAddSub(immediate));
+    Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
+    Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
+         ImmAddSub(immediate) | dest_reg | RnSP(rn));
+  } else if (operand.IsShiftedRegister()) {
+    ASSERT(operand.reg().size() == rd.size());
+    ASSERT(operand.shift() != ROR);
+
+    // For instructions of the form:
+    //   add/sub   wsp, <Wn>, <Wm> [, LSL #0-3 ]
+    //   add/sub   <Wd>, wsp, <Wm> [, LSL #0-3 ]
+    //   add/sub   wsp, wsp, <Wm> [, LSL #0-3 ]
+    //   adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
+    // or their 64-bit register equivalents, convert the operand from shifted to
+    // extended register mode, and emit an add/sub extended instruction.
+    if (rn.IsSP() || rd.IsSP()) {
+      ASSERT(!(rd.IsSP() && (S == SetFlags)));
+      DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
+                               AddSubExtendedFixed | op);
+    } else {
+      DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
+    }
+  } else {
+    ASSERT(operand.IsExtendedRegister());
+    DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
+  }
+}
+
+
+void Assembler::AddSubWithCarry(const Register& rd,
+                                const Register& rn,
+                                const Operand& operand,
+                                FlagsUpdate S,
+                                AddSubWithCarryOp op) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == operand.reg().size());
+  ASSERT(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
+  Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::hlt(int code) {
+  ASSERT(is_uint16(code));
+  Emit(HLT | ImmException(code));
+}
+
+
+void Assembler::brk(int code) {
+  ASSERT(is_uint16(code));
+  Emit(BRK | ImmException(code));
+}
+
+
+void Assembler::Logical(const Register& rd,
+                        const Register& rn,
+                        const Operand& operand,
+                        LogicalOp op) {
+  ASSERT(rd.size() == rn.size());
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    unsigned reg_size = rd.size();
+
+    ASSERT(immediate != 0);
+    ASSERT(immediate != -1);
+    ASSERT(rd.Is64Bits() || is_uint32(immediate));
+
+    // If the operation is NOT, invert the operation and immediate.
+    if ((op & NOT) == NOT) {
+      op = static_cast<LogicalOp>(op & ~NOT);
+      immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
+    }
+
+    unsigned n, imm_s, imm_r;
+    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
+      // Immediate can be encoded in the instruction.
+      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
+    } else {
+      // This case is handled in the macro assembler.
+      UNREACHABLE();
+    }
+  } else {
+    ASSERT(operand.IsShiftedRegister());
+    ASSERT(operand.reg().size() == rd.size());
+    Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
+    DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
+  }
+}
+
+
+void Assembler::LogicalImmediate(const Register& rd,
+                                 const Register& rn,
+                                 unsigned n,
+                                 unsigned imm_s,
+                                 unsigned imm_r,
+                                 LogicalOp op) {
+  unsigned reg_size = rd.size();
+  Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
+  Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
+       ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg |
+       Rn(rn));
+}
+
+
+void Assembler::ConditionalCompare(const Register& rn,
+                                   const Operand& operand,
+                                   StatusFlags nzcv,
+                                   Condition cond,
+                                   ConditionalCompareOp op) {
+  Instr ccmpop;
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    ASSERT(IsImmConditionalCompare(immediate));
+    ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate);
+  } else {
+    ASSERT(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
+    ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg());
+  }
+  Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv));
+}
+
+
+void Assembler::DataProcessing1Source(const Register& rd,
+                                      const Register& rn,
+                                      DataProcessing1SourceOp op) {
+  ASSERT(rd.size() == rn.size());
+  Emit(SF(rn) | op | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::FPDataProcessing1Source(const FPRegister& fd,
+                                        const FPRegister& fn,
+                                        FPDataProcessing1SourceOp op) {
+  Emit(FPType(fn) | op | Rn(fn) | Rd(fd));
+}
+
+
+void Assembler::FPDataProcessing2Source(const FPRegister& fd,
+                                        const FPRegister& fn,
+                                        const FPRegister& fm,
+                                        FPDataProcessing2SourceOp op) {
+  ASSERT(fd.size() == fn.size());
+  ASSERT(fd.size() == fm.size());
+  Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
+}
+
+
+void Assembler::FPDataProcessing3Source(const FPRegister& fd,
+                                        const FPRegister& fn,
+                                        const FPRegister& fm,
+                                        const FPRegister& fa,
+                                        FPDataProcessing3SourceOp op) {
+  ASSERT(AreSameSizeAndType(fd, fn, fm, fa));
+  Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
+}
+
+
+void Assembler::EmitShift(const Register& rd,
+                          const Register& rn,
+                          Shift shift,
+                          unsigned shift_amount) {
+  switch (shift) {
+    case LSL:
+      lsl(rd, rn, shift_amount);
+      break;
+    case LSR:
+      lsr(rd, rn, shift_amount);
+      break;
+    case ASR:
+      asr(rd, rn, shift_amount);
+      break;
+    case ROR:
+      ror(rd, rn, shift_amount);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void Assembler::EmitExtendShift(const Register& rd,
+                                const Register& rn,
+                                Extend extend,
+                                unsigned left_shift) {
+  ASSERT(rd.size() >= rn.size());
+  unsigned reg_size = rd.size();
+  // Use the correct size of register.
+  Register rn_ = Register(rn.code(), rd.size());
+  // Bits extracted are high_bit:0.
+  unsigned high_bit = (8 << (extend & 0x3)) - 1;
+  // Number of bits left in the result that are not introduced by the shift.
+  unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1);
+
+  if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) {
+    switch (extend) {
+      case UXTB:
+      case UXTH:
+      case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break;
+      case SXTB:
+      case SXTH:
+      case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break;
+      case UXTX:
+      case SXTX: {
+        ASSERT(rn.size() == kXRegSize);
+        // Nothing to extend. Just shift.
+        lsl(rd, rn_, left_shift);
+        break;
+      }
+      default: UNREACHABLE();
+    }
+  } else {
+    // No need to extend as the extended bits would be shifted away.
+    lsl(rd, rn_, left_shift);
+  }
+}
+
+
+void Assembler::DataProcShiftedRegister(const Register& rd,
+                                        const Register& rn,
+                                        const Operand& operand,
+                                        FlagsUpdate S,
+                                        Instr op) {
+  ASSERT(operand.IsShiftedRegister());
+  ASSERT(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
+  Emit(SF(rd) | op | Flags(S) |
+       ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) |
+       Rm(operand.reg()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::DataProcExtendedRegister(const Register& rd,
+                                         const Register& rn,
+                                         const Operand& operand,
+                                         FlagsUpdate S,
+                                         Instr op) {
+  Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
+  Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) |
+       ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) |
+       dest_reg | RnSP(rn));
+}
+
+
+bool Assembler::IsImmAddSub(int64_t immediate) {
+  return is_uint12(immediate) ||
+         (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0));
+}
+
+void Assembler::LoadStore(const CPURegister& rt,
+                          const MemOperand& addr,
+                          LoadStoreOp op) {
+  Instr memop = op | Rt(rt) | RnSP(addr.base());
+  ptrdiff_t offset = addr.offset();
+
+  if (addr.IsImmediateOffset()) {
+    LSDataSize size = CalcLSDataSize(op);
+    if (IsImmLSScaled(offset, size)) {
+      // Use the scaled addressing mode.
+      Emit(LoadStoreUnsignedOffsetFixed | memop |
+           ImmLSUnsigned(offset >> size));
+    } else if (IsImmLSUnscaled(offset)) {
+      // Use the unscaled addressing mode.
+      Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
+    } else {
+      // This case is handled in the macro assembler.
+      UNREACHABLE();
+    }
+  } else if (addr.IsRegisterOffset()) {
+    Extend ext = addr.extend();
+    Shift shift = addr.shift();
+    unsigned shift_amount = addr.shift_amount();
+
+    // LSL is encoded in the option field as UXTX.
+    if (shift == LSL) {
+      ext = UXTX;
+    }
+
+    // Shifts are encoded in one bit, indicating a left shift by the memory
+    // access size.
+    ASSERT((shift_amount == 0) ||
+           (shift_amount == static_cast<unsigned>(CalcLSDataSize(op))));
+    Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) |
+         ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0));
+  } else {
+    if (IsImmLSUnscaled(offset)) {
+      if (addr.IsPreIndex()) {
+        Emit(LoadStorePreIndexFixed | memop | ImmLS(offset));
+      } else {
+        ASSERT(addr.IsPostIndex());
+        Emit(LoadStorePostIndexFixed | memop | ImmLS(offset));
+      }
+    } else {
+      // This case is handled in the macro assembler.
+      UNREACHABLE();
+    }
+  }
+}
+
+
+bool Assembler::IsImmLSUnscaled(ptrdiff_t offset) {
+  return is_int9(offset);
+}
+
+
+bool Assembler::IsImmLSScaled(ptrdiff_t offset, LSDataSize size) {
+  bool offset_is_size_multiple = (((offset >> size) << size) == offset);
+  return offset_is_size_multiple && is_uint12(offset >> size);
+}
+
+
+void Assembler::LoadLiteral(const CPURegister& rt,
+                            uint64_t imm,
+                            LoadLiteralOp op) {
+  ASSERT(is_int32(imm) || is_uint32(imm) || (rt.Is64Bits()));
+
+  BlockLiteralPoolScope scope(this);
+  RecordLiteral(imm, rt.SizeInBytes());
+  Emit(op | ImmLLiteral(0) | Rt(rt));
+}
+
+
+// Test if a given value can be encoded in the immediate field of a logical
+// instruction.
+// If it can be encoded, the function returns true, and values pointed to by n,
+// imm_s and imm_r are updated with immediates encoded in the format required
+// by the corresponding fields in the logical instruction.
+// If it can not be encoded, the function returns false, and the values pointed
+// to by n, imm_s and imm_r are undefined.
+bool Assembler::IsImmLogical(uint64_t value,
+                             unsigned width,
+                             unsigned* n,
+                             unsigned* imm_s,
+                             unsigned* imm_r) {
+  ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
+  ASSERT((width == kWRegSize) || (width == kXRegSize));
+
+  // Logical immediates are encoded using parameters n, imm_s and imm_r using
+  // the following table:
+  //
+  //  N   imms    immr    size        S             R
+  //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
+  //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
+  //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
+  //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
+  //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
+  //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
+  // (s bits must not be all set)
+  //
+  // A pattern is constructed of size bits, where the least significant S+1
+  // bits are set. The pattern is rotated right by R, and repeated across a
+  // 32 or 64-bit value, depending on destination register width.
+  //
+  // To test if an arbitrary immediate can be encoded using this scheme, an
+  // iterative algorithm is used.
+  //
+  // TODO: This code does not consider using X/W register overlap to support
+  // 64-bit immediates where the top 32-bits are zero, and the bottom 32-bits
+  // are an encodable logical immediate.
+
+  // 1. If the value has all set or all clear bits, it can't be encoded.
+  if ((value == 0) || (value == 0xffffffffffffffffUL) ||
+      ((width == kWRegSize) && (value == 0xffffffff))) {
+    return false;
+  }
+
+  unsigned lead_zero = CountLeadingZeros(value, width);
+  unsigned lead_one = CountLeadingZeros(~value, width);
+  unsigned trail_zero = CountTrailingZeros(value, width);
+  unsigned trail_one = CountTrailingZeros(~value, width);
+  unsigned set_bits = CountSetBits(value, width);
+
+  // The fixed bits in the immediate s field.
+  // If width == 64 (X reg), start at 0xFFFFFF80.
+  // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit
+  // widths won't be executed.
+  int imm_s_fixed = (width == kXRegSize) ? -128 : -64;
+  int imm_s_mask = 0x3F;
+
+  for (;;) {
+    // 2. If the value is two bits wide, it can be encoded.
+    if (width == 2) {
+      *n = 0;
+      *imm_s = 0x3C;
+      *imm_r = (value & 3) - 1;
+      return true;
+    }
+
+    *n = (width == 64) ? 1 : 0;
+    *imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask);
+    if ((lead_zero + set_bits) == width) {
+      *imm_r = 0;
+    } else {
+      *imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one;
+    }
+
+    // 3. If the sum of leading zeros, trailing zeros and set bits is equal to
+    //    the bit width of the value, it can be encoded.
+    if (lead_zero + trail_zero + set_bits == width) {
+      return true;
+    }
+
+    // 4. If the sum of leading ones, trailing ones and unset bits in the
+    //    value is equal to the bit width of the value, it can be encoded.
+    if (lead_one + trail_one + (width - set_bits) == width) {
+      return true;
+    }
+
+    // 5. If the most-significant half of the bitwise value is equal to the
+    //    least-significant half, return to step 2 using the least-significant
+    //    half of the value.
+    uint64_t mask = (1UL << (width >> 1)) - 1;
+    if ((value & mask) == ((value >> (width >> 1)) & mask)) {
+      width >>= 1;
+      set_bits >>= 1;
+      imm_s_fixed >>= 1;
+      continue;
+    }
+
+    // 6. Otherwise, the value can't be encoded.
+    return false;
+  }
+}
+
+bool Assembler::IsImmConditionalCompare(int64_t immediate) {
+  return is_uint5(immediate);
+}
+
+
+bool Assembler::IsImmFP32(float imm) {
+  // Valid values will have the form:
+  // aBbb.bbbc.defg.h000.0000.0000.0000.0000
+  uint32_t bits = float_to_rawbits(imm);
+  // bits[19..0] are cleared.
+  if ((bits & 0x7ffff) != 0) {
+    return false;
+  }
+
+  // bits[29..25] are all set or all cleared.
+  uint32_t b_pattern = (bits >> 16) & 0x3e00;
+  if (b_pattern != 0 && b_pattern != 0x3e00) {
+    return false;
+  }
+
+  // bit[30] and bit[29] are opposite.
+  if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
+    return false;
+  }
+
+  return true;
+}
+
+
+bool Assembler::IsImmFP64(double imm) {
+  // Valid values will have the form:
+  // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
+  // 0000.0000.0000.0000.0000.0000.0000.0000
+  uint64_t bits = double_to_rawbits(imm);
+  // bits[47..0] are cleared.
+  if ((bits & 0xffffffffffffL) != 0) {
+    return false;
+  }
+
+  // bits[61..54] are all set or all cleared.
+  uint32_t b_pattern = (bits >> 48) & 0x3fc0;
+  if (b_pattern != 0 && b_pattern != 0x3fc0) {
+    return false;
+  }
+
+  // bit[62] and bit[61] are opposite.
+  if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) {
+    return false;
+  }
+
+  return true;
+}
+
+
+LoadStoreOp Assembler::LoadOpFor(const CPURegister& rt) {
+  ASSERT(rt.IsValid());
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDR_x : LDR_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDR_d : LDR_s;
+  }
+}
+
+
+LoadStorePairOp Assembler::LoadPairOpFor(const CPURegister& rt,
+    const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDP_x : LDP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDP_d : LDP_s;
+  }
+}
+
+
+LoadStoreOp Assembler::StoreOpFor(const CPURegister& rt) {
+  ASSERT(rt.IsValid());
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? STR_x : STR_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? STR_d : STR_s;
+  }
+}
+
+
+LoadStorePairOp Assembler::StorePairOpFor(const CPURegister& rt,
+    const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? STP_x : STP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? STP_d : STP_s;
+  }
+}
+
+
+LoadStorePairNonTemporalOp Assembler::LoadPairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDNP_x : LDNP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDNP_d : LDNP_s;
+  }
+}
+
+
+LoadStorePairNonTemporalOp Assembler::StorePairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? STNP_x : STNP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? STNP_d : STNP_s;
+  }
+}
+
+
+void Assembler::RecordLiteral(int64_t imm, unsigned size) {
+  literals_.push_front(new Literal(pc_, imm, size));
+}
+
+
+// Check if a literal pool should be emitted. Currently a literal is emitted
+// when:
+//  * the distance to the first literal load handled by this pool is greater
+//    than the recommended distance and the literal pool can be emitted without
+//    generating a jump over it.
+//  * the distance to the first literal load handled by this pool is greater
+//    than twice the recommended distance.
+// TODO: refine this heuristic using real world data.
+void Assembler::CheckLiteralPool(LiteralPoolEmitOption option) {
+  if (IsLiteralPoolBlocked()) {
+    // Literal pool emission is forbidden, no point in doing further checks.
+    return;
+  }
+
+  if (literals_.empty()) {
+    // No literal pool to emit.
+    next_literal_pool_check_ += kLiteralPoolCheckInterval;
+    return;
+  }
+
+  intptr_t distance = pc_ - literals_.back()->pc_;
+  if ((distance < kRecommendedLiteralPoolRange) ||
+      ((option == JumpRequired) &&
+       (distance < (2 * kRecommendedLiteralPoolRange)))) {
+    // We prefer not to have to jump over the literal pool.
+    next_literal_pool_check_ += kLiteralPoolCheckInterval;
+    return;
+  }
+
+  EmitLiteralPool(option);
+}
+
+
+void Assembler::EmitLiteralPool(LiteralPoolEmitOption option) {
+  // Prevent recursive calls while emitting the literal pool.
+  BlockLiteralPoolScope scope(this);
+
+  Label marker;
+  Label start_of_pool;
+  Label end_of_pool;
+
+  if (option == JumpRequired) {
+    b(&end_of_pool);
+  }
+
+  // Leave space for a literal pool marker. This is populated later, once the
+  // size of the pool is known.
+  bind(&marker);
+  nop();
+
+  // Now populate the literal pool.
+  bind(&start_of_pool);
+  std::list<Literal*>::iterator it;
+  for (it = literals_.begin(); it != literals_.end(); it++) {
+    // Update the load-literal instruction to point to this pool entry.
+    Instruction* load_literal = (*it)->pc_;
+    load_literal->SetImmLLiteral(pc_);
+    // Copy the data into the pool.
+    uint64_t value= (*it)->value_;
+    unsigned size = (*it)->size_;
+    ASSERT((size == kXRegSizeInBytes) || (size == kWRegSizeInBytes));
+    ASSERT((pc_ + size) <= (buffer_ + buffer_size_));
+    memcpy(pc_, &value, size);
+    pc_ += size;
+    delete *it;
+  }
+  literals_.clear();
+  bind(&end_of_pool);
+
+  // The pool size should always be a multiple of four bytes because that is the
+  // scaling applied by the LDR(literal) instruction, even for X-register loads.
+  ASSERT((SizeOfCodeGeneratedSince(&start_of_pool) % 4) == 0);
+  uint64_t pool_size = SizeOfCodeGeneratedSince(&start_of_pool) / 4;
+
+  // Literal pool marker indicating the size in words of the literal pool.
+  // We use a literal load to the zero register, the offset indicating the
+  // size in words. This instruction can encode a large enough offset to span
+  // the entire pool at its maximum size.
+  Instr marker_instruction = LDR_x_lit | ImmLLiteral(pool_size) | Rt(xzr);
+  memcpy(marker.target(), &marker_instruction, kInstructionSize);
+
+  next_literal_pool_check_ = pc_ + kLiteralPoolCheckInterval;
+}
+
+
+// Return the size in bytes, required by the literal pool entries. This does
+// not include any marker or branch over the literal pool itself.
+size_t Assembler::LiteralPoolSize() {
+  size_t size = 0;
+
+  std::list<Literal*>::iterator it;
+  for (it = literals_.begin(); it != literals_.end(); it++) {
+    size += (*it)->size_;
+  }
+
+  return size;
+}
+
+
+bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
+                const CPURegister& reg3, const CPURegister& reg4,
+                const CPURegister& reg5, const CPURegister& reg6,
+                const CPURegister& reg7, const CPURegister& reg8) {
+  int number_of_valid_regs = 0;
+  int number_of_valid_fpregs = 0;
+
+  RegList unique_regs = 0;
+  RegList unique_fpregs = 0;
+
+  const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
+
+  for (unsigned i = 0; i < sizeof(regs) / sizeof(regs[0]); i++) {
+    if (regs[i].IsRegister()) {
+      number_of_valid_regs++;
+      unique_regs |= regs[i].Bit();
+    } else if (regs[i].IsFPRegister()) {
+      number_of_valid_fpregs++;
+      unique_fpregs |= regs[i].Bit();
+    } else {
+      ASSERT(!regs[i].IsValid());
+    }
+  }
+
+  int number_of_unique_regs =
+    CountSetBits(unique_regs, sizeof(unique_regs) * 8);
+  int number_of_unique_fpregs =
+    CountSetBits(unique_fpregs, sizeof(unique_fpregs) * 8);
+
+  ASSERT(number_of_valid_regs >= number_of_unique_regs);
+  ASSERT(number_of_valid_fpregs >= number_of_unique_fpregs);
+
+  return (number_of_valid_regs != number_of_unique_regs) ||
+         (number_of_valid_fpregs != number_of_unique_fpregs);
+}
+
+
+bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2,
+                        const CPURegister& reg3, const CPURegister& reg4,
+                        const CPURegister& reg5, const CPURegister& reg6,
+                        const CPURegister& reg7, const CPURegister& reg8) {
+  ASSERT(reg1.IsValid());
+  bool match = true;
+  match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1);
+  match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1);
+  match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1);
+  match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1);
+  match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1);
+  match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1);
+  match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1);
+  return match;
+}
+
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/assembler-a64.h b/disas/libvixl/src/a64/assembler-a64.h
new file mode 100644
index 0000000..93b3011
--- /dev/null
+++ b/disas/libvixl/src/a64/assembler-a64.h
@@ -0,0 +1,1784 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_ASSEMBLER_A64_H_
+#define VIXL_A64_ASSEMBLER_A64_H_
+
+#include <list>
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/instructions-a64.h"
+
+namespace vixl {
+
+typedef uint64_t RegList;
+static const int kRegListSizeInBits = sizeof(RegList) * 8;
+
+// Registers.
+
+// Some CPURegister methods can return Register and FPRegister types, so we
+// need to declare them in advance.
+class Register;
+class FPRegister;
+
+
+class CPURegister {
+ public:
+  enum RegisterType {
+    // The kInvalid value is used to detect uninitialized static instances,
+    // which are always zero-initialized before any constructors are called.
+    kInvalid = 0,
+    kRegister,
+    kFPRegister,
+    kNoRegister
+  };
+
+  CPURegister() : code_(0), size_(0), type_(kNoRegister) {
+    ASSERT(!IsValid());
+    ASSERT(IsNone());
+  }
+
+  CPURegister(unsigned code, unsigned size, RegisterType type)
+      : code_(code), size_(size), type_(type) {
+    ASSERT(IsValidOrNone());
+  }
+
+  unsigned code() const {
+    ASSERT(IsValid());
+    return code_;
+  }
+
+  RegisterType type() const {
+    ASSERT(IsValidOrNone());
+    return type_;
+  }
+
+  RegList Bit() const {
+    ASSERT(code_ < (sizeof(RegList) * 8));
+    return IsValid() ? (static_cast<RegList>(1) << code_) : 0;
+  }
+
+  unsigned size() const {
+    ASSERT(IsValid());
+    return size_;
+  }
+
+  int SizeInBytes() const {
+    ASSERT(IsValid());
+    ASSERT(size() % 8 == 0);
+    return size_ / 8;
+  }
+
+  int SizeInBits() const {
+    ASSERT(IsValid());
+    return size_;
+  }
+
+  bool Is32Bits() const {
+    ASSERT(IsValid());
+    return size_ == 32;
+  }
+
+  bool Is64Bits() const {
+    ASSERT(IsValid());
+    return size_ == 64;
+  }
+
+  bool IsValid() const {
+    if (IsValidRegister() || IsValidFPRegister()) {
+      ASSERT(!IsNone());
+      return true;
+    } else {
+      ASSERT(IsNone());
+      return false;
+    }
+  }
+
+  bool IsValidRegister() const {
+    return IsRegister() &&
+           ((size_ == kWRegSize) || (size_ == kXRegSize)) &&
+           ((code_ < kNumberOfRegisters) || (code_ == kSPRegInternalCode));
+  }
+
+  bool IsValidFPRegister() const {
+    return IsFPRegister() &&
+           ((size_ == kSRegSize) || (size_ == kDRegSize)) &&
+           (code_ < kNumberOfFPRegisters);
+  }
+
+  bool IsNone() const {
+    // kNoRegister types should always have size 0 and code 0.
+    ASSERT((type_ != kNoRegister) || (code_ == 0));
+    ASSERT((type_ != kNoRegister) || (size_ == 0));
+
+    return type_ == kNoRegister;
+  }
+
+  bool Is(const CPURegister& other) const {
+    ASSERT(IsValidOrNone() && other.IsValidOrNone());
+    return (code_ == other.code_) && (size_ == other.size_) &&
+           (type_ == other.type_);
+  }
+
+  inline bool IsZero() const {
+    ASSERT(IsValid());
+    return IsRegister() && (code_ == kZeroRegCode);
+  }
+
+  inline bool IsSP() const {
+    ASSERT(IsValid());
+    return IsRegister() && (code_ == kSPRegInternalCode);
+  }
+
+  inline bool IsRegister() const {
+    return type_ == kRegister;
+  }
+
+  inline bool IsFPRegister() const {
+    return type_ == kFPRegister;
+  }
+
+  const Register& W() const;
+  const Register& X() const;
+  const FPRegister& S() const;
+  const FPRegister& D() const;
+
+  inline bool IsSameSizeAndType(const CPURegister& other) const {
+    return (size_ == other.size_) && (type_ == other.type_);
+  }
+
+ protected:
+  unsigned code_;
+  unsigned size_;
+  RegisterType type_;
+
+ private:
+  bool IsValidOrNone() const {
+    return IsValid() || IsNone();
+  }
+};
+
+
+class Register : public CPURegister {
+ public:
+  explicit Register() : CPURegister() {}
+  inline explicit Register(const CPURegister& other)
+      : CPURegister(other.code(), other.size(), other.type()) {
+    ASSERT(IsValidRegister());
+  }
+  explicit Register(unsigned code, unsigned size)
+      : CPURegister(code, size, kRegister) {}
+
+  bool IsValid() const {
+    ASSERT(IsRegister() || IsNone());
+    return IsValidRegister();
+  }
+
+  static const Register& WRegFromCode(unsigned code);
+  static const Register& XRegFromCode(unsigned code);
+
+  // V8 compatibility.
+  static const int kNumRegisters = kNumberOfRegisters;
+  static const int kNumAllocatableRegisters = kNumberOfRegisters - 1;
+
+ private:
+  static const Register wregisters[];
+  static const Register xregisters[];
+};
+
+
+class FPRegister : public CPURegister {
+ public:
+  inline FPRegister() : CPURegister() {}
+  inline explicit FPRegister(const CPURegister& other)
+      : CPURegister(other.code(), other.size(), other.type()) {
+    ASSERT(IsValidFPRegister());
+  }
+  inline FPRegister(unsigned code, unsigned size)
+      : CPURegister(code, size, kFPRegister) {}
+
+  bool IsValid() const {
+    ASSERT(IsFPRegister() || IsNone());
+    return IsValidFPRegister();
+  }
+
+  static const FPRegister& SRegFromCode(unsigned code);
+  static const FPRegister& DRegFromCode(unsigned code);
+
+  // V8 compatibility.
+  static const int kNumRegisters = kNumberOfFPRegisters;
+  static const int kNumAllocatableRegisters = kNumberOfFPRegisters - 1;
+
+ private:
+  static const FPRegister sregisters[];
+  static const FPRegister dregisters[];
+};
+
+
+// No*Reg is used to indicate an unused argument, or an error case. Note that
+// these all compare equal (using the Is() method). The Register and FPRegister
+// variants are provided for convenience.
+const Register NoReg;
+const FPRegister NoFPReg;
+const CPURegister NoCPUReg;
+
+
+#define DEFINE_REGISTERS(N)  \
+const Register w##N(N, kWRegSize);  \
+const Register x##N(N, kXRegSize);
+REGISTER_CODE_LIST(DEFINE_REGISTERS)
+#undef DEFINE_REGISTERS
+const Register wsp(kSPRegInternalCode, kWRegSize);
+const Register sp(kSPRegInternalCode, kXRegSize);
+
+
+#define DEFINE_FPREGISTERS(N)  \
+const FPRegister s##N(N, kSRegSize);  \
+const FPRegister d##N(N, kDRegSize);
+REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
+#undef DEFINE_FPREGISTERS
+
+
+// Registers aliases.
+const Register ip0 = x16;
+const Register ip1 = x17;
+const Register lr = x30;
+const Register xzr = x31;
+const Register wzr = w31;
+
+
+// AreAliased returns true if any of the named registers overlap. Arguments
+// set to NoReg are ignored. The system stack pointer may be specified.
+bool AreAliased(const CPURegister& reg1,
+                const CPURegister& reg2,
+                const CPURegister& reg3 = NoReg,
+                const CPURegister& reg4 = NoReg,
+                const CPURegister& reg5 = NoReg,
+                const CPURegister& reg6 = NoReg,
+                const CPURegister& reg7 = NoReg,
+                const CPURegister& reg8 = NoReg);
+
+
+// AreSameSizeAndType returns true if all of the specified registers have the
+// same size, and are of the same type. The system stack pointer may be
+// specified. Arguments set to NoReg are ignored, as are any subsequent
+// arguments. At least one argument (reg1) must be valid (not NoCPUReg).
+bool AreSameSizeAndType(const CPURegister& reg1,
+                        const CPURegister& reg2,
+                        const CPURegister& reg3 = NoCPUReg,
+                        const CPURegister& reg4 = NoCPUReg,
+                        const CPURegister& reg5 = NoCPUReg,
+                        const CPURegister& reg6 = NoCPUReg,
+                        const CPURegister& reg7 = NoCPUReg,
+                        const CPURegister& reg8 = NoCPUReg);
+
+
+// Lists of registers.
+class CPURegList {
+ public:
+  inline explicit CPURegList(CPURegister reg1,
+                             CPURegister reg2 = NoCPUReg,
+                             CPURegister reg3 = NoCPUReg,
+                             CPURegister reg4 = NoCPUReg)
+      : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()),
+        size_(reg1.size()), type_(reg1.type()) {
+    ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4));
+    ASSERT(IsValid());
+  }
+
+  inline CPURegList(CPURegister::RegisterType type, unsigned size, RegList list)
+      : list_(list), size_(size), type_(type) {
+    ASSERT(IsValid());
+  }
+
+  inline CPURegList(CPURegister::RegisterType type, unsigned size,
+                    unsigned first_reg, unsigned last_reg)
+      : size_(size), type_(type) {
+    ASSERT(((type == CPURegister::kRegister) &&
+            (last_reg < kNumberOfRegisters)) ||
+           ((type == CPURegister::kFPRegister) &&
+            (last_reg < kNumberOfFPRegisters)));
+    ASSERT(last_reg >= first_reg);
+    list_ = (1UL << (last_reg + 1)) - 1;
+    list_ &= ~((1UL << first_reg) - 1);
+    ASSERT(IsValid());
+  }
+
+  inline CPURegister::RegisterType type() const {
+    ASSERT(IsValid());
+    return type_;
+  }
+
+  // Combine another CPURegList into this one. Registers that already exist in
+  // this list are left unchanged. The type and size of the registers in the
+  // 'other' list must match those in this list.
+  void Combine(const CPURegList& other) {
+    ASSERT(IsValid());
+    ASSERT(other.type() == type_);
+    ASSERT(other.RegisterSizeInBits() == size_);
+    list_ |= other.list();
+  }
+
+  // Remove every register in the other CPURegList from this one. Registers that
+  // do not exist in this list are ignored. The type and size of the registers
+  // in the 'other' list must match those in this list.
+  void Remove(const CPURegList& other) {
+    ASSERT(IsValid());
+    ASSERT(other.type() == type_);
+    ASSERT(other.RegisterSizeInBits() == size_);
+    list_ &= ~other.list();
+  }
+
+  // Variants of Combine and Remove which take a single register.
+  inline void Combine(const CPURegister& other) {
+    ASSERT(other.type() == type_);
+    ASSERT(other.size() == size_);
+    Combine(other.code());
+  }
+
+  inline void Remove(const CPURegister& other) {
+    ASSERT(other.type() == type_);
+    ASSERT(other.size() == size_);
+    Remove(other.code());
+  }
+
+  // Variants of Combine and Remove which take a single register by its code;
+  // the type and size of the register is inferred from this list.
+  inline void Combine(int code) {
+    ASSERT(IsValid());
+    ASSERT(CPURegister(code, size_, type_).IsValid());
+    list_ |= (1UL << code);
+  }
+
+  inline void Remove(int code) {
+    ASSERT(IsValid());
+    ASSERT(CPURegister(code, size_, type_).IsValid());
+    list_ &= ~(1UL << code);
+  }
+
+  inline RegList list() const {
+    ASSERT(IsValid());
+    return list_;
+  }
+
+  // Remove all callee-saved registers from the list. This can be useful when
+  // preparing registers for an AAPCS64 function call, for example.
+  void RemoveCalleeSaved();
+
+  CPURegister PopLowestIndex();
+  CPURegister PopHighestIndex();
+
+  // AAPCS64 callee-saved registers.
+  static CPURegList GetCalleeSaved(unsigned size = kXRegSize);
+  static CPURegList GetCalleeSavedFP(unsigned size = kDRegSize);
+
+  // AAPCS64 caller-saved registers. Note that this includes lr.
+  static CPURegList GetCallerSaved(unsigned size = kXRegSize);
+  static CPURegList GetCallerSavedFP(unsigned size = kDRegSize);
+
+  inline bool IsEmpty() const {
+    ASSERT(IsValid());
+    return list_ == 0;
+  }
+
+  inline bool IncludesAliasOf(const CPURegister& other) const {
+    ASSERT(IsValid());
+    return (type_ == other.type()) && (other.Bit() & list_);
+  }
+
+  inline int Count() const {
+    ASSERT(IsValid());
+    return CountSetBits(list_, kRegListSizeInBits);
+  }
+
+  inline unsigned RegisterSizeInBits() const {
+    ASSERT(IsValid());
+    return size_;
+  }
+
+  inline unsigned RegisterSizeInBytes() const {
+    int size_in_bits = RegisterSizeInBits();
+    ASSERT((size_in_bits % 8) == 0);
+    return size_in_bits / 8;
+  }
+
+ private:
+  RegList list_;
+  unsigned size_;
+  CPURegister::RegisterType type_;
+
+  bool IsValid() const;
+};
+
+
+// AAPCS64 callee-saved registers.
+extern const CPURegList kCalleeSaved;
+extern const CPURegList kCalleeSavedFP;
+
+
+// AAPCS64 caller-saved registers. Note that this includes lr.
+extern const CPURegList kCallerSaved;
+extern const CPURegList kCallerSavedFP;
+
+
+// Operand.
+class Operand {
+ public:
+  // #<immediate>
+  // where <immediate> is int64_t.
+  // This is allowed to be an implicit constructor because Operand is
+  // a wrapper class that doesn't normally perform any type conversion.
+  Operand(int64_t immediate);           // NOLINT(runtime/explicit)
+
+  // rm, {<shift> #<shift_amount>}
+  // where <shift> is one of {LSL, LSR, ASR, ROR}.
+  //       <shift_amount> is uint6_t.
+  // This is allowed to be an implicit constructor because Operand is
+  // a wrapper class that doesn't normally perform any type conversion.
+  Operand(Register reg,
+          Shift shift = LSL,
+          unsigned shift_amount = 0);   // NOLINT(runtime/explicit)
+
+  // rm, {<extend> {#<shift_amount>}}
+  // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}.
+  //       <shift_amount> is uint2_t.
+  explicit Operand(Register reg, Extend extend, unsigned shift_amount = 0);
+
+  bool IsImmediate() const;
+  bool IsShiftedRegister() const;
+  bool IsExtendedRegister() const;
+
+  // This returns an LSL shift (<= 4) operand as an equivalent extend operand,
+  // which helps in the encoding of instructions that use the stack pointer.
+  Operand ToExtendedRegister() const;
+
+  int64_t immediate() const {
+    ASSERT(IsImmediate());
+    return immediate_;
+  }
+
+  Register reg() const {
+    ASSERT(IsShiftedRegister() || IsExtendedRegister());
+    return reg_;
+  }
+
+  Shift shift() const {
+    ASSERT(IsShiftedRegister());
+    return shift_;
+  }
+
+  Extend extend() const {
+    ASSERT(IsExtendedRegister());
+    return extend_;
+  }
+
+  unsigned shift_amount() const {
+    ASSERT(IsShiftedRegister() || IsExtendedRegister());
+    return shift_amount_;
+  }
+
+ private:
+  int64_t immediate_;
+  Register reg_;
+  Shift shift_;
+  Extend extend_;
+  unsigned shift_amount_;
+};
+
+
+// MemOperand represents the addressing mode of a load or store instruction.
+class MemOperand {
+ public:
+  explicit MemOperand(Register base,
+                      ptrdiff_t offset = 0,
+                      AddrMode addrmode = Offset);
+  explicit MemOperand(Register base,
+                      Register regoffset,
+                      Shift shift = LSL,
+                      unsigned shift_amount = 0);
+  explicit MemOperand(Register base,
+                      Register regoffset,
+                      Extend extend,
+                      unsigned shift_amount = 0);
+  explicit MemOperand(Register base,
+                      const Operand& offset,
+                      AddrMode addrmode = Offset);
+
+  const Register& base() const { return base_; }
+  const Register& regoffset() const { return regoffset_; }
+  ptrdiff_t offset() const { return offset_; }
+  AddrMode addrmode() const { return addrmode_; }
+  Shift shift() const { return shift_; }
+  Extend extend() const { return extend_; }
+  unsigned shift_amount() const { return shift_amount_; }
+  bool IsImmediateOffset() const;
+  bool IsRegisterOffset() const;
+  bool IsPreIndex() const;
+  bool IsPostIndex() const;
+
+ private:
+  Register base_;
+  Register regoffset_;
+  ptrdiff_t offset_;
+  AddrMode addrmode_;
+  Shift shift_;
+  Extend extend_;
+  unsigned shift_amount_;
+};
+
+
+class Label {
+ public:
+  Label() : is_bound_(false), link_(NULL), target_(NULL) {}
+  ~Label() {
+    // If the label has been linked to, it needs to be bound to a target.
+    ASSERT(!IsLinked() || IsBound());
+  }
+
+  inline Instruction* link() const { return link_; }
+  inline Instruction* target() const { return target_; }
+
+  inline bool IsBound() const { return is_bound_; }
+  inline bool IsLinked() const { return link_ != NULL; }
+
+  inline void set_link(Instruction* new_link) { link_ = new_link; }
+
+  static const int kEndOfChain = 0;
+
+ private:
+  // Indicates if the label has been bound, ie its location is fixed.
+  bool is_bound_;
+  // Branches instructions branching to this label form a chained list, with
+  // their offset indicating where the next instruction is located.
+  // link_ points to the latest branch instruction generated branching to this
+  // branch.
+  // If link_ is not NULL, the label has been linked to.
+  Instruction* link_;
+  // The label location.
+  Instruction* target_;
+
+  friend class Assembler;
+};
+
+
+// TODO: Obtain better values for these, based on real-world data.
+const int kLiteralPoolCheckInterval = 4 * KBytes;
+const int kRecommendedLiteralPoolRange = 2 * kLiteralPoolCheckInterval;
+
+
+// Control whether a branch over the literal pool should also be emitted. This
+// is needed if the literal pool has to be emitted in the middle of the JITted
+// code.
+enum LiteralPoolEmitOption {
+  JumpRequired,
+  NoJumpRequired
+};
+
+
+// Literal pool entry.
+class Literal {
+ public:
+  Literal(Instruction* pc, uint64_t imm, unsigned size)
+      : pc_(pc), value_(imm), size_(size) {}
+
+ private:
+  Instruction* pc_;
+  int64_t value_;
+  unsigned size_;
+
+  friend class Assembler;
+};
+
+
+// Assembler.
+class Assembler {
+ public:
+  Assembler(byte* buffer, unsigned buffer_size);
+
+  // The destructor asserts that one of the following is true:
+  //  * The Assembler object has not been used.
+  //  * Nothing has been emitted since the last Reset() call.
+  //  * Nothing has been emitted since the last FinalizeCode() call.
+  ~Assembler();
+
+  // System functions.
+
+  // Start generating code from the beginning of the buffer, discarding any code
+  // and data that has already been emitted into the buffer.
+  //
+  // In order to avoid any accidental transfer of state, Reset ASSERTs that the
+  // constant pool is not blocked.
+  void Reset();
+
+  // Finalize a code buffer of generated instructions. This function must be
+  // called before executing or copying code from the buffer.
+  void FinalizeCode();
+
+  // Label.
+  // Bind a label to the current PC.
+  void bind(Label* label);
+  int UpdateAndGetByteOffsetTo(Label* label);
+  inline int UpdateAndGetInstructionOffsetTo(Label* label) {
+    ASSERT(Label::kEndOfChain == 0);
+    return UpdateAndGetByteOffsetTo(label) >> kInstructionSizeLog2;
+  }
+
+
+  // Instruction set functions.
+
+  // Branch / Jump instructions.
+  // Branch to register.
+  void br(const Register& xn);
+
+  // Branch with link to register.
+  void blr(const Register& xn);
+
+  // Branch to register with return hint.
+  void ret(const Register& xn = lr);
+
+  // Unconditional branch to label.
+  void b(Label* label);
+
+  // Conditional branch to label.
+  void b(Label* label, Condition cond);
+
+  // Unconditional branch to PC offset.
+  void b(int imm26);
+
+  // Conditional branch to PC offset.
+  void b(int imm19, Condition cond);
+
+  // Branch with link to label.
+  void bl(Label* label);
+
+  // Branch with link to PC offset.
+  void bl(int imm26);
+
+  // Compare and branch to label if zero.
+  void cbz(const Register& rt, Label* label);
+
+  // Compare and branch to PC offset if zero.
+  void cbz(const Register& rt, int imm19);
+
+  // Compare and branch to label if not zero.
+  void cbnz(const Register& rt, Label* label);
+
+  // Compare and branch to PC offset if not zero.
+  void cbnz(const Register& rt, int imm19);
+
+  // Test bit and branch to label if zero.
+  void tbz(const Register& rt, unsigned bit_pos, Label* label);
+
+  // Test bit and branch to PC offset if zero.
+  void tbz(const Register& rt, unsigned bit_pos, int imm14);
+
+  // Test bit and branch to label if not zero.
+  void tbnz(const Register& rt, unsigned bit_pos, Label* label);
+
+  // Test bit and branch to PC offset if not zero.
+  void tbnz(const Register& rt, unsigned bit_pos, int imm14);
+
+  // Address calculation instructions.
+  // Calculate a PC-relative address. Unlike for branches the offset in adr is
+  // unscaled (i.e. the result can be unaligned).
+
+  // Calculate the address of a label.
+  void adr(const Register& rd, Label* label);
+
+  // Calculate the address of a PC offset.
+  void adr(const Register& rd, int imm21);
+
+  // Data Processing instructions.
+  // Add.
+  void add(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Compare negative.
+  void cmn(const Register& rn, const Operand& operand);
+
+  // Subtract.
+  void sub(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Compare.
+  void cmp(const Register& rn, const Operand& operand);
+
+  // Negate.
+  void neg(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Add with carry bit.
+  void adc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Subtract with carry bit.
+  void sbc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Negate with carry bit.
+  void ngc(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Logical instructions.
+  // Bitwise and (A & B).
+  void and_(const Register& rd,
+            const Register& rn,
+            const Operand& operand,
+            FlagsUpdate S = LeaveFlags);
+
+  // Bit test and set flags.
+  void tst(const Register& rn, const Operand& operand);
+
+  // Bit clear (A & ~B).
+  void bic(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Bitwise or (A | B).
+  void orr(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Bitwise nor (A | ~B).
+  void orn(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Bitwise eor/xor (A ^ B).
+  void eor(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Bitwise enor/xnor (A ^ ~B).
+  void eon(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Logical shift left by variable.
+  void lslv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Logical shift right by variable.
+  void lsrv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Arithmetic shift right by variable.
+  void asrv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Rotate right by variable.
+  void rorv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Bitfield instructions.
+  // Bitfield move.
+  void bfm(const Register& rd,
+           const Register& rn,
+           unsigned immr,
+           unsigned imms);
+
+  // Signed bitfield move.
+  void sbfm(const Register& rd,
+            const Register& rn,
+            unsigned immr,
+            unsigned imms);
+
+  // Unsigned bitfield move.
+  void ubfm(const Register& rd,
+            const Register& rn,
+            unsigned immr,
+            unsigned imms);
+
+  // Bfm aliases.
+  // Bitfield insert.
+  inline void bfi(const Register& rd,
+                  const Register& rn,
+                  unsigned lsb,
+                  unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    bfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1);
+  }
+
+  // Bitfield extract and insert low.
+  inline void bfxil(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    bfm(rd, rn, lsb, lsb + width - 1);
+  }
+
+  // Sbfm aliases.
+  // Arithmetic shift right.
+  inline void asr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(shift < rd.size());
+    sbfm(rd, rn, shift, rd.size() - 1);
+  }
+
+  // Signed bitfield insert with zero at right.
+  inline void sbfiz(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    sbfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1);
+  }
+
+  // Signed bitfield extract.
+  inline void sbfx(const Register& rd,
+                   const Register& rn,
+                   unsigned lsb,
+                   unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    sbfm(rd, rn, lsb, lsb + width - 1);
+  }
+
+  // Signed extend byte.
+  inline void sxtb(const Register& rd, const Register& rn) {
+    sbfm(rd, rn, 0, 7);
+  }
+
+  // Signed extend halfword.
+  inline void sxth(const Register& rd, const Register& rn) {
+    sbfm(rd, rn, 0, 15);
+  }
+
+  // Signed extend word.
+  inline void sxtw(const Register& rd, const Register& rn) {
+    sbfm(rd, rn, 0, 31);
+  }
+
+  // Ubfm aliases.
+  // Logical shift left.
+  inline void lsl(const Register& rd, const Register& rn, unsigned shift) {
+    unsigned reg_size = rd.size();
+    ASSERT(shift < reg_size);
+    ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1);
+  }
+
+  // Logical shift right.
+  inline void lsr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(shift < rd.size());
+    ubfm(rd, rn, shift, rd.size() - 1);
+  }
+
+  // Unsigned bitfield insert with zero at right.
+  inline void ubfiz(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    ubfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1);
+  }
+
+  // Unsigned bitfield extract.
+  inline void ubfx(const Register& rd,
+                   const Register& rn,
+                   unsigned lsb,
+                   unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    ubfm(rd, rn, lsb, lsb + width - 1);
+  }
+
+  // Unsigned extend byte.
+  inline void uxtb(const Register& rd, const Register& rn) {
+    ubfm(rd, rn, 0, 7);
+  }
+
+  // Unsigned extend halfword.
+  inline void uxth(const Register& rd, const Register& rn) {
+    ubfm(rd, rn, 0, 15);
+  }
+
+  // Unsigned extend word.
+  inline void uxtw(const Register& rd, const Register& rn) {
+    ubfm(rd, rn, 0, 31);
+  }
+
+  // Extract.
+  void extr(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            unsigned lsb);
+
+  // Conditional select: rd = cond ? rn : rm.
+  void csel(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            Condition cond);
+
+  // Conditional select increment: rd = cond ? rn : rm + 1.
+  void csinc(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond);
+
+  // Conditional select inversion: rd = cond ? rn : ~rm.
+  void csinv(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond);
+
+  // Conditional select negation: rd = cond ? rn : -rm.
+  void csneg(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond);
+
+  // Conditional set: rd = cond ? 1 : 0.
+  void cset(const Register& rd, Condition cond);
+
+  // Conditional set mask: rd = cond ? -1 : 0.
+  void csetm(const Register& rd, Condition cond);
+
+  // Conditional increment: rd = cond ? rn + 1 : rn.
+  void cinc(const Register& rd, const Register& rn, Condition cond);
+
+  // Conditional invert: rd = cond ? ~rn : rn.
+  void cinv(const Register& rd, const Register& rn, Condition cond);
+
+  // Conditional negate: rd = cond ? -rn : rn.
+  void cneg(const Register& rd, const Register& rn, Condition cond);
+
+  // Rotate right.
+  inline void ror(const Register& rd, const Register& rs, unsigned shift) {
+    extr(rd, rs, rs, shift);
+  }
+
+  // Conditional comparison.
+  // Conditional compare negative.
+  void ccmn(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+
+  // Conditional compare.
+  void ccmp(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+
+  // Multiply.
+  void mul(const Register& rd, const Register& rn, const Register& rm);
+
+  // Negated multiply.
+  void mneg(const Register& rd, const Register& rn, const Register& rm);
+
+  // Signed long multiply: 32 x 32 -> 64-bit.
+  void smull(const Register& rd, const Register& rn, const Register& rm);
+
+  // Signed multiply high: 64 x 64 -> 64-bit <127:64>.
+  void smulh(const Register& xd, const Register& xn, const Register& xm);
+
+  // Multiply and accumulate.
+  void madd(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra);
+
+  // Multiply and subtract.
+  void msub(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra);
+
+  // Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+  void smaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+  void umaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+  void smsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+  void umsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Signed integer divide.
+  void sdiv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Unsigned integer divide.
+  void udiv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Bit reverse.
+  void rbit(const Register& rd, const Register& rn);
+
+  // Reverse bytes in 16-bit half words.
+  void rev16(const Register& rd, const Register& rn);
+
+  // Reverse bytes in 32-bit words.
+  void rev32(const Register& rd, const Register& rn);
+
+  // Reverse bytes.
+  void rev(const Register& rd, const Register& rn);
+
+  // Count leading zeroes.
+  void clz(const Register& rd, const Register& rn);
+
+  // Count leading sign bits.
+  void cls(const Register& rd, const Register& rn);
+
+  // Memory instructions.
+  // Load integer or FP register.
+  void ldr(const CPURegister& rt, const MemOperand& src);
+
+  // Store integer or FP register.
+  void str(const CPURegister& rt, const MemOperand& dst);
+
+  // Load word with sign extension.
+  void ldrsw(const Register& rt, const MemOperand& src);
+
+  // Load byte.
+  void ldrb(const Register& rt, const MemOperand& src);
+
+  // Store byte.
+  void strb(const Register& rt, const MemOperand& dst);
+
+  // Load byte with sign extension.
+  void ldrsb(const Register& rt, const MemOperand& src);
+
+  // Load half-word.
+  void ldrh(const Register& rt, const MemOperand& src);
+
+  // Store half-word.
+  void strh(const Register& rt, const MemOperand& dst);
+
+  // Load half-word with sign extension.
+  void ldrsh(const Register& rt, const MemOperand& src);
+
+  // Load integer or FP register pair.
+  void ldp(const CPURegister& rt, const CPURegister& rt2,
+           const MemOperand& src);
+
+  // Store integer or FP register pair.
+  void stp(const CPURegister& rt, const CPURegister& rt2,
+           const MemOperand& dst);
+
+  // Load word pair with sign extension.
+  void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src);
+
+  // Load integer or FP register pair, non-temporal.
+  void ldnp(const CPURegister& rt, const CPURegister& rt2,
+            const MemOperand& src);
+
+  // Store integer or FP register pair, non-temporal.
+  void stnp(const CPURegister& rt, const CPURegister& rt2,
+            const MemOperand& dst);
+
+  // Load literal to register.
+  void ldr(const Register& rt, uint64_t imm);
+
+  // Load literal to FP register.
+  void ldr(const FPRegister& ft, double imm);
+
+  // Move instructions. The default shift of -1 indicates that the move
+  // instruction will calculate an appropriate 16-bit immediate and left shift
+  // that is equal to the 64-bit immediate argument. If an explicit left shift
+  // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value.
+  //
+  // For movk, an explicit shift can be used to indicate which half word should
+  // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant
+  // half word with zero, whereas movk(x0, 0, 48) will overwrite the
+  // most-significant.
+
+  // Move immediate and keep.
+  void movk(const Register& rd, uint64_t imm, int shift = -1) {
+    MoveWide(rd, imm, shift, MOVK);
+  }
+
+  // Move inverted immediate.
+  void movn(const Register& rd, uint64_t imm, int shift = -1) {
+    MoveWide(rd, imm, shift, MOVN);
+  }
+
+  // Move immediate.
+  void movz(const Register& rd, uint64_t imm, int shift = -1) {
+    MoveWide(rd, imm, shift, MOVZ);
+  }
+
+  // Misc instructions.
+  // Monitor debug-mode breakpoint.
+  void brk(int code);
+
+  // Halting debug-mode breakpoint.
+  void hlt(int code);
+
+  // Move register to register.
+  void mov(const Register& rd, const Register& rn);
+
+  // Move inverted operand to register.
+  void mvn(const Register& rd, const Operand& operand);
+
+  // System instructions.
+  // Move to register from system register.
+  void mrs(const Register& rt, SystemRegister sysreg);
+
+  // Move from register to system register.
+  void msr(SystemRegister sysreg, const Register& rt);
+
+  // System hint.
+  void hint(SystemHint code);
+
+  // Alias for system instructions.
+  // No-op.
+  void nop() {
+    hint(NOP);
+  }
+
+  // FP instructions.
+  // Move immediate to FP register.
+  void fmov(FPRegister fd, double imm);
+
+  // Move FP register to register.
+  void fmov(Register rd, FPRegister fn);
+
+  // Move register to FP register.
+  void fmov(FPRegister fd, Register rn);
+
+  // Move FP register to FP register.
+  void fmov(FPRegister fd, FPRegister fn);
+
+  // FP add.
+  void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP subtract.
+  void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP multiply.
+  void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP multiply and subtract.
+  void fmsub(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             const FPRegister& fa);
+
+  // FP divide.
+  void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP maximum.
+  void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP minimum.
+  void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP absolute.
+  void fabs(const FPRegister& fd, const FPRegister& fn);
+
+  // FP negate.
+  void fneg(const FPRegister& fd, const FPRegister& fn);
+
+  // FP square root.
+  void fsqrt(const FPRegister& fd, const FPRegister& fn);
+
+  // FP round to integer (nearest with ties to even).
+  void frintn(const FPRegister& fd, const FPRegister& fn);
+
+  // FP round to integer (towards zero).
+  void frintz(const FPRegister& fd, const FPRegister& fn);
+
+  // FP compare registers.
+  void fcmp(const FPRegister& fn, const FPRegister& fm);
+
+  // FP compare immediate.
+  void fcmp(const FPRegister& fn, double value);
+
+  // FP conditional compare.
+  void fccmp(const FPRegister& fn,
+             const FPRegister& fm,
+             StatusFlags nzcv,
+             Condition cond);
+
+  // FP conditional select.
+  void fcsel(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             Condition cond);
+
+  // Common FP Convert function.
+  void FPConvertToInt(const Register& rd,
+                      const FPRegister& fn,
+                      FPIntegerConvertOp op);
+
+  // FP convert between single and double precision.
+  void fcvt(const FPRegister& fd, const FPRegister& fn);
+
+  // Convert FP to unsigned integer (round towards -infinity).
+  void fcvtmu(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to signed integer (round towards -infinity).
+  void fcvtms(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to unsigned integer (nearest with ties to even).
+  void fcvtnu(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to signed integer (nearest with ties to even).
+  void fcvtns(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to unsigned integer (round towards zero).
+  void fcvtzu(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to signed integer (round towards zero).
+  void fcvtzs(const Register& rd, const FPRegister& fn);
+
+  // Convert signed integer or fixed point to FP.
+  void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
+
+  // Convert unsigned integer or fixed point to FP.
+  void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
+
+  // Emit generic instructions.
+  // Emit raw instructions into the instruction stream.
+  inline void dci(Instr raw_inst) { Emit(raw_inst); }
+
+  // Emit 32 bits of data into the instruction stream.
+  inline void dc32(uint32_t data) { EmitData(&data, sizeof(data)); }
+
+  // Emit 64 bits of data into the instruction stream.
+  inline void dc64(uint64_t data) { EmitData(&data, sizeof(data)); }
+
+  // Copy a string into the instruction stream, including the terminating NULL
+  // character. The instruction pointer (pc_) is then aligned correctly for
+  // subsequent instructions.
+  void EmitStringData(const char * string) {
+    ASSERT(string != NULL);
+
+    size_t len = strlen(string) + 1;
+    EmitData(string, len);
+
+    // Pad with NULL characters until pc_ is aligned.
+    const char pad[] = {'\0', '\0', '\0', '\0'};
+    ASSERT(sizeof(pad) == kInstructionSize);
+    Instruction* next_pc = AlignUp(pc_, kInstructionSize);
+    EmitData(&pad, next_pc - pc_);
+  }
+
+  // Code generation helpers.
+
+  // Register encoding.
+  static Instr Rd(CPURegister rd) {
+    ASSERT(rd.code() != kSPRegInternalCode);
+    return rd.code() << Rd_offset;
+  }
+
+  static Instr Rn(CPURegister rn) {
+    ASSERT(rn.code() != kSPRegInternalCode);
+    return rn.code() << Rn_offset;
+  }
+
+  static Instr Rm(CPURegister rm) {
+    ASSERT(rm.code() != kSPRegInternalCode);
+    return rm.code() << Rm_offset;
+  }
+
+  static Instr Ra(CPURegister ra) {
+    ASSERT(ra.code() != kSPRegInternalCode);
+    return ra.code() << Ra_offset;
+  }
+
+  static Instr Rt(CPURegister rt) {
+    ASSERT(rt.code() != kSPRegInternalCode);
+    return rt.code() << Rt_offset;
+  }
+
+  static Instr Rt2(CPURegister rt2) {
+    ASSERT(rt2.code() != kSPRegInternalCode);
+    return rt2.code() << Rt2_offset;
+  }
+
+  // These encoding functions allow the stack pointer to be encoded, and
+  // disallow the zero register.
+  static Instr RdSP(Register rd) {
+    ASSERT(!rd.IsZero());
+    return (rd.code() & kRegCodeMask) << Rd_offset;
+  }
+
+  static Instr RnSP(Register rn) {
+    ASSERT(!rn.IsZero());
+    return (rn.code() & kRegCodeMask) << Rn_offset;
+  }
+
+  // Flags encoding.
+  static Instr Flags(FlagsUpdate S) {
+    if (S == SetFlags) {
+      return 1 << FlagsUpdate_offset;
+    } else if (S == LeaveFlags) {
+      return 0 << FlagsUpdate_offset;
+    }
+    UNREACHABLE();
+    return 0;
+  }
+
+  static Instr Cond(Condition cond) {
+    return cond << Condition_offset;
+  }
+
+  // PC-relative address encoding.
+  static Instr ImmPCRelAddress(int imm21) {
+    ASSERT(is_int21(imm21));
+    Instr imm = static_cast<Instr>(truncate_to_int21(imm21));
+    Instr immhi = (imm >> ImmPCRelLo_width) << ImmPCRelHi_offset;
+    Instr immlo = imm << ImmPCRelLo_offset;
+    return (immhi & ImmPCRelHi_mask) | (immlo & ImmPCRelLo_mask);
+  }
+
+  // Branch encoding.
+  static Instr ImmUncondBranch(int imm26) {
+    ASSERT(is_int26(imm26));
+    return truncate_to_int26(imm26) << ImmUncondBranch_offset;
+  }
+
+  static Instr ImmCondBranch(int imm19) {
+    ASSERT(is_int19(imm19));
+    return truncate_to_int19(imm19) << ImmCondBranch_offset;
+  }
+
+  static Instr ImmCmpBranch(int imm19) {
+    ASSERT(is_int19(imm19));
+    return truncate_to_int19(imm19) << ImmCmpBranch_offset;
+  }
+
+  static Instr ImmTestBranch(int imm14) {
+    ASSERT(is_int14(imm14));
+    return truncate_to_int14(imm14) << ImmTestBranch_offset;
+  }
+
+  static Instr ImmTestBranchBit(unsigned bit_pos) {
+    ASSERT(is_uint6(bit_pos));
+    // Subtract five from the shift offset, as we need bit 5 from bit_pos.
+    unsigned b5 = bit_pos << (ImmTestBranchBit5_offset - 5);
+    unsigned b40 = bit_pos << ImmTestBranchBit40_offset;
+    b5 &= ImmTestBranchBit5_mask;
+    b40 &= ImmTestBranchBit40_mask;
+    return b5 | b40;
+  }
+
+  // Data Processing encoding.
+  static Instr SF(Register rd) {
+      return rd.Is64Bits() ? SixtyFourBits : ThirtyTwoBits;
+  }
+
+  static Instr ImmAddSub(int64_t imm) {
+    ASSERT(IsImmAddSub(imm));
+    if (is_uint12(imm)) {  // No shift required.
+      return imm << ImmAddSub_offset;
+    } else {
+      return ((imm >> 12) << ImmAddSub_offset) | (1 << ShiftAddSub_offset);
+    }
+  }
+
+  static inline Instr ImmS(unsigned imms, unsigned reg_size) {
+    ASSERT(((reg_size == kXRegSize) && is_uint6(imms)) ||
+           ((reg_size == kWRegSize) && is_uint5(imms)));
+    USE(reg_size);
+    return imms << ImmS_offset;
+  }
+
+  static inline Instr ImmR(unsigned immr, unsigned reg_size) {
+    ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) ||
+           ((reg_size == kWRegSize) && is_uint5(immr)));
+    USE(reg_size);
+    ASSERT(is_uint6(immr));
+    return immr << ImmR_offset;
+  }
+
+  static inline Instr ImmSetBits(unsigned imms, unsigned reg_size) {
+    ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+    ASSERT(is_uint6(imms));
+    ASSERT((reg_size == kXRegSize) || is_uint6(imms + 3));
+    USE(reg_size);
+    return imms << ImmSetBits_offset;
+  }
+
+  static inline Instr ImmRotate(unsigned immr, unsigned reg_size) {
+    ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+    ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) ||
+           ((reg_size == kWRegSize) && is_uint5(immr)));
+    USE(reg_size);
+    return immr << ImmRotate_offset;
+  }
+
+  static inline Instr ImmLLiteral(int imm19) {
+    ASSERT(is_int19(imm19));
+    return truncate_to_int19(imm19) << ImmLLiteral_offset;
+  }
+
+  static inline Instr BitN(unsigned bitn, unsigned reg_size) {
+    ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+    ASSERT((reg_size == kXRegSize) || (bitn == 0));
+    USE(reg_size);
+    return bitn << BitN_offset;
+  }
+
+  static Instr ShiftDP(Shift shift) {
+    ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR);
+    return shift << ShiftDP_offset;
+  }
+
+  static Instr ImmDPShift(unsigned amount) {
+    ASSERT(is_uint6(amount));
+    return amount << ImmDPShift_offset;
+  }
+
+  static Instr ExtendMode(Extend extend) {
+    return extend << ExtendMode_offset;
+  }
+
+  static Instr ImmExtendShift(unsigned left_shift) {
+    ASSERT(left_shift <= 4);
+    return left_shift << ImmExtendShift_offset;
+  }
+
+  static Instr ImmCondCmp(unsigned imm) {
+    ASSERT(is_uint5(imm));
+    return imm << ImmCondCmp_offset;
+  }
+
+  static Instr Nzcv(StatusFlags nzcv) {
+    return ((nzcv >> Flags_offset) & 0xf) << Nzcv_offset;
+  }
+
+  // MemOperand offset encoding.
+  static Instr ImmLSUnsigned(int imm12) {
+    ASSERT(is_uint12(imm12));
+    return imm12 << ImmLSUnsigned_offset;
+  }
+
+  static Instr ImmLS(int imm9) {
+    ASSERT(is_int9(imm9));
+    return truncate_to_int9(imm9) << ImmLS_offset;
+  }
+
+  static Instr ImmLSPair(int imm7, LSDataSize size) {
+    ASSERT(((imm7 >> size) << size) == imm7);
+    int scaled_imm7 = imm7 >> size;
+    ASSERT(is_int7(scaled_imm7));
+    return truncate_to_int7(scaled_imm7) << ImmLSPair_offset;
+  }
+
+  static Instr ImmShiftLS(unsigned shift_amount) {
+    ASSERT(is_uint1(shift_amount));
+    return shift_amount << ImmShiftLS_offset;
+  }
+
+  static Instr ImmException(int imm16) {
+    ASSERT(is_uint16(imm16));
+    return imm16 << ImmException_offset;
+  }
+
+  static Instr ImmSystemRegister(int imm15) {
+    ASSERT(is_uint15(imm15));
+    return imm15 << ImmSystemRegister_offset;
+  }
+
+  static Instr ImmHint(int imm7) {
+    ASSERT(is_uint7(imm7));
+    return imm7 << ImmHint_offset;
+  }
+
+  static LSDataSize CalcLSDataSize(LoadStoreOp op) {
+    ASSERT((SizeLS_offset + SizeLS_width) == (kInstructionSize * 8));
+    return static_cast<LSDataSize>(op >> SizeLS_offset);
+  }
+
+  // Move immediates encoding.
+  static Instr ImmMoveWide(uint64_t imm) {
+    ASSERT(is_uint16(imm));
+    return imm << ImmMoveWide_offset;
+  }
+
+  static Instr ShiftMoveWide(int64_t shift) {
+    ASSERT(is_uint2(shift));
+    return shift << ShiftMoveWide_offset;
+  }
+
+  // FP Immediates.
+  static Instr ImmFP32(float imm);
+  static Instr ImmFP64(double imm);
+
+  // FP register type.
+  static Instr FPType(FPRegister fd) {
+    return fd.Is64Bits() ? FP64 : FP32;
+  }
+
+  static Instr FPScale(unsigned scale) {
+    ASSERT(is_uint6(scale));
+    return scale << FPScale_offset;
+  }
+
+  // Size of the code generated in bytes
+  uint64_t SizeOfCodeGenerated() const {
+    ASSERT((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_)));
+    return pc_ - buffer_;
+  }
+
+  // Size of the code generated since label to the current position.
+  uint64_t SizeOfCodeGeneratedSince(Label* label) const {
+    ASSERT(label->IsBound());
+    ASSERT((pc_ >= label->target()) && (pc_ < (buffer_ + buffer_size_)));
+    return pc_ - label->target();
+  }
+
+
+  inline void BlockLiteralPool() {
+    literal_pool_monitor_++;
+  }
+
+  inline void ReleaseLiteralPool() {
+    if (--literal_pool_monitor_ == 0) {
+      // Has the literal pool been blocked for too long?
+      ASSERT(literals_.empty() ||
+             (pc_ < (literals_.back()->pc_ + kMaxLoadLiteralRange)));
+    }
+  }
+
+  inline bool IsLiteralPoolBlocked() {
+    return literal_pool_monitor_ != 0;
+  }
+
+  void CheckLiteralPool(LiteralPoolEmitOption option = JumpRequired);
+  void EmitLiteralPool(LiteralPoolEmitOption option = NoJumpRequired);
+  size_t LiteralPoolSize();
+
+ protected:
+  inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const {
+    return reg.Is64Bits() ? xzr : wzr;
+  }
+
+
+  void LoadStore(const CPURegister& rt,
+                 const MemOperand& addr,
+                 LoadStoreOp op);
+  static bool IsImmLSUnscaled(ptrdiff_t offset);
+  static bool IsImmLSScaled(ptrdiff_t offset, LSDataSize size);
+
+  void Logical(const Register& rd,
+               const Register& rn,
+               const Operand& operand,
+               LogicalOp op);
+  void LogicalImmediate(const Register& rd,
+                        const Register& rn,
+                        unsigned n,
+                        unsigned imm_s,
+                        unsigned imm_r,
+                        LogicalOp op);
+  static bool IsImmLogical(uint64_t value,
+                           unsigned width,
+                           unsigned* n,
+                           unsigned* imm_s,
+                           unsigned* imm_r);
+
+  void ConditionalCompare(const Register& rn,
+                          const Operand& operand,
+                          StatusFlags nzcv,
+                          Condition cond,
+                          ConditionalCompareOp op);
+  static bool IsImmConditionalCompare(int64_t immediate);
+
+  void AddSubWithCarry(const Register& rd,
+                       const Register& rn,
+                       const Operand& operand,
+                       FlagsUpdate S,
+                       AddSubWithCarryOp op);
+
+  // Functions for emulating operands not directly supported by the instruction
+  // set.
+  void EmitShift(const Register& rd,
+                 const Register& rn,
+                 Shift shift,
+                 unsigned amount);
+  void EmitExtendShift(const Register& rd,
+                       const Register& rn,
+                       Extend extend,
+                       unsigned left_shift);
+
+  void AddSub(const Register& rd,
+              const Register& rn,
+              const Operand& operand,
+              FlagsUpdate S,
+              AddSubOp op);
+  static bool IsImmAddSub(int64_t immediate);
+
+  // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified
+  // registers. Only simple loads are supported; sign- and zero-extension (such
+  // as in LDPSW_x or LDRB_w) are not supported.
+  static LoadStoreOp LoadOpFor(const CPURegister& rt);
+  static LoadStorePairOp LoadPairOpFor(const CPURegister& rt,
+                                       const CPURegister& rt2);
+  static LoadStoreOp StoreOpFor(const CPURegister& rt);
+  static LoadStorePairOp StorePairOpFor(const CPURegister& rt,
+                                        const CPURegister& rt2);
+  static LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2);
+  static LoadStorePairNonTemporalOp StorePairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2);
+
+
+ private:
+  // Instruction helpers.
+  void MoveWide(const Register& rd,
+                uint64_t imm,
+                int shift,
+                MoveWideImmediateOp mov_op);
+  void DataProcShiftedRegister(const Register& rd,
+                               const Register& rn,
+                               const Operand& operand,
+                               FlagsUpdate S,
+                               Instr op);
+  void DataProcExtendedRegister(const Register& rd,
+                                const Register& rn,
+                                const Operand& operand,
+                                FlagsUpdate S,
+                                Instr op);
+  void LoadStorePair(const CPURegister& rt,
+                     const CPURegister& rt2,
+                     const MemOperand& addr,
+                     LoadStorePairOp op);
+  void LoadStorePairNonTemporal(const CPURegister& rt,
+                                const CPURegister& rt2,
+                                const MemOperand& addr,
+                                LoadStorePairNonTemporalOp op);
+  void LoadLiteral(const CPURegister& rt, uint64_t imm, LoadLiteralOp op);
+  void ConditionalSelect(const Register& rd,
+                         const Register& rn,
+                         const Register& rm,
+                         Condition cond,
+                         ConditionalSelectOp op);
+  void DataProcessing1Source(const Register& rd,
+                             const Register& rn,
+                             DataProcessing1SourceOp op);
+  void DataProcessing3Source(const Register& rd,
+                             const Register& rn,
+                             const Register& rm,
+                             const Register& ra,
+                             DataProcessing3SourceOp op);
+  void FPDataProcessing1Source(const FPRegister& fd,
+                               const FPRegister& fn,
+                               FPDataProcessing1SourceOp op);
+  void FPDataProcessing2Source(const FPRegister& fd,
+                               const FPRegister& fn,
+                               const FPRegister& fm,
+                               FPDataProcessing2SourceOp op);
+  void FPDataProcessing3Source(const FPRegister& fd,
+                               const FPRegister& fn,
+                               const FPRegister& fm,
+                               const FPRegister& fa,
+                               FPDataProcessing3SourceOp op);
+
+  // Encoding helpers.
+  static bool IsImmFP32(float imm);
+  static bool IsImmFP64(double imm);
+
+  void RecordLiteral(int64_t imm, unsigned size);
+
+  // Emit the instruction at pc_.
+  void Emit(Instr instruction) {
+    ASSERT(sizeof(*pc_) == 1);
+    ASSERT(sizeof(instruction) == kInstructionSize);
+    ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_));
+
+#ifdef DEBUG
+    finalized_ = false;
+#endif
+
+    memcpy(pc_, &instruction, sizeof(instruction));
+    pc_ += sizeof(instruction);
+    CheckBufferSpace();
+  }
+
+  // Emit data inline in the instruction stream.
+  void EmitData(void const * data, unsigned size) {
+    ASSERT(sizeof(*pc_) == 1);
+    ASSERT((pc_ + size) <= (buffer_ + buffer_size_));
+
+#ifdef DEBUG
+    finalized_ = false;
+#endif
+
+    // TODO: Record this 'instruction' as data, so that it can be disassembled
+    // correctly.
+    memcpy(pc_, data, size);
+    pc_ += size;
+    CheckBufferSpace();
+  }
+
+  inline void CheckBufferSpace() {
+    ASSERT(pc_ < (buffer_ + buffer_size_));
+    if (pc_ > next_literal_pool_check_) {
+      CheckLiteralPool();
+    }
+  }
+
+  // The buffer into which code and relocation info are generated.
+  Instruction* buffer_;
+  // Buffer size, in bytes.
+  unsigned buffer_size_;
+  Instruction* pc_;
+  std::list<Literal*> literals_;
+  Instruction* next_literal_pool_check_;
+  unsigned literal_pool_monitor_;
+
+  friend class BlockLiteralPoolScope;
+
+#ifdef DEBUG
+  bool finalized_;
+#endif
+};
+
+class BlockLiteralPoolScope {
+ public:
+  explicit BlockLiteralPoolScope(Assembler* assm) : assm_(assm) {
+    assm_->BlockLiteralPool();
+  }
+
+  ~BlockLiteralPoolScope() {
+    assm_->ReleaseLiteralPool();
+  }
+
+ private:
+  Assembler* assm_;
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_ASSEMBLER_A64_H_
diff --git a/disas/libvixl/src/a64/constants-a64.h b/disas/libvixl/src/a64/constants-a64.h
new file mode 100644
index 0000000..2e0336d
--- /dev/null
+++ b/disas/libvixl/src/a64/constants-a64.h
@@ -0,0 +1,1104 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_CONSTANTS_A64_H_
+#define VIXL_A64_CONSTANTS_A64_H_
+
+namespace vixl {
+
+const unsigned kNumberOfRegisters = 32;
+const unsigned kNumberOfFPRegisters = 32;
+// Callee saved registers are x21-x30(lr).
+const int kNumberOfCalleeSavedRegisters = 10;
+const int kFirstCalleeSavedRegisterIndex = 21;
+// Callee saved FP registers are d8-d15.
+const int kNumberOfCalleeSavedFPRegisters = 8;
+const int kFirstCalleeSavedFPRegisterIndex = 8;
+
+#define REGISTER_CODE_LIST(R)                                                  \
+R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
+R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
+R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
+R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
+#define INSTRUCTION_FIELDS_LIST(V_)                                            \
+/* Register fields */                                                          \
+V_(Rd, 4, 0, Bits)                        /* Destination register.     */      \
+V_(Rn, 9, 5, Bits)                        /* First source register.    */      \
+V_(Rm, 20, 16, Bits)                      /* Second source register.   */      \
+V_(Ra, 14, 10, Bits)                      /* Third source register.    */      \
+V_(Rt, 4, 0, Bits)                        /* Load dest / store source. */      \
+V_(Rt2, 14, 10, Bits)                     /* Load second dest /        */      \
+                                         /* store second source.      */       \
+V_(PrefetchMode, 4, 0, Bits)                                                   \
+                                                                               \
+/* Common bits */                                                              \
+V_(SixtyFourBits, 31, 31, Bits)                                                \
+V_(FlagsUpdate, 29, 29, Bits)                                                  \
+                                                                               \
+/* PC relative addressing */                                                   \
+V_(ImmPCRelHi, 23, 5, SignedBits)                                              \
+V_(ImmPCRelLo, 30, 29, Bits)                                                   \
+                                                                               \
+/* Add/subtract/logical shift register */                                      \
+V_(ShiftDP, 23, 22, Bits)                                                      \
+V_(ImmDPShift, 15, 10, Bits)                                                   \
+                                                                               \
+/* Add/subtract immediate */                                                   \
+V_(ImmAddSub, 21, 10, Bits)                                                    \
+V_(ShiftAddSub, 23, 22, Bits)                                                  \
+                                                                               \
+/* Add/substract extend */                                                     \
+V_(ImmExtendShift, 12, 10, Bits)                                               \
+V_(ExtendMode, 15, 13, Bits)                                                   \
+                                                                               \
+/* Move wide */                                                                \
+V_(ImmMoveWide, 20, 5, Bits)                                                   \
+V_(ShiftMoveWide, 22, 21, Bits)                                                \
+                                                                               \
+/* Logical immediate, bitfield and extract */                                  \
+V_(BitN, 22, 22, Bits)                                                         \
+V_(ImmRotate, 21, 16, Bits)                                                    \
+V_(ImmSetBits, 15, 10, Bits)                                                   \
+V_(ImmR, 21, 16, Bits)                                                         \
+V_(ImmS, 15, 10, Bits)                                                         \
+                                                                               \
+/* Test and branch immediate */                                                \
+V_(ImmTestBranch, 18, 5, SignedBits)                                           \
+V_(ImmTestBranchBit40, 23, 19, Bits)                                           \
+V_(ImmTestBranchBit5, 31, 31, Bits)                                            \
+                                                                               \
+/* Conditionals */                                                             \
+V_(Condition, 15, 12, Bits)                                                    \
+V_(ConditionBranch, 3, 0, Bits)                                                \
+V_(Nzcv, 3, 0, Bits)                                                           \
+V_(ImmCondCmp, 20, 16, Bits)                                                   \
+V_(ImmCondBranch, 23, 5, SignedBits)                                           \
+                                                                               \
+/* Floating point */                                                           \
+V_(FPType, 23, 22, Bits)                                                       \
+V_(ImmFP, 20, 13, Bits)                                                        \
+V_(FPScale, 15, 10, Bits)                                                      \
+                                                                               \
+/* Load Store */                                                               \
+V_(ImmLS, 20, 12, SignedBits)                                                  \
+V_(ImmLSUnsigned, 21, 10, Bits)                                                \
+V_(ImmLSPair, 21, 15, SignedBits)                                              \
+V_(SizeLS, 31, 30, Bits)                                                       \
+V_(ImmShiftLS, 12, 12, Bits)                                                   \
+                                                                               \
+/* Other immediates */                                                         \
+V_(ImmUncondBranch, 25, 0, SignedBits)                                         \
+V_(ImmCmpBranch, 23, 5, SignedBits)                                            \
+V_(ImmLLiteral, 23, 5, SignedBits)                                             \
+V_(ImmException, 20, 5, Bits)                                                  \
+V_(ImmHint, 11, 5, Bits)                                                       \
+                                                                               \
+/* System (MRS, MSR) */                                                        \
+V_(ImmSystemRegister, 19, 5, Bits)                                             \
+V_(SysO0, 19, 19, Bits)                                                        \
+V_(SysOp1, 18, 16, Bits)                                                       \
+V_(SysOp2, 7, 5, Bits)                                                         \
+V_(CRn, 15, 12, Bits)                                                          \
+V_(CRm, 11, 8, Bits)                                                           \
+
+
+#define SYSTEM_REGISTER_FIELDS_LIST(V_, M_)                                    \
+/* NZCV */                                                                     \
+V_(Flags, 31, 28, Bits)                                                        \
+V_(N, 31, 31, Bits)                                                            \
+V_(Z, 30, 30, Bits)                                                            \
+V_(C, 29, 29, Bits)                                                            \
+V_(V, 28, 28, Bits)                                                            \
+M_(NZCV, Flags_mask)                                                           \
+                                                                               \
+/* FPCR */                                                                     \
+V_(AHP, 26, 26, Bits)                                                          \
+V_(DN, 25, 25, Bits)                                                           \
+V_(FZ, 24, 24, Bits)                                                           \
+V_(RMode, 23, 22, Bits)                                                        \
+M_(FPCR, AHP_mask | DN_mask | FZ_mask | RMode_mask)
+
+
+// Fields offsets.
+#define DECLARE_FIELDS_OFFSETS(Name, HighBit, LowBit, X)                       \
+const int Name##_offset = LowBit;                                              \
+const int Name##_width = HighBit - LowBit + 1;                                 \
+const uint32_t Name##_mask = ((1 << Name##_width) - 1) << LowBit;
+#define NOTHING(A, B)
+INSTRUCTION_FIELDS_LIST(DECLARE_FIELDS_OFFSETS)
+SYSTEM_REGISTER_FIELDS_LIST(DECLARE_FIELDS_OFFSETS, NOTHING)
+#undef NOTHING
+#undef DECLARE_FIELDS_BITS
+
+// ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), formed
+// from ImmPCRelLo and ImmPCRelHi.
+const int ImmPCRel_mask = ImmPCRelLo_mask | ImmPCRelHi_mask;
+
+// Condition codes.
+enum Condition {
+  eq = 0,
+  ne = 1,
+  hs = 2,
+  lo = 3,
+  mi = 4,
+  pl = 5,
+  vs = 6,
+  vc = 7,
+  hi = 8,
+  ls = 9,
+  ge = 10,
+  lt = 11,
+  gt = 12,
+  le = 13,
+  al = 14,
+  nv = 15  // Behaves as always/al.
+};
+
+inline Condition InvertCondition(Condition cond) {
+  // Conditions al and nv behave identically, as "always true". They can't be
+  // inverted, because there is no "always false" condition.
+  ASSERT((cond != al) && (cond != nv));
+  return static_cast<Condition>(cond ^ 1);
+}
+
+enum FlagsUpdate {
+  SetFlags   = 1,
+  LeaveFlags = 0
+};
+
+enum StatusFlags {
+  NoFlag    = 0,
+
+  // Derive the flag combinations from the system register bit descriptions.
+  NFlag     = N_mask,
+  ZFlag     = Z_mask,
+  CFlag     = C_mask,
+  VFlag     = V_mask,
+  NZFlag    = NFlag | ZFlag,
+  NCFlag    = NFlag | CFlag,
+  NVFlag    = NFlag | VFlag,
+  ZCFlag    = ZFlag | CFlag,
+  ZVFlag    = ZFlag | VFlag,
+  CVFlag    = CFlag | VFlag,
+  NZCFlag   = NFlag | ZFlag | CFlag,
+  NZVFlag   = NFlag | ZFlag | VFlag,
+  NCVFlag   = NFlag | CFlag | VFlag,
+  ZCVFlag   = ZFlag | CFlag | VFlag,
+  NZCVFlag  = NFlag | ZFlag | CFlag | VFlag,
+
+  // Floating-point comparison results.
+  FPEqualFlag       = ZCFlag,
+  FPLessThanFlag    = NFlag,
+  FPGreaterThanFlag = CFlag,
+  FPUnorderedFlag   = CVFlag
+};
+
+enum Shift {
+  NO_SHIFT = -1,
+  LSL = 0x0,
+  LSR = 0x1,
+  ASR = 0x2,
+  ROR = 0x3
+};
+
+enum Extend {
+  NO_EXTEND = -1,
+  UXTB      = 0,
+  UXTH      = 1,
+  UXTW      = 2,
+  UXTX      = 3,
+  SXTB      = 4,
+  SXTH      = 5,
+  SXTW      = 6,
+  SXTX      = 7
+};
+
+enum SystemHint {
+  NOP   = 0,
+  YIELD = 1,
+  WFE   = 2,
+  WFI   = 3,
+  SEV   = 4,
+  SEVL  = 5
+};
+
+// System/special register names.
+// This information is not encoded as one field but as the concatenation of
+// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
+enum SystemRegister {
+  NZCV = ((0x1 << SysO0_offset) |
+          (0x3 << SysOp1_offset) |
+          (0x4 << CRn_offset) |
+          (0x2 << CRm_offset) |
+          (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset,
+  FPCR = ((0x1 << SysO0_offset) |
+          (0x3 << SysOp1_offset) |
+          (0x4 << CRn_offset) |
+          (0x4 << CRm_offset) |
+          (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset
+};
+
+// Instruction enumerations.
+//
+// These are the masks that define a class of instructions, and the list of
+// instructions within each class. Each enumeration has a Fixed, FMask and
+// Mask value.
+//
+// Fixed: The fixed bits in this instruction class.
+// FMask: The mask used to extract the fixed bits in the class.
+// Mask:  The mask used to identify the instructions within a class.
+//
+// The enumerations can be used like this:
+//
+// ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed);
+// switch(instr->Mask(PCRelAddressingMask)) {
+//   case ADR:  Format("adr 'Xd, 'AddrPCRelByte"); break;
+//   case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break;
+//   default:   printf("Unknown instruction\n");
+// }
+
+
+// Generic fields.
+enum GenericInstrField {
+  SixtyFourBits        = 0x80000000,
+  ThirtyTwoBits        = 0x00000000,
+  FP32                 = 0x00000000,
+  FP64                 = 0x00400000
+};
+
+// PC relative addressing.
+enum PCRelAddressingOp {
+  PCRelAddressingFixed = 0x10000000,
+  PCRelAddressingFMask = 0x1F000000,
+  PCRelAddressingMask  = 0x9F000000,
+  ADR                  = PCRelAddressingFixed | 0x00000000,
+  ADRP                 = PCRelAddressingFixed | 0x80000000
+};
+
+// Add/sub (immediate, shifted and extended.)
+const int kSFOffset = 31;
+enum AddSubOp {
+  AddSubOpMask      = 0x60000000,
+  AddSubSetFlagsBit = 0x20000000,
+  ADD               = 0x00000000,
+  ADDS              = ADD | AddSubSetFlagsBit,
+  SUB               = 0x40000000,
+  SUBS              = SUB | AddSubSetFlagsBit
+};
+
+#define ADD_SUB_OP_LIST(V)  \
+  V(ADD),                   \
+  V(ADDS),                  \
+  V(SUB),                   \
+  V(SUBS)
+
+enum AddSubImmediateOp {
+  AddSubImmediateFixed = 0x11000000,
+  AddSubImmediateFMask = 0x1F000000,
+  AddSubImmediateMask  = 0xFF000000,
+  #define ADD_SUB_IMMEDIATE(A)           \
+  A##_w_imm = AddSubImmediateFixed | A,  \
+  A##_x_imm = AddSubImmediateFixed | A | SixtyFourBits
+  ADD_SUB_OP_LIST(ADD_SUB_IMMEDIATE)
+  #undef ADD_SUB_IMMEDIATE
+};
+
+enum AddSubShiftedOp {
+  AddSubShiftedFixed   = 0x0B000000,
+  AddSubShiftedFMask   = 0x1F200000,
+  AddSubShiftedMask    = 0xFF200000,
+  #define ADD_SUB_SHIFTED(A)             \
+  A##_w_shift = AddSubShiftedFixed | A,  \
+  A##_x_shift = AddSubShiftedFixed | A | SixtyFourBits
+  ADD_SUB_OP_LIST(ADD_SUB_SHIFTED)
+  #undef ADD_SUB_SHIFTED
+};
+
+enum AddSubExtendedOp {
+  AddSubExtendedFixed  = 0x0B200000,
+  AddSubExtendedFMask  = 0x1F200000,
+  AddSubExtendedMask   = 0xFFE00000,
+  #define ADD_SUB_EXTENDED(A)           \
+  A##_w_ext = AddSubExtendedFixed | A,  \
+  A##_x_ext = AddSubExtendedFixed | A | SixtyFourBits
+  ADD_SUB_OP_LIST(ADD_SUB_EXTENDED)
+  #undef ADD_SUB_EXTENDED
+};
+
+// Add/sub with carry.
+enum AddSubWithCarryOp {
+  AddSubWithCarryFixed = 0x1A000000,
+  AddSubWithCarryFMask = 0x1FE00000,
+  AddSubWithCarryMask  = 0xFFE0FC00,
+  ADC_w                = AddSubWithCarryFixed | ADD,
+  ADC_x                = AddSubWithCarryFixed | ADD | SixtyFourBits,
+  ADC                  = ADC_w,
+  ADCS_w               = AddSubWithCarryFixed | ADDS,
+  ADCS_x               = AddSubWithCarryFixed | ADDS | SixtyFourBits,
+  SBC_w                = AddSubWithCarryFixed | SUB,
+  SBC_x                = AddSubWithCarryFixed | SUB | SixtyFourBits,
+  SBC                  = SBC_w,
+  SBCS_w               = AddSubWithCarryFixed | SUBS,
+  SBCS_x               = AddSubWithCarryFixed | SUBS | SixtyFourBits
+};
+
+
+// Logical (immediate and shifted register).
+enum LogicalOp {
+  LogicalOpMask = 0x60200000,
+  NOT   = 0x00200000,
+  AND   = 0x00000000,
+  BIC   = AND | NOT,
+  ORR   = 0x20000000,
+  ORN   = ORR | NOT,
+  EOR   = 0x40000000,
+  EON   = EOR | NOT,
+  ANDS  = 0x60000000,
+  BICS  = ANDS | NOT
+};
+
+// Logical immediate.
+enum LogicalImmediateOp {
+  LogicalImmediateFixed = 0x12000000,
+  LogicalImmediateFMask = 0x1F800000,
+  LogicalImmediateMask  = 0xFF800000,
+  AND_w_imm   = LogicalImmediateFixed | AND,
+  AND_x_imm   = LogicalImmediateFixed | AND | SixtyFourBits,
+  ORR_w_imm   = LogicalImmediateFixed | ORR,
+  ORR_x_imm   = LogicalImmediateFixed | ORR | SixtyFourBits,
+  EOR_w_imm   = LogicalImmediateFixed | EOR,
+  EOR_x_imm   = LogicalImmediateFixed | EOR | SixtyFourBits,
+  ANDS_w_imm  = LogicalImmediateFixed | ANDS,
+  ANDS_x_imm  = LogicalImmediateFixed | ANDS | SixtyFourBits
+};
+
+// Logical shifted register.
+enum LogicalShiftedOp {
+  LogicalShiftedFixed = 0x0A000000,
+  LogicalShiftedFMask = 0x1F000000,
+  LogicalShiftedMask  = 0xFF200000,
+  AND_w               = LogicalShiftedFixed | AND,
+  AND_x               = LogicalShiftedFixed | AND | SixtyFourBits,
+  AND_shift           = AND_w,
+  BIC_w               = LogicalShiftedFixed | BIC,
+  BIC_x               = LogicalShiftedFixed | BIC | SixtyFourBits,
+  BIC_shift           = BIC_w,
+  ORR_w               = LogicalShiftedFixed | ORR,
+  ORR_x               = LogicalShiftedFixed | ORR | SixtyFourBits,
+  ORR_shift           = ORR_w,
+  ORN_w               = LogicalShiftedFixed | ORN,
+  ORN_x               = LogicalShiftedFixed | ORN | SixtyFourBits,
+  ORN_shift           = ORN_w,
+  EOR_w               = LogicalShiftedFixed | EOR,
+  EOR_x               = LogicalShiftedFixed | EOR | SixtyFourBits,
+  EOR_shift           = EOR_w,
+  EON_w               = LogicalShiftedFixed | EON,
+  EON_x               = LogicalShiftedFixed | EON | SixtyFourBits,
+  EON_shift           = EON_w,
+  ANDS_w              = LogicalShiftedFixed | ANDS,
+  ANDS_x              = LogicalShiftedFixed | ANDS | SixtyFourBits,
+  ANDS_shift          = ANDS_w,
+  BICS_w              = LogicalShiftedFixed | BICS,
+  BICS_x              = LogicalShiftedFixed | BICS | SixtyFourBits,
+  BICS_shift          = BICS_w
+};
+
+// Move wide immediate.
+enum MoveWideImmediateOp {
+  MoveWideImmediateFixed = 0x12800000,
+  MoveWideImmediateFMask = 0x1F800000,
+  MoveWideImmediateMask  = 0xFF800000,
+  MOVN                   = 0x00000000,
+  MOVZ                   = 0x40000000,
+  MOVK                   = 0x60000000,
+  MOVN_w                 = MoveWideImmediateFixed | MOVN,
+  MOVN_x                 = MoveWideImmediateFixed | MOVN | SixtyFourBits,
+  MOVZ_w                 = MoveWideImmediateFixed | MOVZ,
+  MOVZ_x                 = MoveWideImmediateFixed | MOVZ | SixtyFourBits,
+  MOVK_w                 = MoveWideImmediateFixed | MOVK,
+  MOVK_x                 = MoveWideImmediateFixed | MOVK | SixtyFourBits
+};
+
+// Bitfield.
+const int kBitfieldNOffset = 22;
+enum BitfieldOp {
+  BitfieldFixed = 0x13000000,
+  BitfieldFMask = 0x1F800000,
+  BitfieldMask  = 0xFF800000,
+  SBFM_w        = BitfieldFixed | 0x00000000,
+  SBFM_x        = BitfieldFixed | 0x80000000,
+  SBFM          = SBFM_w,
+  BFM_w         = BitfieldFixed | 0x20000000,
+  BFM_x         = BitfieldFixed | 0xA0000000,
+  BFM           = BFM_w,
+  UBFM_w        = BitfieldFixed | 0x40000000,
+  UBFM_x        = BitfieldFixed | 0xC0000000,
+  UBFM          = UBFM_w
+  // Bitfield N field.
+};
+
+// Extract.
+enum ExtractOp {
+  ExtractFixed = 0x13800000,
+  ExtractFMask = 0x1F800000,
+  ExtractMask  = 0xFFA00000,
+  EXTR_w       = ExtractFixed | 0x00000000,
+  EXTR_x       = ExtractFixed | 0x80000000,
+  EXTR         = EXTR_w
+};
+
+// Unconditional branch.
+enum UnconditionalBranchOp {
+  UnconditionalBranchFixed = 0x14000000,
+  UnconditionalBranchFMask = 0x7C000000,
+  UnconditionalBranchMask  = 0xFC000000,
+  B                        = UnconditionalBranchFixed | 0x00000000,
+  BL                       = UnconditionalBranchFixed | 0x80000000
+};
+
+// Unconditional branch to register.
+enum UnconditionalBranchToRegisterOp {
+  UnconditionalBranchToRegisterFixed = 0xD6000000,
+  UnconditionalBranchToRegisterFMask = 0xFE000000,
+  UnconditionalBranchToRegisterMask  = 0xFFFFFC1F,
+  BR      = UnconditionalBranchToRegisterFixed | 0x001F0000,
+  BLR     = UnconditionalBranchToRegisterFixed | 0x003F0000,
+  RET     = UnconditionalBranchToRegisterFixed | 0x005F0000
+};
+
+// Compare and branch.
+enum CompareBranchOp {
+  CompareBranchFixed = 0x34000000,
+  CompareBranchFMask = 0x7E000000,
+  CompareBranchMask  = 0xFF000000,
+  CBZ_w              = CompareBranchFixed | 0x00000000,
+  CBZ_x              = CompareBranchFixed | 0x80000000,
+  CBZ                = CBZ_w,
+  CBNZ_w             = CompareBranchFixed | 0x01000000,
+  CBNZ_x             = CompareBranchFixed | 0x81000000,
+  CBNZ               = CBNZ_w
+};
+
+// Test and branch.
+enum TestBranchOp {
+  TestBranchFixed = 0x36000000,
+  TestBranchFMask = 0x7E000000,
+  TestBranchMask  = 0x7F000000,
+  TBZ             = TestBranchFixed | 0x00000000,
+  TBNZ            = TestBranchFixed | 0x01000000
+};
+
+// Conditional branch.
+enum ConditionalBranchOp {
+  ConditionalBranchFixed = 0x54000000,
+  ConditionalBranchFMask = 0xFE000000,
+  ConditionalBranchMask  = 0xFF000010,
+  B_cond                 = ConditionalBranchFixed | 0x00000000
+};
+
+// System.
+// System instruction encoding is complicated because some instructions use op
+// and CR fields to encode parameters. To handle this cleanly, the system
+// instructions are split into more than one enum.
+
+enum SystemOp {
+  SystemFixed = 0xD5000000,
+  SystemFMask = 0xFFC00000
+};
+
+enum SystemSysRegOp {
+  SystemSysRegFixed = 0xD5100000,
+  SystemSysRegFMask = 0xFFD00000,
+  SystemSysRegMask  = 0xFFF00000,
+  MRS               = SystemSysRegFixed | 0x00200000,
+  MSR               = SystemSysRegFixed | 0x00000000
+};
+
+enum SystemHintOp {
+  SystemHintFixed = 0xD503201F,
+  SystemHintFMask = 0xFFFFF01F,
+  SystemHintMask  = 0xFFFFF01F,
+  HINT            = SystemHintFixed | 0x00000000
+};
+
+// Exception.
+enum ExceptionOp {
+  ExceptionFixed = 0xD4000000,
+  ExceptionFMask = 0xFF000000,
+  ExceptionMask  = 0xFFE0001F,
+  HLT            = ExceptionFixed | 0x00400000,
+  BRK            = ExceptionFixed | 0x00200000,
+  SVC            = ExceptionFixed | 0x00000001,
+  HVC            = ExceptionFixed | 0x00000002,
+  SMC            = ExceptionFixed | 0x00000003,
+  DCPS1          = ExceptionFixed | 0x00A00001,
+  DCPS2          = ExceptionFixed | 0x00A00002,
+  DCPS3          = ExceptionFixed | 0x00A00003
+};
+
+// Any load or store.
+enum LoadStoreAnyOp {
+  LoadStoreAnyFMask = 0x0a000000,
+  LoadStoreAnyFixed = 0x08000000
+};
+
+#define LOAD_STORE_PAIR_OP_LIST(V)  \
+  V(STP, w,   0x00000000),          \
+  V(LDP, w,   0x00400000),          \
+  V(LDPSW, x, 0x40400000),          \
+  V(STP, x,   0x80000000),          \
+  V(LDP, x,   0x80400000),          \
+  V(STP, s,   0x04000000),          \
+  V(LDP, s,   0x04400000),          \
+  V(STP, d,   0x44000000),          \
+  V(LDP, d,   0x44400000)
+
+// Load/store pair (post, pre and offset.)
+enum LoadStorePairOp {
+  LoadStorePairMask = 0xC4400000,
+  LoadStorePairLBit = 1 << 22,
+  #define LOAD_STORE_PAIR(A, B, C) \
+  A##_##B = C
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR)
+  #undef LOAD_STORE_PAIR
+};
+
+enum LoadStorePairPostIndexOp {
+  LoadStorePairPostIndexFixed = 0x28800000,
+  LoadStorePairPostIndexFMask = 0x3B800000,
+  LoadStorePairPostIndexMask  = 0xFFC00000,
+  #define LOAD_STORE_PAIR_POST_INDEX(A, B, C)  \
+  A##_##B##_post = LoadStorePairPostIndexFixed | A##_##B
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_POST_INDEX)
+  #undef LOAD_STORE_PAIR_POST_INDEX
+};
+
+enum LoadStorePairPreIndexOp {
+  LoadStorePairPreIndexFixed = 0x29800000,
+  LoadStorePairPreIndexFMask = 0x3B800000,
+  LoadStorePairPreIndexMask  = 0xFFC00000,
+  #define LOAD_STORE_PAIR_PRE_INDEX(A, B, C)  \
+  A##_##B##_pre = LoadStorePairPreIndexFixed | A##_##B
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_PRE_INDEX)
+  #undef LOAD_STORE_PAIR_PRE_INDEX
+};
+
+enum LoadStorePairOffsetOp {
+  LoadStorePairOffsetFixed = 0x29000000,
+  LoadStorePairOffsetFMask = 0x3B800000,
+  LoadStorePairOffsetMask  = 0xFFC00000,
+  #define LOAD_STORE_PAIR_OFFSET(A, B, C)  \
+  A##_##B##_off = LoadStorePairOffsetFixed | A##_##B
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_OFFSET)
+  #undef LOAD_STORE_PAIR_OFFSET
+};
+
+enum LoadStorePairNonTemporalOp {
+  LoadStorePairNonTemporalFixed = 0x28000000,
+  LoadStorePairNonTemporalFMask = 0x3B800000,
+  LoadStorePairNonTemporalMask  = 0xFFC00000,
+  STNP_w = LoadStorePairNonTemporalFixed | STP_w,
+  LDNP_w = LoadStorePairNonTemporalFixed | LDP_w,
+  STNP_x = LoadStorePairNonTemporalFixed | STP_x,
+  LDNP_x = LoadStorePairNonTemporalFixed | LDP_x,
+  STNP_s = LoadStorePairNonTemporalFixed | STP_s,
+  LDNP_s = LoadStorePairNonTemporalFixed | LDP_s,
+  STNP_d = LoadStorePairNonTemporalFixed | STP_d,
+  LDNP_d = LoadStorePairNonTemporalFixed | LDP_d
+};
+
+// Load literal.
+enum LoadLiteralOp {
+  LoadLiteralFixed = 0x18000000,
+  LoadLiteralFMask = 0x3B000000,
+  LoadLiteralMask  = 0xFF000000,
+  LDR_w_lit        = LoadLiteralFixed | 0x00000000,
+  LDR_x_lit        = LoadLiteralFixed | 0x40000000,
+  LDRSW_x_lit      = LoadLiteralFixed | 0x80000000,
+  PRFM_lit         = LoadLiteralFixed | 0xC0000000,
+  LDR_s_lit        = LoadLiteralFixed | 0x04000000,
+  LDR_d_lit        = LoadLiteralFixed | 0x44000000
+};
+
+#define LOAD_STORE_OP_LIST(V)     \
+  V(ST, RB, w,  0x00000000),  \
+  V(ST, RH, w,  0x40000000),  \
+  V(ST, R, w,   0x80000000),  \
+  V(ST, R, x,   0xC0000000),  \
+  V(LD, RB, w,  0x00400000),  \
+  V(LD, RH, w,  0x40400000),  \
+  V(LD, R, w,   0x80400000),  \
+  V(LD, R, x,   0xC0400000),  \
+  V(LD, RSB, x, 0x00800000),  \
+  V(LD, RSH, x, 0x40800000),  \
+  V(LD, RSW, x, 0x80800000),  \
+  V(LD, RSB, w, 0x00C00000),  \
+  V(LD, RSH, w, 0x40C00000),  \
+  V(ST, R, s,   0x84000000),  \
+  V(ST, R, d,   0xC4000000),  \
+  V(LD, R, s,   0x84400000),  \
+  V(LD, R, d,   0xC4400000)
+
+
+// Load/store unscaled offset.
+enum LoadStoreUnscaledOffsetOp {
+  LoadStoreUnscaledOffsetFixed = 0x38000000,
+  LoadStoreUnscaledOffsetFMask = 0x3B200C00,
+  LoadStoreUnscaledOffsetMask  = 0xFFE00C00,
+  #define LOAD_STORE_UNSCALED(A, B, C, D)  \
+  A##U##B##_##C = LoadStoreUnscaledOffsetFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_UNSCALED)
+  #undef LOAD_STORE_UNSCALED
+};
+
+// Load/store (post, pre, offset and unsigned.)
+enum LoadStoreOp {
+  LoadStoreOpMask   = 0xC4C00000,
+  #define LOAD_STORE(A, B, C, D)  \
+  A##B##_##C = D
+  LOAD_STORE_OP_LIST(LOAD_STORE),
+  #undef LOAD_STORE
+  PRFM = 0xC0800000
+};
+
+// Load/store post index.
+enum LoadStorePostIndex {
+  LoadStorePostIndexFixed = 0x38000400,
+  LoadStorePostIndexFMask = 0x3B200C00,
+  LoadStorePostIndexMask  = 0xFFE00C00,
+  #define LOAD_STORE_POST_INDEX(A, B, C, D)  \
+  A##B##_##C##_post = LoadStorePostIndexFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_POST_INDEX)
+  #undef LOAD_STORE_POST_INDEX
+};
+
+// Load/store pre index.
+enum LoadStorePreIndex {
+  LoadStorePreIndexFixed = 0x38000C00,
+  LoadStorePreIndexFMask = 0x3B200C00,
+  LoadStorePreIndexMask  = 0xFFE00C00,
+  #define LOAD_STORE_PRE_INDEX(A, B, C, D)  \
+  A##B##_##C##_pre = LoadStorePreIndexFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_PRE_INDEX)
+  #undef LOAD_STORE_PRE_INDEX
+};
+
+// Load/store unsigned offset.
+enum LoadStoreUnsignedOffset {
+  LoadStoreUnsignedOffsetFixed = 0x39000000,
+  LoadStoreUnsignedOffsetFMask = 0x3B000000,
+  LoadStoreUnsignedOffsetMask  = 0xFFC00000,
+  PRFM_unsigned                = LoadStoreUnsignedOffsetFixed | PRFM,
+  #define LOAD_STORE_UNSIGNED_OFFSET(A, B, C, D) \
+  A##B##_##C##_unsigned = LoadStoreUnsignedOffsetFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_UNSIGNED_OFFSET)
+  #undef LOAD_STORE_UNSIGNED_OFFSET
+};
+
+// Load/store register offset.
+enum LoadStoreRegisterOffset {
+  LoadStoreRegisterOffsetFixed = 0x38200800,
+  LoadStoreRegisterOffsetFMask = 0x3B200C00,
+  LoadStoreRegisterOffsetMask  = 0xFFE00C00,
+  PRFM_reg                     = LoadStoreRegisterOffsetFixed | PRFM,
+  #define LOAD_STORE_REGISTER_OFFSET(A, B, C, D) \
+  A##B##_##C##_reg = LoadStoreRegisterOffsetFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_REGISTER_OFFSET)
+  #undef LOAD_STORE_REGISTER_OFFSET
+};
+
+// Conditional compare.
+enum ConditionalCompareOp {
+  ConditionalCompareMask = 0x60000000,
+  CCMN                   = 0x20000000,
+  CCMP                   = 0x60000000
+};
+
+// Conditional compare register.
+enum ConditionalCompareRegisterOp {
+  ConditionalCompareRegisterFixed = 0x1A400000,
+  ConditionalCompareRegisterFMask = 0x1FE00800,
+  ConditionalCompareRegisterMask  = 0xFFE00C10,
+  CCMN_w = ConditionalCompareRegisterFixed | CCMN,
+  CCMN_x = ConditionalCompareRegisterFixed | SixtyFourBits | CCMN,
+  CCMP_w = ConditionalCompareRegisterFixed | CCMP,
+  CCMP_x = ConditionalCompareRegisterFixed | SixtyFourBits | CCMP
+};
+
+// Conditional compare immediate.
+enum ConditionalCompareImmediateOp {
+  ConditionalCompareImmediateFixed = 0x1A400800,
+  ConditionalCompareImmediateFMask = 0x1FE00800,
+  ConditionalCompareImmediateMask  = 0xFFE00C10,
+  CCMN_w_imm = ConditionalCompareImmediateFixed | CCMN,
+  CCMN_x_imm = ConditionalCompareImmediateFixed | SixtyFourBits | CCMN,
+  CCMP_w_imm = ConditionalCompareImmediateFixed | CCMP,
+  CCMP_x_imm = ConditionalCompareImmediateFixed | SixtyFourBits | CCMP
+};
+
+// Conditional select.
+enum ConditionalSelectOp {
+  ConditionalSelectFixed = 0x1A800000,
+  ConditionalSelectFMask = 0x1FE00000,
+  ConditionalSelectMask  = 0xFFE00C00,
+  CSEL_w                 = ConditionalSelectFixed | 0x00000000,
+  CSEL_x                 = ConditionalSelectFixed | 0x80000000,
+  CSEL                   = CSEL_w,
+  CSINC_w                = ConditionalSelectFixed | 0x00000400,
+  CSINC_x                = ConditionalSelectFixed | 0x80000400,
+  CSINC                  = CSINC_w,
+  CSINV_w                = ConditionalSelectFixed | 0x40000000,
+  CSINV_x                = ConditionalSelectFixed | 0xC0000000,
+  CSINV                  = CSINV_w,
+  CSNEG_w                = ConditionalSelectFixed | 0x40000400,
+  CSNEG_x                = ConditionalSelectFixed | 0xC0000400,
+  CSNEG                  = CSNEG_w
+};
+
+// Data processing 1 source.
+enum DataProcessing1SourceOp {
+  DataProcessing1SourceFixed = 0x5AC00000,
+  DataProcessing1SourceFMask = 0x5FE00000,
+  DataProcessing1SourceMask  = 0xFFFFFC00,
+  RBIT    = DataProcessing1SourceFixed | 0x00000000,
+  RBIT_w  = RBIT,
+  RBIT_x  = RBIT | SixtyFourBits,
+  REV16   = DataProcessing1SourceFixed | 0x00000400,
+  REV16_w = REV16,
+  REV16_x = REV16 | SixtyFourBits,
+  REV     = DataProcessing1SourceFixed | 0x00000800,
+  REV_w   = REV,
+  REV32_x = REV | SixtyFourBits,
+  REV_x   = DataProcessing1SourceFixed | SixtyFourBits | 0x00000C00,
+  CLZ     = DataProcessing1SourceFixed | 0x00001000,
+  CLZ_w   = CLZ,
+  CLZ_x   = CLZ | SixtyFourBits,
+  CLS     = DataProcessing1SourceFixed | 0x00001400,
+  CLS_w   = CLS,
+  CLS_x   = CLS | SixtyFourBits
+};
+
+// Data processing 2 source.
+enum DataProcessing2SourceOp {
+  DataProcessing2SourceFixed = 0x1AC00000,
+  DataProcessing2SourceFMask = 0x5FE00000,
+  DataProcessing2SourceMask  = 0xFFE0FC00,
+  UDIV_w  = DataProcessing2SourceFixed | 0x00000800,
+  UDIV_x  = DataProcessing2SourceFixed | 0x80000800,
+  UDIV    = UDIV_w,
+  SDIV_w  = DataProcessing2SourceFixed | 0x00000C00,
+  SDIV_x  = DataProcessing2SourceFixed | 0x80000C00,
+  SDIV    = SDIV_w,
+  LSLV_w  = DataProcessing2SourceFixed | 0x00002000,
+  LSLV_x  = DataProcessing2SourceFixed | 0x80002000,
+  LSLV    = LSLV_w,
+  LSRV_w  = DataProcessing2SourceFixed | 0x00002400,
+  LSRV_x  = DataProcessing2SourceFixed | 0x80002400,
+  LSRV    = LSRV_w,
+  ASRV_w  = DataProcessing2SourceFixed | 0x00002800,
+  ASRV_x  = DataProcessing2SourceFixed | 0x80002800,
+  ASRV    = ASRV_w,
+  RORV_w  = DataProcessing2SourceFixed | 0x00002C00,
+  RORV_x  = DataProcessing2SourceFixed | 0x80002C00,
+  RORV    = RORV_w,
+  CRC32B  = DataProcessing2SourceFixed | 0x00004000,
+  CRC32H  = DataProcessing2SourceFixed | 0x00004400,
+  CRC32W  = DataProcessing2SourceFixed | 0x00004800,
+  CRC32X  = DataProcessing2SourceFixed | SixtyFourBits | 0x00004C00,
+  CRC32CB = DataProcessing2SourceFixed | 0x00005000,
+  CRC32CH = DataProcessing2SourceFixed | 0x00005400,
+  CRC32CW = DataProcessing2SourceFixed | 0x00005800,
+  CRC32CX = DataProcessing2SourceFixed | SixtyFourBits | 0x00005C00
+};
+
+// Data processing 3 source.
+enum DataProcessing3SourceOp {
+  DataProcessing3SourceFixed = 0x1B000000,
+  DataProcessing3SourceFMask = 0x1F000000,
+  DataProcessing3SourceMask  = 0xFFE08000,
+  MADD_w                     = DataProcessing3SourceFixed | 0x00000000,
+  MADD_x                     = DataProcessing3SourceFixed | 0x80000000,
+  MADD                       = MADD_w,
+  MSUB_w                     = DataProcessing3SourceFixed | 0x00008000,
+  MSUB_x                     = DataProcessing3SourceFixed | 0x80008000,
+  MSUB                       = MSUB_w,
+  SMADDL_x                   = DataProcessing3SourceFixed | 0x80200000,
+  SMSUBL_x                   = DataProcessing3SourceFixed | 0x80208000,
+  SMULH_x                    = DataProcessing3SourceFixed | 0x80400000,
+  UMADDL_x                   = DataProcessing3SourceFixed | 0x80A00000,
+  UMSUBL_x                   = DataProcessing3SourceFixed | 0x80A08000,
+  UMULH_x                    = DataProcessing3SourceFixed | 0x80C00000
+};
+
+// Floating point compare.
+enum FPCompareOp {
+  FPCompareFixed = 0x1E202000,
+  FPCompareFMask = 0x5F203C00,
+  FPCompareMask  = 0xFFE0FC1F,
+  FCMP_s         = FPCompareFixed | 0x00000000,
+  FCMP_d         = FPCompareFixed | FP64 | 0x00000000,
+  FCMP           = FCMP_s,
+  FCMP_s_zero    = FPCompareFixed | 0x00000008,
+  FCMP_d_zero    = FPCompareFixed | FP64 | 0x00000008,
+  FCMP_zero      = FCMP_s_zero,
+  FCMPE_s        = FPCompareFixed | 0x00000010,
+  FCMPE_d        = FPCompareFixed | FP64 | 0x00000010,
+  FCMPE_s_zero   = FPCompareFixed | 0x00000018,
+  FCMPE_d_zero   = FPCompareFixed | FP64 | 0x00000018
+};
+
+// Floating point conditional compare.
+enum FPConditionalCompareOp {
+  FPConditionalCompareFixed = 0x1E200400,
+  FPConditionalCompareFMask = 0x5F200C00,
+  FPConditionalCompareMask  = 0xFFE00C10,
+  FCCMP_s                   = FPConditionalCompareFixed | 0x00000000,
+  FCCMP_d                   = FPConditionalCompareFixed | FP64 | 0x00000000,
+  FCCMP                     = FCCMP_s,
+  FCCMPE_s                  = FPConditionalCompareFixed | 0x00000010,
+  FCCMPE_d                  = FPConditionalCompareFixed | FP64 | 0x00000010,
+  FCCMPE                    = FCCMPE_s
+};
+
+// Floating point conditional select.
+enum FPConditionalSelectOp {
+  FPConditionalSelectFixed = 0x1E200C00,
+  FPConditionalSelectFMask = 0x5F200C00,
+  FPConditionalSelectMask  = 0xFFE00C00,
+  FCSEL_s                  = FPConditionalSelectFixed | 0x00000000,
+  FCSEL_d                  = FPConditionalSelectFixed | FP64 | 0x00000000,
+  FCSEL                    = FCSEL_s
+};
+
+// Floating point immediate.
+enum FPImmediateOp {
+  FPImmediateFixed = 0x1E201000,
+  FPImmediateFMask = 0x5F201C00,
+  FPImmediateMask  = 0xFFE01C00,
+  FMOV_s_imm       = FPImmediateFixed | 0x00000000,
+  FMOV_d_imm       = FPImmediateFixed | FP64 | 0x00000000
+};
+
+// Floating point data processing 1 source.
+enum FPDataProcessing1SourceOp {
+  FPDataProcessing1SourceFixed = 0x1E204000,
+  FPDataProcessing1SourceFMask = 0x5F207C00,
+  FPDataProcessing1SourceMask  = 0xFFFFFC00,
+  FMOV_s   = FPDataProcessing1SourceFixed | 0x00000000,
+  FMOV_d   = FPDataProcessing1SourceFixed | FP64 | 0x00000000,
+  FMOV     = FMOV_s,
+  FABS_s   = FPDataProcessing1SourceFixed | 0x00008000,
+  FABS_d   = FPDataProcessing1SourceFixed | FP64 | 0x00008000,
+  FABS     = FABS_s,
+  FNEG_s   = FPDataProcessing1SourceFixed | 0x00010000,
+  FNEG_d   = FPDataProcessing1SourceFixed | FP64 | 0x00010000,
+  FNEG     = FNEG_s,
+  FSQRT_s  = FPDataProcessing1SourceFixed | 0x00018000,
+  FSQRT_d  = FPDataProcessing1SourceFixed | FP64 | 0x00018000,
+  FSQRT    = FSQRT_s,
+  FCVT_ds  = FPDataProcessing1SourceFixed | 0x00028000,
+  FCVT_sd  = FPDataProcessing1SourceFixed | FP64 | 0x00020000,
+  FRINTN_s = FPDataProcessing1SourceFixed | 0x00040000,
+  FRINTN_d = FPDataProcessing1SourceFixed | FP64 | 0x00040000,
+  FRINTN   = FRINTN_s,
+  FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000,
+  FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000,
+  FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000,
+  FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000,
+  FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000,
+  FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000,
+  FRINTZ   = FRINTZ_s,
+  FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000,
+  FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000,
+  FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000,
+  FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000,
+  FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000,
+  FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000
+};
+
+// Floating point data processing 2 source.
+enum FPDataProcessing2SourceOp {
+  FPDataProcessing2SourceFixed = 0x1E200800,
+  FPDataProcessing2SourceFMask = 0x5F200C00,
+  FPDataProcessing2SourceMask  = 0xFFE0FC00,
+  FMUL     = FPDataProcessing2SourceFixed | 0x00000000,
+  FMUL_s   = FMUL,
+  FMUL_d   = FMUL | FP64,
+  FDIV     = FPDataProcessing2SourceFixed | 0x00001000,
+  FDIV_s   = FDIV,
+  FDIV_d   = FDIV | FP64,
+  FADD     = FPDataProcessing2SourceFixed | 0x00002000,
+  FADD_s   = FADD,
+  FADD_d   = FADD | FP64,
+  FSUB     = FPDataProcessing2SourceFixed | 0x00003000,
+  FSUB_s   = FSUB,
+  FSUB_d   = FSUB | FP64,
+  FMAX     = FPDataProcessing2SourceFixed | 0x00004000,
+  FMAX_s   = FMAX,
+  FMAX_d   = FMAX | FP64,
+  FMIN     = FPDataProcessing2SourceFixed | 0x00005000,
+  FMIN_s   = FMIN,
+  FMIN_d   = FMIN | FP64,
+  FMAXNM   = FPDataProcessing2SourceFixed | 0x00006000,
+  FMAXNM_s = FMAXNM,
+  FMAXNM_d = FMAXNM | FP64,
+  FMINNM   = FPDataProcessing2SourceFixed | 0x00007000,
+  FMINNM_s = FMINNM,
+  FMINNM_d = FMINNM | FP64,
+  FNMUL    = FPDataProcessing2SourceFixed | 0x00008000,
+  FNMUL_s  = FNMUL,
+  FNMUL_d  = FNMUL | FP64
+};
+
+// Floating point data processing 3 source.
+enum FPDataProcessing3SourceOp {
+  FPDataProcessing3SourceFixed = 0x1F000000,
+  FPDataProcessing3SourceFMask = 0x5F000000,
+  FPDataProcessing3SourceMask  = 0xFFE08000,
+  FMADD_s                      = FPDataProcessing3SourceFixed | 0x00000000,
+  FMSUB_s                      = FPDataProcessing3SourceFixed | 0x00008000,
+  FNMADD_s                     = FPDataProcessing3SourceFixed | 0x00200000,
+  FNMSUB_s                     = FPDataProcessing3SourceFixed | 0x00208000,
+  FMADD_d                      = FPDataProcessing3SourceFixed | 0x00400000,
+  FMSUB_d                      = FPDataProcessing3SourceFixed | 0x00408000,
+  FNMADD_d                     = FPDataProcessing3SourceFixed | 0x00600000,
+  FNMSUB_d                     = FPDataProcessing3SourceFixed | 0x00608000
+};
+
+// Conversion between floating point and integer.
+enum FPIntegerConvertOp {
+  FPIntegerConvertFixed = 0x1E200000,
+  FPIntegerConvertFMask = 0x5F20FC00,
+  FPIntegerConvertMask  = 0xFFFFFC00,
+  FCVTNS    = FPIntegerConvertFixed | 0x00000000,
+  FCVTNS_ws = FCVTNS,
+  FCVTNS_xs = FCVTNS | SixtyFourBits,
+  FCVTNS_wd = FCVTNS | FP64,
+  FCVTNS_xd = FCVTNS | SixtyFourBits | FP64,
+  FCVTNU    = FPIntegerConvertFixed | 0x00010000,
+  FCVTNU_ws = FCVTNU,
+  FCVTNU_xs = FCVTNU | SixtyFourBits,
+  FCVTNU_wd = FCVTNU | FP64,
+  FCVTNU_xd = FCVTNU | SixtyFourBits | FP64,
+  FCVTPS    = FPIntegerConvertFixed | 0x00080000,
+  FCVTPS_ws = FCVTPS,
+  FCVTPS_xs = FCVTPS | SixtyFourBits,
+  FCVTPS_wd = FCVTPS | FP64,
+  FCVTPS_xd = FCVTPS | SixtyFourBits | FP64,
+  FCVTPU    = FPIntegerConvertFixed | 0x00090000,
+  FCVTPU_ws = FCVTPU,
+  FCVTPU_xs = FCVTPU | SixtyFourBits,
+  FCVTPU_wd = FCVTPU | FP64,
+  FCVTPU_xd = FCVTPU | SixtyFourBits | FP64,
+  FCVTMS    = FPIntegerConvertFixed | 0x00100000,
+  FCVTMS_ws = FCVTMS,
+  FCVTMS_xs = FCVTMS | SixtyFourBits,
+  FCVTMS_wd = FCVTMS | FP64,
+  FCVTMS_xd = FCVTMS | SixtyFourBits | FP64,
+  FCVTMU    = FPIntegerConvertFixed | 0x00110000,
+  FCVTMU_ws = FCVTMU,
+  FCVTMU_xs = FCVTMU | SixtyFourBits,
+  FCVTMU_wd = FCVTMU | FP64,
+  FCVTMU_xd = FCVTMU | SixtyFourBits | FP64,
+  FCVTZS    = FPIntegerConvertFixed | 0x00180000,
+  FCVTZS_ws = FCVTZS,
+  FCVTZS_xs = FCVTZS | SixtyFourBits,
+  FCVTZS_wd = FCVTZS | FP64,
+  FCVTZS_xd = FCVTZS | SixtyFourBits | FP64,
+  FCVTZU    = FPIntegerConvertFixed | 0x00190000,
+  FCVTZU_ws = FCVTZU,
+  FCVTZU_xs = FCVTZU | SixtyFourBits,
+  FCVTZU_wd = FCVTZU | FP64,
+  FCVTZU_xd = FCVTZU | SixtyFourBits | FP64,
+  SCVTF     = FPIntegerConvertFixed | 0x00020000,
+  SCVTF_sw  = SCVTF,
+  SCVTF_sx  = SCVTF | SixtyFourBits,
+  SCVTF_dw  = SCVTF | FP64,
+  SCVTF_dx  = SCVTF | SixtyFourBits | FP64,
+  UCVTF     = FPIntegerConvertFixed | 0x00030000,
+  UCVTF_sw  = UCVTF,
+  UCVTF_sx  = UCVTF | SixtyFourBits,
+  UCVTF_dw  = UCVTF | FP64,
+  UCVTF_dx  = UCVTF | SixtyFourBits | FP64,
+  FCVTAS    = FPIntegerConvertFixed | 0x00040000,
+  FCVTAS_ws = FCVTAS,
+  FCVTAS_xs = FCVTAS | SixtyFourBits,
+  FCVTAS_wd = FCVTAS | FP64,
+  FCVTAS_xd = FCVTAS | SixtyFourBits | FP64,
+  FCVTAU    = FPIntegerConvertFixed | 0x00050000,
+  FCVTAU_ws = FCVTAU,
+  FCVTAU_xs = FCVTAU | SixtyFourBits,
+  FCVTAU_wd = FCVTAU | FP64,
+  FCVTAU_xd = FCVTAU | SixtyFourBits | FP64,
+  FMOV_ws   = FPIntegerConvertFixed | 0x00060000,
+  FMOV_sw   = FPIntegerConvertFixed | 0x00070000,
+  FMOV_xd   = FMOV_ws | SixtyFourBits | FP64,
+  FMOV_dx   = FMOV_sw | SixtyFourBits | FP64
+};
+
+// Conversion between fixed point and floating point.
+enum FPFixedPointConvertOp {
+  FPFixedPointConvertFixed = 0x1E000000,
+  FPFixedPointConvertFMask = 0x5F200000,
+  FPFixedPointConvertMask  = 0xFFFF0000,
+  FCVTZS_fixed    = FPFixedPointConvertFixed | 0x00180000,
+  FCVTZS_ws_fixed = FCVTZS_fixed,
+  FCVTZS_xs_fixed = FCVTZS_fixed | SixtyFourBits,
+  FCVTZS_wd_fixed = FCVTZS_fixed | FP64,
+  FCVTZS_xd_fixed = FCVTZS_fixed | SixtyFourBits | FP64,
+  FCVTZU_fixed    = FPFixedPointConvertFixed | 0x00190000,
+  FCVTZU_ws_fixed = FCVTZU_fixed,
+  FCVTZU_xs_fixed = FCVTZU_fixed | SixtyFourBits,
+  FCVTZU_wd_fixed = FCVTZU_fixed | FP64,
+  FCVTZU_xd_fixed = FCVTZU_fixed | SixtyFourBits | FP64,
+  SCVTF_fixed     = FPFixedPointConvertFixed | 0x00020000,
+  SCVTF_sw_fixed  = SCVTF_fixed,
+  SCVTF_sx_fixed  = SCVTF_fixed | SixtyFourBits,
+  SCVTF_dw_fixed  = SCVTF_fixed | FP64,
+  SCVTF_dx_fixed  = SCVTF_fixed | SixtyFourBits | FP64,
+  UCVTF_fixed     = FPFixedPointConvertFixed | 0x00030000,
+  UCVTF_sw_fixed  = UCVTF_fixed,
+  UCVTF_sx_fixed  = UCVTF_fixed | SixtyFourBits,
+  UCVTF_dw_fixed  = UCVTF_fixed | FP64,
+  UCVTF_dx_fixed  = UCVTF_fixed | SixtyFourBits | FP64
+};
+
+// Unimplemented and unallocated instructions. These are defined to make fixed
+// bit assertion easier.
+enum UnimplementedOp {
+  UnimplementedFixed = 0x00000000,
+  UnimplementedFMask = 0x00000000
+};
+
+enum UnallocatedOp {
+  UnallocatedFixed = 0x00000000,
+  UnallocatedFMask = 0x00000000
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_CONSTANTS_A64_H_
diff --git a/disas/libvixl/src/a64/cpu-a64.cc b/disas/libvixl/src/a64/cpu-a64.cc
new file mode 100644
index 0000000..8586563
--- /dev/null
+++ b/disas/libvixl/src/a64/cpu-a64.cc
@@ -0,0 +1,148 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utils.h"
+#include "a64/cpu-a64.h"
+
+namespace vixl {
+
+// Initialise to smallest possible cache size.
+unsigned CPU::dcache_line_size_ = 1;
+unsigned CPU::icache_line_size_ = 1;
+
+
+// Currently computes I and D cache line size.
+void CPU::SetUp() {
+  uint32_t cache_type_register = GetCacheType();
+
+  // The cache type register holds information about the caches, including I
+  // D caches line size.
+  static const int kDCacheLineSizeShift = 16;
+  static const int kICacheLineSizeShift = 0;
+  static const uint32_t kDCacheLineSizeMask = 0xf << kDCacheLineSizeShift;
+  static const uint32_t kICacheLineSizeMask = 0xf << kICacheLineSizeShift;
+
+  // The cache type register holds the size of the I and D caches as a power of
+  // two.
+  uint32_t dcache_line_size_power_of_two =
+      (cache_type_register & kDCacheLineSizeMask) >> kDCacheLineSizeShift;
+  uint32_t icache_line_size_power_of_two =
+      (cache_type_register & kICacheLineSizeMask) >> kICacheLineSizeShift;
+
+  dcache_line_size_ = 1 << dcache_line_size_power_of_two;
+  icache_line_size_ = 1 << icache_line_size_power_of_two;
+}
+
+
+uint32_t CPU::GetCacheType() {
+#ifdef USE_SIMULATOR
+  // This will lead to a cache with 1 byte long lines, which is fine since the
+  // simulator will not need this information.
+  return 0;
+#else
+  uint32_t cache_type_register;
+  // Copy the content of the cache type register to a core register.
+  __asm__ __volatile__ ("mrs %[ctr], ctr_el0"  // NOLINT
+                        : [ctr] "=r" (cache_type_register));
+  return cache_type_register;
+#endif
+}
+
+
+void CPU::EnsureIAndDCacheCoherency(void *address, size_t length) {
+#ifdef USE_SIMULATOR
+  USE(address);
+  USE(length);
+  // TODO: consider adding cache simulation to ensure every address run has been
+  // synchronised.
+#else
+  // The code below assumes user space cache operations are allowed.
+
+  uintptr_t start = reinterpret_cast<uintptr_t>(address);
+  // Sizes will be used to generate a mask big enough to cover a pointer.
+  uintptr_t dsize = static_cast<uintptr_t>(dcache_line_size_);
+  uintptr_t isize = static_cast<uintptr_t>(icache_line_size_);
+  // Cache line sizes are always a power of 2.
+  ASSERT(CountSetBits(dsize, 64) == 1);
+  ASSERT(CountSetBits(isize, 64) == 1);
+  uintptr_t dstart = start & ~(dsize - 1);
+  uintptr_t istart = start & ~(isize - 1);
+  uintptr_t end = start + length;
+
+  __asm__ __volatile__ (  // NOLINT
+    // Clean every line of the D cache containing the target data.
+    "0:                                \n\t"
+    // dc      : Data Cache maintenance
+    //    c    : Clean
+    //     va  : by (Virtual) Address
+    //       u : to the point of Unification
+    // The point of unification for a processor is the point by which the
+    // instruction and data caches are guaranteed to see the same copy of a
+    // memory location. See ARM DDI 0406B page B2-12 for more information.
+    "dc   cvau, %[dline]                \n\t"
+    "add  %[dline], %[dline], %[dsize]  \n\t"
+    "cmp  %[dline], %[end]              \n\t"
+    "b.lt 0b                            \n\t"
+    // Barrier to make sure the effect of the code above is visible to the rest
+    // of the world.
+    // dsb    : Data Synchronisation Barrier
+    //    ish : Inner SHareable domain
+    // The point of unification for an Inner Shareable shareability domain is
+    // the point by which the instruction and data caches of all the processors
+    // in that Inner Shareable shareability domain are guaranteed to see the
+    // same copy of a memory location.  See ARM DDI 0406B page B2-12 for more
+    // information.
+    "dsb  ish                           \n\t"
+    // Invalidate every line of the I cache containing the target data.
+    "1:                                 \n\t"
+    // ic      : instruction cache maintenance
+    //    i    : invalidate
+    //     va  : by address
+    //       u : to the point of unification
+    "ic   ivau, %[iline]                \n\t"
+    "add  %[iline], %[iline], %[isize]  \n\t"
+    "cmp  %[iline], %[end]              \n\t"
+    "b.lt 1b                            \n\t"
+    // Barrier to make sure the effect of the code above is visible to the rest
+    // of the world.
+    "dsb  ish                           \n\t"
+    // Barrier to ensure any prefetching which happened before this code is
+    // discarded.
+    // isb : Instruction Synchronisation Barrier
+    "isb                                \n\t"
+    : [dline] "+r" (dstart),
+      [iline] "+r" (istart)
+    : [dsize] "r"  (dsize),
+      [isize] "r"  (isize),
+      [end]   "r"  (end)
+    // This code does not write to memory but without the dependency gcc might
+    // move this code before the code is generated.
+    : "cc", "memory"
+  );  // NOLINT
+#endif
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/cpu-a64.h b/disas/libvixl/src/a64/cpu-a64.h
new file mode 100644
index 0000000..dfd8f01
--- /dev/null
+++ b/disas/libvixl/src/a64/cpu-a64.h
@@ -0,0 +1,56 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_CPU_A64_H
+#define VIXL_CPU_A64_H
+
+#include "globals.h"
+
+namespace vixl {
+
+class CPU {
+ public:
+  // Initialise CPU support.
+  static void SetUp();
+
+  // Ensures the data at a given address and with a given size is the same for
+  // the I and D caches. I and D caches are not automatically coherent on ARM
+  // so this operation is required before any dynamically generated code can
+  // safely run.
+  static void EnsureIAndDCacheCoherency(void *address, size_t length);
+
+ private:
+  // Return the content of the cache type register.
+  static uint32_t GetCacheType();
+
+  // I and D cache line size in bytes.
+  static unsigned icache_line_size_;
+  static unsigned dcache_line_size_;
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_CPU_A64_H
diff --git a/disas/libvixl/src/a64/debugger-a64.cc b/disas/libvixl/src/a64/debugger-a64.cc
new file mode 100644
index 0000000..ecdc835
--- /dev/null
+++ b/disas/libvixl/src/a64/debugger-a64.cc
@@ -0,0 +1,1511 @@
+// Copyright 2013 ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/debugger-a64.h"
+
+namespace vixl {
+
+// List of commands supported by the debugger.
+#define DEBUG_COMMAND_LIST(C)  \
+C(HelpCommand)                 \
+C(ContinueCommand)             \
+C(StepCommand)                 \
+C(DisasmCommand)               \
+C(PrintCommand)                \
+C(MemCommand)
+
+// Debugger command lines are broken up in token of different type to make
+// processing easier later on.
+class Token {
+ public:
+  virtual ~Token() {}
+
+  // Token type.
+  virtual bool IsRegister() const { return false; }
+  virtual bool IsFPRegister() const { return false; }
+  virtual bool IsIdentifier() const { return false; }
+  virtual bool IsAddress() const { return false; }
+  virtual bool IsInteger() const { return false; }
+  virtual bool IsFormat() const { return false; }
+  virtual bool IsUnknown() const { return false; }
+  // Token properties.
+  virtual bool CanAddressMemory() const { return false; }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const = 0;
+
+  static Token* Tokenize(const char* arg);
+};
+
+// Tokens often hold one value.
+template<typename T> class ValueToken : public Token {
+ public:
+  explicit ValueToken(T value) : value_(value) {}
+  ValueToken() {}
+
+  T value() const { return value_; }
+
+ protected:
+  T value_;
+};
+
+// Integer registers (X or W) and their aliases.
+// Format: wn or xn with 0 <= n < 32 or a name in the aliases list.
+class RegisterToken : public ValueToken<const Register> {
+ public:
+  explicit RegisterToken(const Register reg)
+      : ValueToken<const Register>(reg) {}
+
+  virtual bool IsRegister() const { return true; }
+  virtual bool CanAddressMemory() const { return value().Is64Bits(); }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const ;
+  const char* Name() const;
+
+  static Token* Tokenize(const char* arg);
+  static RegisterToken* Cast(Token* tok) {
+    ASSERT(tok->IsRegister());
+    return reinterpret_cast<RegisterToken*>(tok);
+  }
+
+ private:
+  static const int kMaxAliasNumber = 4;
+  static const char* kXAliases[kNumberOfRegisters][kMaxAliasNumber];
+  static const char* kWAliases[kNumberOfRegisters][kMaxAliasNumber];
+};
+
+// Floating point registers (D or S).
+// Format: sn or dn with 0 <= n < 32.
+class FPRegisterToken : public ValueToken<const FPRegister> {
+ public:
+  explicit FPRegisterToken(const FPRegister fpreg)
+      : ValueToken<const FPRegister>(fpreg) {}
+
+  virtual bool IsFPRegister() const { return true; }
+  virtual void Print(FILE* out = stdout) const ;
+
+  static Token* Tokenize(const char* arg);
+  static FPRegisterToken* Cast(Token* tok) {
+    ASSERT(tok->IsFPRegister());
+    return reinterpret_cast<FPRegisterToken*>(tok);
+  }
+};
+
+
+// Non-register identifiers.
+// Format: Alphanumeric string starting with a letter.
+class IdentifierToken : public ValueToken<char*> {
+ public:
+  explicit IdentifierToken(const char* name) {
+    int size = strlen(name) + 1;
+    value_ = new char[size];
+    strncpy(value_, name, size);
+  }
+  virtual ~IdentifierToken() { delete[] value_; }
+
+  virtual bool IsIdentifier() const { return true; }
+  virtual bool CanAddressMemory() const { return strcmp(value(), "pc") == 0; }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const;
+
+  static Token* Tokenize(const char* arg);
+  static IdentifierToken* Cast(Token* tok) {
+    ASSERT(tok->IsIdentifier());
+    return reinterpret_cast<IdentifierToken*>(tok);
+  }
+};
+
+// 64-bit address literal.
+// Format: 0x... with up to 16 hexadecimal digits.
+class AddressToken : public ValueToken<uint8_t*> {
+ public:
+  explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {}
+
+  virtual bool IsAddress() const { return true; }
+  virtual bool CanAddressMemory() const { return true; }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const ;
+
+  static Token* Tokenize(const char* arg);
+  static AddressToken* Cast(Token* tok) {
+    ASSERT(tok->IsAddress());
+    return reinterpret_cast<AddressToken*>(tok);
+  }
+};
+
+
+// 64-bit decimal integer literal.
+// Format: n.
+class IntegerToken : public ValueToken<int64_t> {
+ public:
+  explicit IntegerToken(int value) : ValueToken<int64_t>(value) {}
+
+  virtual bool IsInteger() const { return true; }
+  virtual void Print(FILE* out = stdout) const;
+
+  static Token* Tokenize(const char* arg);
+  static IntegerToken* Cast(Token* tok) {
+    ASSERT(tok->IsInteger());
+    return reinterpret_cast<IntegerToken*>(tok);
+  }
+};
+
+// Literal describing how to print a chunk of data (up to 64 bits).
+// Format: %qt
+// where q (qualifier) is one of
+//  * s: signed integer
+//  * u: unsigned integer
+//  * a: hexadecimal floating point
+// and t (type) is one of
+//  * x: 64-bit integer
+//  * w: 32-bit integer
+//  * h: 16-bit integer
+//  * b: 8-bit integer
+//  * c: character
+//  * d: double
+//  * s: float
+// When no qualifier is given for integers, they are printed in hexadecinal.
+class FormatToken : public Token {
+ public:
+  FormatToken() {}
+
+  virtual bool IsFormat() const { return true; }
+  virtual int SizeOf() const = 0;
+  virtual void PrintData(void* data, FILE* out = stdout) const = 0;
+  virtual void Print(FILE* out = stdout) const = 0;
+
+  static Token* Tokenize(const char* arg);
+  static FormatToken* Cast(Token* tok) {
+    ASSERT(tok->IsFormat());
+    return reinterpret_cast<FormatToken*>(tok);
+  }
+};
+
+
+template<typename T> class Format : public FormatToken {
+ public:
+  explicit Format(const char* fmt) : fmt_(fmt) {}
+
+  virtual int SizeOf() const { return sizeof(T); }
+  virtual void PrintData(void* data, FILE* out = stdout) const {
+    T value;
+    memcpy(&value, data, sizeof(value));
+    fprintf(out, fmt_, value);
+  }
+  virtual void Print(FILE* out = stdout) const;
+
+ private:
+  const char* fmt_;
+};
+
+// Tokens which don't fit any of the above.
+class UnknownToken : public Token {
+ public:
+  explicit UnknownToken(const char* arg) {
+    int size = strlen(arg) + 1;
+    unknown_ = new char[size];
+    strncpy(unknown_, arg, size);
+  }
+  virtual ~UnknownToken() { delete[] unknown_; }
+
+  virtual bool IsUnknown() const { return true; }
+  virtual void Print(FILE* out = stdout) const;
+
+ private:
+  char* unknown_;
+};
+
+
+// All debugger commands must subclass DebugCommand and implement Run, Print
+// and Build. Commands must also define kHelp and kAliases.
+class DebugCommand {
+ public:
+  explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {}
+  DebugCommand() : name_(NULL) {}
+  virtual ~DebugCommand() { delete name_; }
+
+  const char* name() { return name_->value(); }
+  // Run the command on the given debugger. The command returns true if
+  // execution should move to the next instruction.
+  virtual bool Run(Debugger * debugger) = 0;
+  virtual void Print(FILE* out = stdout);
+
+  static bool Match(const char* name, const char** aliases);
+  static DebugCommand* Parse(char* line);
+  static void PrintHelp(const char** aliases,
+                        const char* args,
+                        const char* help);
+
+ private:
+  IdentifierToken* name_;
+};
+
+// For all commands below see their respective kHelp and kAliases in
+// debugger-a64.cc
+class HelpCommand : public DebugCommand {
+ public:
+  explicit HelpCommand(Token* name) : DebugCommand(name) {}
+
+  virtual bool Run(Debugger* debugger);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+};
+
+
+class ContinueCommand : public DebugCommand {
+ public:
+  explicit ContinueCommand(Token* name) : DebugCommand(name) {}
+
+  virtual bool Run(Debugger* debugger);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+};
+
+
+class StepCommand : public DebugCommand {
+ public:
+  StepCommand(Token* name, IntegerToken* count)
+      : DebugCommand(name), count_(count) {}
+  virtual ~StepCommand() { delete count_; }
+
+  int64_t count() { return count_->value(); }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  IntegerToken* count_;
+};
+
+class DisasmCommand : public DebugCommand {
+ public:
+  DisasmCommand(Token* name, Token* target, IntegerToken* count)
+      : DebugCommand(name), target_(target), count_(count) {}
+  virtual ~DisasmCommand() {
+    delete target_;
+    delete count_;
+  }
+
+  Token* target() { return target_; }
+  int64_t count() { return count_->value(); }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  Token* target_;
+  IntegerToken* count_;
+};
+
+
+class PrintCommand : public DebugCommand {
+ public:
+  PrintCommand(Token* name, Token* target)
+      : DebugCommand(name), target_(target) {}
+  virtual ~PrintCommand() { delete target_; }
+
+  Token* target() { return target_; }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  Token* target_;
+};
+
+class MemCommand : public DebugCommand {
+ public:
+  MemCommand(Token* name,
+             Token* target,
+             IntegerToken* count,
+             FormatToken* format)
+      : DebugCommand(name), target_(target), count_(count), format_(format) {}
+  virtual ~MemCommand() {
+    delete target_;
+    delete count_;
+    delete format_;
+  }
+
+  Token* target() { return target_; }
+  int64_t count() { return count_->value(); }
+  FormatToken* format() { return format_; }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  Token* target_;
+  IntegerToken* count_;
+  FormatToken* format_;
+};
+
+// Commands which name does not match any of the known commnand.
+class UnknownCommand : public DebugCommand {
+ public:
+  explicit UnknownCommand(std::vector<Token*> args) : args_(args) {}
+  virtual ~UnknownCommand();
+
+  virtual bool Run(Debugger* debugger);
+
+ private:
+  std::vector<Token*> args_;
+};
+
+// Commands which name match a known command but the syntax is invalid.
+class InvalidCommand : public DebugCommand {
+ public:
+  InvalidCommand(std::vector<Token*> args, int index, const char* cause)
+      : args_(args), index_(index), cause_(cause) {}
+  virtual ~InvalidCommand();
+
+  virtual bool Run(Debugger* debugger);
+
+ private:
+  std::vector<Token*> args_;
+  int index_;
+  const char* cause_;
+};
+
+const char* HelpCommand::kAliases[] = { "help", NULL };
+const char* HelpCommand::kArguments = NULL;
+const char* HelpCommand::kHelp = "  print this help";
+
+const char* ContinueCommand::kAliases[] = { "continue", "c", NULL };
+const char* ContinueCommand::kArguments = NULL;
+const char* ContinueCommand::kHelp = "  resume execution";
+
+const char* StepCommand::kAliases[] = { "stepi", "si", NULL };
+const char* StepCommand::kArguments = "[n = 1]";
+const char* StepCommand::kHelp = "  execute n next instruction(s)";
+
+const char* DisasmCommand::kAliases[] = { "dis", "d", NULL };
+const char* DisasmCommand::kArguments = "[addr = pc] [n = 1]";
+const char* DisasmCommand::kHelp =
+  "  disassemble n instruction(s) at address addr.\n"
+  "  addr can be an immediate address, a register or the pc."
+;
+
+const char* PrintCommand::kAliases[] = { "print", "p", NULL };
+const char* PrintCommand::kArguments =  "<entity>";
+const char* PrintCommand::kHelp =
+  "  print the given entity\n"
+  "  entity can be 'regs' for W and X registers, 'fpregs' for S and D\n"
+  "  registers, 'sysregs' for system registers (including NZCV) or 'pc'."
+;
+
+const char* MemCommand::kAliases[] = { "mem", "m", NULL };
+const char* MemCommand::kArguments = "<addr> [n = 1] [format = %x]";
+const char* MemCommand::kHelp =
+  "  print n memory item(s) at address addr according to the given format.\n"
+  "  addr can be an immediate address, a register or the pc.\n"
+  "  format is made of a qualifer: 's', 'u', 'a' (signed, unsigned, hexa)\n"
+  "  and a type 'x', 'w', 'h', 'b' (64- to 8-bit integer), 'c' (character),\n"
+  "  's' (float) or 'd' (double). E.g 'mem sp %w' will print a 32-bit word\n"
+  "  from the stack as an hexadecimal number."
+;
+
+const char* RegisterToken::kXAliases[kNumberOfRegisters][kMaxAliasNumber] = {
+  { "x0", NULL },
+  { "x1", NULL },
+  { "x2", NULL },
+  { "x3", NULL },
+  { "x4", NULL },
+  { "x5", NULL },
+  { "x6", NULL },
+  { "x7", NULL },
+  { "x8", NULL },
+  { "x9", NULL },
+  { "x10", NULL },
+  { "x11", NULL },
+  { "x12", NULL },
+  { "x13", NULL },
+  { "x14", NULL },
+  { "x15", NULL },
+  { "ip0", "x16", NULL },
+  { "ip1", "x17", NULL },
+  { "x18", "pr", NULL },
+  { "x19", NULL },
+  { "x20", NULL },
+  { "x21", NULL },
+  { "x22", NULL },
+  { "x23", NULL },
+  { "x24", NULL },
+  { "x25", NULL },
+  { "x26", NULL },
+  { "x27", NULL },
+  { "x28", NULL },
+  { "fp", "x29", NULL },
+  { "lr", "x30", NULL },
+  { "sp", NULL}
+};
+
+const char* RegisterToken::kWAliases[kNumberOfRegisters][kMaxAliasNumber] = {
+  { "w0", NULL },
+  { "w1", NULL },
+  { "w2", NULL },
+  { "w3", NULL },
+  { "w4", NULL },
+  { "w5", NULL },
+  { "w6", NULL },
+  { "w7", NULL },
+  { "w8", NULL },
+  { "w9", NULL },
+  { "w10", NULL },
+  { "w11", NULL },
+  { "w12", NULL },
+  { "w13", NULL },
+  { "w14", NULL },
+  { "w15", NULL },
+  { "w16", NULL },
+  { "w17", NULL },
+  { "w18", NULL },
+  { "w19", NULL },
+  { "w20", NULL },
+  { "w21", NULL },
+  { "w22", NULL },
+  { "w23", NULL },
+  { "w24", NULL },
+  { "w25", NULL },
+  { "w26", NULL },
+  { "w27", NULL },
+  { "w28", NULL },
+  { "w29", NULL },
+  { "w30", NULL },
+  { "wsp", NULL }
+};
+
+
+Debugger::Debugger(Decoder* decoder, FILE* stream)
+    : Simulator(decoder, stream),
+      log_parameters_(0),
+      debug_parameters_(0),
+      pending_request_(false),
+      steps_(0),
+      last_command_(NULL) {
+  disasm_ = new PrintDisassembler(stdout);
+  printer_ = new Decoder();
+  printer_->AppendVisitor(disasm_);
+}
+
+
+void Debugger::Run() {
+  while (pc_ != kEndOfSimAddress) {
+    if (pending_request()) {
+      LogProcessorState();
+      RunDebuggerShell();
+    }
+
+    ExecuteInstruction();
+  }
+}
+
+
+void Debugger::PrintInstructions(void* address, int64_t count) {
+  if (count == 0) {
+    return;
+  }
+
+  Instruction* from = Instruction::Cast(address);
+  if (count < 0) {
+    count = -count;
+    from -= (count - 1) * kInstructionSize;
+  }
+  Instruction* to = from + count * kInstructionSize;
+
+  for (Instruction* current = from;
+       current < to;
+       current = current->NextInstruction()) {
+    printer_->Decode(current);
+  }
+}
+
+
+void Debugger::PrintMemory(const uint8_t* address,
+                           int64_t count,
+                           const FormatToken* format) {
+  if (count == 0) {
+    return;
+  }
+
+  const uint8_t* from = address;
+  int size = format->SizeOf();
+  if (count < 0) {
+    count = -count;
+    from -= (count - 1) * size;
+  }
+  const uint8_t* to = from + count * size;
+
+  for (const uint8_t* current = from; current < to; current += size) {
+    if (((current - from) % 16) == 0) {
+      printf("\n%p: ", current);
+    }
+
+    uint64_t data = MemoryRead(current, size);
+    format->PrintData(&data);
+    printf(" ");
+  }
+  printf("\n\n");
+}
+
+
+void Debugger::VisitException(Instruction* instr) {
+  switch (instr->Mask(ExceptionMask)) {
+    case BRK:
+      DoBreakpoint(instr);
+      return;
+    case HLT:
+      switch (instr->ImmException()) {
+        case kUnreachableOpcode:
+          DoUnreachable(instr);
+          return;
+        case kTraceOpcode:
+          DoTrace(instr);
+          return;
+        case kLogOpcode:
+          DoLog(instr);
+          return;
+      }
+      // Fall through
+    default: Simulator::VisitException(instr);
+  }
+}
+
+
+void Debugger::LogSystemRegisters() {
+  if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters();
+}
+
+
+void Debugger::LogRegisters() {
+  if (log_parameters_ & LOG_REGS) PrintRegisters();
+}
+
+
+void Debugger::LogFPRegisters() {
+  if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters();
+}
+
+
+void Debugger::LogProcessorState() {
+  LogSystemRegisters();
+  LogRegisters();
+  LogFPRegisters();
+}
+
+
+// Read a command. A command will be at most kMaxDebugShellLine char long and
+// ends with '\n\0'.
+// TODO: Should this be a utility function?
+char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) {
+  int fgets_calls = 0;
+  char* end = NULL;
+
+  printf("%s", prompt);
+  fflush(stdout);
+
+  do {
+    if (fgets(buffer, length, stdin) == NULL) {
+      printf(" ** Error while reading command. **\n");
+      return NULL;
+    }
+
+    fgets_calls++;
+    end = strchr(buffer, '\n');
+  } while (end == NULL);
+
+  if (fgets_calls != 1) {
+    printf(" ** Command too long. **\n");
+    return NULL;
+  }
+
+  // Remove the newline from the end of the command.
+  ASSERT(end[1] == '\0');
+  ASSERT((end - buffer) < (length - 1));
+  end[0] = '\0';
+
+  return buffer;
+}
+
+
+void Debugger::RunDebuggerShell() {
+  if (IsDebuggerRunning()) {
+    if (steps_ > 0) {
+      // Finish stepping first.
+      --steps_;
+      return;
+    }
+
+    printf("Next: ");
+    PrintInstructions(pc());
+    bool done = false;
+    while (!done) {
+      char buffer[kMaxDebugShellLine];
+      char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine);
+
+      if (line == NULL) continue;  // An error occurred.
+
+      DebugCommand* command = DebugCommand::Parse(line);
+      if (command != NULL) {
+        last_command_ = command;
+      }
+
+      if (last_command_ != NULL) {
+        done = last_command_->Run(this);
+      } else {
+        printf("No previous command to run!\n");
+      }
+    }
+
+    if ((debug_parameters_ & DBG_BREAK) != 0) {
+      // The break request has now been handled, move to next instruction.
+      debug_parameters_ &= ~DBG_BREAK;
+      increment_pc();
+    }
+  }
+}
+
+
+void Debugger::DoBreakpoint(Instruction* instr) {
+  ASSERT(instr->Mask(ExceptionMask) == BRK);
+
+  printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<void*>(instr));
+  set_debug_parameters(debug_parameters() | DBG_BREAK | DBG_ACTIVE);
+  // Make the shell point to the brk instruction.
+  set_pc(instr);
+}
+
+
+void Debugger::DoUnreachable(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kUnreachableOpcode));
+
+  fprintf(stream_, "Hit UNREACHABLE marker at pc=%p.\n",
+          reinterpret_cast<void*>(instr));
+  abort();
+}
+
+
+void Debugger::DoTrace(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kTraceOpcode));
+
+  // Read the arguments encoded inline in the instruction stream.
+  uint32_t parameters;
+  uint32_t command;
+
+  ASSERT(sizeof(*instr) == 1);
+  memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
+  memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
+
+  switch (command) {
+    case TRACE_ENABLE:
+      set_log_parameters(log_parameters() | parameters);
+      break;
+    case TRACE_DISABLE:
+      set_log_parameters(log_parameters() & ~parameters);
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  set_pc(instr->InstructionAtOffset(kTraceLength));
+}
+
+
+void Debugger::DoLog(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kLogOpcode));
+
+  // Read the arguments encoded inline in the instruction stream.
+  uint32_t parameters;
+
+  ASSERT(sizeof(*instr) == 1);
+  memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
+
+  // We don't support a one-shot LOG_DISASM.
+  ASSERT((parameters & LOG_DISASM) == 0);
+  // Print the requested information.
+  if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true);
+  if (parameters & LOG_REGS) PrintRegisters(true);
+  if (parameters & LOG_FP_REGS) PrintFPRegisters(true);
+
+  set_pc(instr->InstructionAtOffset(kLogLength));
+}
+
+
+static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) {
+  char* endptr = NULL;
+  errno = 0;  // Reset errors.
+  uint64_t parsed = strtoul(line, &endptr, base);
+
+  if (errno == ERANGE) {
+    // Overflow.
+    return false;
+  }
+
+  if (endptr == line) {
+    // No digits were parsed.
+    return false;
+  }
+
+  if (*endptr != '\0') {
+    // Non-digit characters present at the end.
+    return false;
+  }
+
+  *value = parsed;
+  return true;
+}
+
+
+static bool StringToInt64(int64_t* value, const char* line, int base = 10) {
+  char* endptr = NULL;
+  errno = 0;  // Reset errors.
+  int64_t parsed = strtol(line, &endptr, base);
+
+  if (errno == ERANGE) {
+    // Overflow, undeflow.
+    return false;
+  }
+
+  if (endptr == line) {
+    // No digits were parsed.
+    return false;
+  }
+
+  if (*endptr != '\0') {
+    // Non-digit characters present at the end.
+    return false;
+  }
+
+  *value = parsed;
+  return true;
+}
+
+
+uint8_t* Token::ToAddress(Debugger* debugger) const {
+  USE(debugger);
+  UNREACHABLE();
+  return NULL;
+}
+
+
+Token* Token::Tokenize(const char* arg) {
+  if ((arg == NULL) || (*arg == '\0')) {
+    return NULL;
+  }
+
+  // The order is important. For example Identifier::Tokenize would consider
+  // any register to be a valid identifier.
+
+  Token* token = RegisterToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = FPRegisterToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = IdentifierToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = AddressToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = IntegerToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = FormatToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  return new UnknownToken(arg);
+}
+
+
+uint8_t* RegisterToken::ToAddress(Debugger* debugger) const {
+  ASSERT(CanAddressMemory());
+  uint64_t reg_value = debugger->xreg(value().code(), Reg31IsStackPointer);
+  uint8_t* address = NULL;
+  memcpy(&address, &reg_value, sizeof(address));
+  return address;
+}
+
+
+void RegisterToken::Print(FILE* out) const {
+  ASSERT(value().IsValid());
+  fprintf(out, "[Register %s]", Name());
+}
+
+
+const char* RegisterToken::Name() const {
+  if (value().Is32Bits()) {
+    return kWAliases[value().code()][0];
+  } else {
+    return kXAliases[value().code()][0];
+  }
+}
+
+
+Token* RegisterToken::Tokenize(const char* arg) {
+  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
+    // Is it a X register or alias?
+    for (const char** current = kXAliases[i]; *current != NULL; current++) {
+      if (strcmp(arg, *current) == 0) {
+        return new RegisterToken(Register::XRegFromCode(i));
+      }
+    }
+
+    // Is it a W register or alias?
+    for (const char** current = kWAliases[i]; *current != NULL; current++) {
+      if (strcmp(arg, *current) == 0) {
+        return new RegisterToken(Register::WRegFromCode(i));
+      }
+    }
+  }
+
+  return NULL;
+}
+
+
+void FPRegisterToken::Print(FILE* out) const {
+  ASSERT(value().IsValid());
+  char prefix = value().Is32Bits() ? 's' : 'd';
+  fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().code());
+}
+
+
+Token* FPRegisterToken::Tokenize(const char* arg) {
+  if (strlen(arg) < 2) {
+    return NULL;
+  }
+
+  switch (*arg) {
+    case 's':
+    case 'd':
+      const char* cursor = arg + 1;
+      uint64_t code = 0;
+      if (!StringToUInt64(&code, cursor)) {
+        return NULL;
+      }
+
+      if (code > kNumberOfFPRegisters) {
+        return NULL;
+      }
+
+      FPRegister fpreg = NoFPReg;
+      switch (*arg) {
+        case 's': fpreg = FPRegister::SRegFromCode(code); break;
+        case 'd': fpreg = FPRegister::DRegFromCode(code); break;
+        default: UNREACHABLE();
+      }
+
+      return new FPRegisterToken(fpreg);
+  }
+
+  return NULL;
+}
+
+
+uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const {
+  ASSERT(CanAddressMemory());
+  Instruction* pc_value = debugger->pc();
+  uint8_t* address = NULL;
+  memcpy(&address, &pc_value, sizeof(address));
+  return address;
+}
+
+void IdentifierToken::Print(FILE* out) const {
+  fprintf(out, "[Identifier %s]", value());
+}
+
+
+Token* IdentifierToken::Tokenize(const char* arg) {
+  if (!isalpha(arg[0])) {
+    return NULL;
+  }
+
+  const char* cursor = arg + 1;
+  while ((*cursor != '\0') && isalnum(*cursor)) {
+    ++cursor;
+  }
+
+  if (*cursor == '\0') {
+    return new IdentifierToken(arg);
+  }
+
+  return NULL;
+}
+
+
+uint8_t* AddressToken::ToAddress(Debugger* debugger) const {
+  USE(debugger);
+  return value();
+}
+
+
+void AddressToken::Print(FILE* out) const {
+  fprintf(out, "[Address %p]", value());
+}
+
+
+Token* AddressToken::Tokenize(const char* arg) {
+  if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) {
+    return NULL;
+  }
+
+  uint64_t ptr = 0;
+  if (!StringToUInt64(&ptr, arg, 16)) {
+    return NULL;
+  }
+
+  uint8_t* address = reinterpret_cast<uint8_t*>(ptr);
+  return new AddressToken(address);
+}
+
+
+void IntegerToken::Print(FILE* out) const {
+  fprintf(out, "[Integer %" PRId64 "]", value());
+}
+
+
+Token* IntegerToken::Tokenize(const char* arg) {
+  int64_t value = 0;
+  if (!StringToInt64(&value, arg)) {
+    return NULL;
+  }
+
+  return new IntegerToken(value);
+}
+
+
+Token* FormatToken::Tokenize(const char* arg) {
+  if (arg[0] != '%') {
+    return NULL;
+  }
+
+  int length = strlen(arg);
+  if ((length < 2) || (length > 3)) {
+    return NULL;
+  }
+
+  char type = arg[length - 1];
+  if (length == 2) {
+    switch (type) {
+      case 'x': return new Format<uint64_t>("%016" PRIx64);
+      case 'w': return new Format<uint32_t>("%08" PRIx32);
+      case 'h': return new Format<uint16_t>("%04" PRIx16);
+      case 'b': return new Format<uint8_t>("%02" PRIx8);
+      case 'c': return new Format<char>("%c");
+      case 'd': return new Format<double>("%g");
+      case 's': return new Format<float>("%g");
+      default: return NULL;
+    }
+  }
+
+  ASSERT(length == 3);
+  switch (arg[1]) {
+    case 's':
+      switch (type) {
+        case 'x': return new Format<int64_t>("%+20" PRId64);
+        case 'w': return new Format<int32_t>("%+11" PRId32);
+        case 'h': return new Format<int16_t>("%+6" PRId16);
+        case 'b': return new Format<int8_t>("%+4" PRId8);
+        default: return NULL;
+      }
+    case 'u':
+      switch (type) {
+        case 'x': return new Format<uint64_t>("%20" PRIu64);
+        case 'w': return new Format<uint32_t>("%10" PRIu32);
+        case 'h': return new Format<uint16_t>("%5" PRIu16);
+        case 'b': return new Format<uint8_t>("%3" PRIu8);
+        default: return NULL;
+      }
+    case 'a':
+      switch (type) {
+        case 'd': return new Format<double>("%a");
+        case 's': return new Format<float>("%a");
+        default: return NULL;
+      }
+    default: return NULL;
+  }
+}
+
+
+template<typename T>
+void Format<T>::Print(FILE* out) const {
+  fprintf(out, "[Format %s - %lu byte(s)]", fmt_, sizeof(T));
+}
+
+
+void UnknownToken::Print(FILE* out) const {
+  fprintf(out, "[Unknown %s]", unknown_);
+}
+
+
+void DebugCommand::Print(FILE* out) {
+  fprintf(out, "%s", name());
+}
+
+
+bool DebugCommand::Match(const char* name, const char** aliases) {
+  for (const char** current = aliases; *current != NULL; current++) {
+    if (strcmp(name, *current) == 0) {
+       return true;
+    }
+  }
+
+  return false;
+}
+
+
+DebugCommand* DebugCommand::Parse(char* line) {
+  std::vector<Token*> args;
+
+  for (char* chunk = strtok(line, " ");
+       chunk != NULL;
+       chunk = strtok(NULL, " ")) {
+    args.push_back(Token::Tokenize(chunk));
+  }
+
+  if (args.size() == 0) {
+    return NULL;
+  }
+
+  if (!args[0]->IsIdentifier()) {
+    return new InvalidCommand(args, 0, "command name is not an identifier");
+  }
+
+  const char* name = IdentifierToken::Cast(args[0])->value();
+  #define RETURN_IF_MATCH(Command)       \
+  if (Match(name, Command::kAliases)) {  \
+    return Command::Build(args);         \
+  }
+  DEBUG_COMMAND_LIST(RETURN_IF_MATCH);
+  #undef RETURN_IF_MATCH
+
+  return new UnknownCommand(args);
+}
+
+
+void DebugCommand::PrintHelp(const char** aliases,
+                             const char* args,
+                             const char* help) {
+  ASSERT(aliases[0] != NULL);
+  ASSERT(help != NULL);
+
+  printf("\n----\n\n");
+  for (const char** current = aliases; *current != NULL; current++) {
+    if (args != NULL) {
+      printf("%s %s\n", *current, args);
+    } else {
+      printf("%s\n", *current);
+    }
+  }
+  printf("\n%s\n", help);
+}
+
+
+bool HelpCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+  USE(debugger);
+
+  #define PRINT_HELP(Command)                     \
+    DebugCommand::PrintHelp(Command::kAliases,    \
+                            Command::kArguments,  \
+                            Command::kHelp);
+  DEBUG_COMMAND_LIST(PRINT_HELP);
+  #undef PRINT_HELP
+  printf("\n----\n\n");
+
+  return false;
+}
+
+
+DebugCommand* HelpCommand::Build(std::vector<Token*> args) {
+  if (args.size() != 1) {
+    return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new HelpCommand(args[0]);
+}
+
+
+bool ContinueCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  debugger->set_debug_parameters(debugger->debug_parameters() & ~DBG_ACTIVE);
+  return true;
+}
+
+
+DebugCommand* ContinueCommand::Build(std::vector<Token*> args) {
+  if (args.size() != 1) {
+    return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new ContinueCommand(args[0]);
+}
+
+
+bool StepCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  int64_t steps = count();
+  if (steps < 0) {
+    printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
+  } else if (steps > 1) {
+    debugger->set_steps(steps - 1);
+  }
+
+  return true;
+}
+
+
+void StepCommand::Print(FILE* out) {
+  fprintf(out, "%s %" PRId64 "", name(), count());
+}
+
+
+DebugCommand* StepCommand::Build(std::vector<Token*> args) {
+  IntegerToken* count = NULL;
+  switch (args.size()) {
+    case 1: {  // step [1]
+      count = new IntegerToken(1);
+      break;
+    }
+    case 2: {  // step n
+      Token* first = args[1];
+      if (!first->IsInteger()) {
+        return new InvalidCommand(args, 1, "expects int");
+      }
+      count = IntegerToken::Cast(first);
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new StepCommand(args[0], count);
+}
+
+
+bool DisasmCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  uint8_t* from = target()->ToAddress(debugger);
+  debugger->PrintInstructions(from, count());
+
+  return false;
+}
+
+
+void DisasmCommand::Print(FILE* out) {
+  fprintf(out, "%s ", name());
+  target()->Print(out);
+  fprintf(out, " %" PRId64 "", count());
+}
+
+
+DebugCommand* DisasmCommand::Build(std::vector<Token*> args) {
+  Token* address = NULL;
+  IntegerToken* count = NULL;
+  switch (args.size()) {
+    case 1: {  // disasm [pc] [1]
+      address = new IdentifierToken("pc");
+      count = new IntegerToken(1);
+      break;
+    }
+    case 2: {  // disasm [pc] n or disasm address [1]
+      Token* first = args[1];
+      if (first->IsInteger()) {
+        address = new IdentifierToken("pc");
+        count = IntegerToken::Cast(first);
+      } else if (first->CanAddressMemory()) {
+        address = first;
+        count = new IntegerToken(1);
+      } else {
+        return new InvalidCommand(args, 1, "expects int or addr");
+      }
+      break;
+    }
+    case 3: {  // disasm address count
+      Token* first = args[1];
+      Token* second = args[2];
+      if (!first->CanAddressMemory() || !second->IsInteger()) {
+        return new InvalidCommand(args, -1, "disasm addr int");
+      }
+      address = first;
+      count = IntegerToken::Cast(second);
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "wrong arguments number");
+  }
+
+  return new DisasmCommand(args[0], address, count);
+}
+
+
+void PrintCommand::Print(FILE* out) {
+  fprintf(out, "%s ", name());
+  target()->Print(out);
+}
+
+
+bool PrintCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  Token* tok = target();
+  if (tok->IsIdentifier()) {
+    char* identifier = IdentifierToken::Cast(tok)->value();
+    if (strcmp(identifier, "regs") == 0) {
+      debugger->PrintRegisters(true);
+    } else if (strcmp(identifier, "fpregs") == 0) {
+      debugger->PrintFPRegisters(true);
+    } else if (strcmp(identifier, "sysregs") == 0) {
+      debugger->PrintSystemRegisters(true);
+    } else if (strcmp(identifier, "pc") == 0) {
+      printf("pc = %16p\n", reinterpret_cast<void*>(debugger->pc()));
+    } else {
+      printf(" ** Unknown identifier to print: %s **\n", identifier);
+    }
+
+    return false;
+  }
+
+  if (tok->IsRegister()) {
+    RegisterToken* reg_tok = RegisterToken::Cast(tok);
+    Register reg = reg_tok->value();
+    if (reg.Is32Bits()) {
+      printf("%s = %" PRId32 "\n",
+             reg_tok->Name(),
+             debugger->wreg(reg.code(), Reg31IsStackPointer));
+    } else {
+      printf("%s = %" PRId64 "\n",
+             reg_tok->Name(),
+             debugger->xreg(reg.code(), Reg31IsStackPointer));
+    }
+
+    return false;
+  }
+
+  if (tok->IsFPRegister()) {
+    FPRegister fpreg = FPRegisterToken::Cast(tok)->value();
+    if (fpreg.Is32Bits()) {
+      printf("s%u = %g\n", fpreg.code(), debugger->sreg(fpreg.code()));
+    } else {
+      printf("d%u = %g\n", fpreg.code(), debugger->dreg(fpreg.code()));
+    }
+
+    return false;
+  }
+
+  UNREACHABLE();
+  return false;
+}
+
+
+DebugCommand* PrintCommand::Build(std::vector<Token*> args) {
+  Token* target = NULL;
+  switch (args.size()) {
+    case 2: {
+      target = args[1];
+      if (!target->IsRegister()
+          && !target->IsFPRegister()
+          && !target->IsIdentifier()) {
+        return new InvalidCommand(args, 1, "expects reg or identifier");
+      }
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new PrintCommand(args[0], target);
+}
+
+
+bool MemCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  uint8_t* address = target()->ToAddress(debugger);
+  debugger->PrintMemory(address, count(), format());
+
+  return false;
+}
+
+
+void MemCommand::Print(FILE* out) {
+  fprintf(out, "%s ", name());
+  target()->Print(out);
+  fprintf(out, " %" PRId64 " ", count());
+  format()->Print(out);
+}
+
+
+DebugCommand* MemCommand::Build(std::vector<Token*> args) {
+  if (args.size() < 2) {
+    return new InvalidCommand(args, -1, "too few arguments");
+  }
+
+  Token* target = args[1];
+  IntegerToken* count = NULL;
+  FormatToken* format = NULL;
+
+  if (!target->CanAddressMemory()) {
+    return new InvalidCommand(args, 1, "expects address");
+  }
+
+  switch (args.size()) {
+    case 2: {  // mem addressable [1] [%x]
+      count = new IntegerToken(1);
+      format = new Format<uint64_t>("%016x");
+      break;
+    }
+    case 3: {  // mem addr n [%x] or mem addr [n] %f
+      Token* second = args[2];
+      if (second->IsInteger()) {
+        count = IntegerToken::Cast(second);
+        format = new Format<uint64_t>("%016x");
+      } else if (second->IsFormat()) {
+        count = new IntegerToken(1);
+        format = FormatToken::Cast(second);
+      } else {
+        return new InvalidCommand(args, 2, "expects int or format");
+      }
+      break;
+    }
+    case 4: {  // mem addr n %f
+      Token* second = args[2];
+      Token* third = args[3];
+      if (!second->IsInteger() || !third->IsFormat()) {
+        return new InvalidCommand(args, -1, "mem addr >>int<< %F");
+      }
+
+      count = IntegerToken::Cast(second);
+      format = FormatToken::Cast(third);
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new MemCommand(args[0], target, count, format);
+}
+
+
+UnknownCommand::~UnknownCommand() {
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    delete args_[i];
+  }
+}
+
+
+bool UnknownCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+  USE(debugger);
+
+  printf(" ** Unknown Command:");
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    printf(" ");
+    args_[i]->Print(stdout);
+  }
+  printf(" **\n");
+
+  return false;
+}
+
+
+InvalidCommand::~InvalidCommand() {
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    delete args_[i];
+  }
+}
+
+
+bool InvalidCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+  USE(debugger);
+
+  printf(" ** Invalid Command:");
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    printf(" ");
+    if (i == index_) {
+      printf(">>");
+      args_[i]->Print(stdout);
+      printf("<<");
+    } else {
+      args_[i]->Print(stdout);
+    }
+  }
+  printf(" **\n");
+  printf(" ** %s\n", cause_);
+
+  return false;
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/debugger-a64.h b/disas/libvixl/src/a64/debugger-a64.h
new file mode 100644
index 0000000..542d202
--- /dev/null
+++ b/disas/libvixl/src/a64/debugger-a64.h
@@ -0,0 +1,188 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_DEBUGGER_A64_H_
+#define VIXL_A64_DEBUGGER_A64_H_
+
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <vector>
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/constants-a64.h"
+#include "a64/simulator-a64.h"
+
+namespace vixl {
+
+// Debug instructions.
+//
+// VIXL's macro-assembler and debugger support a few pseudo instructions to
+// make debugging easier. These pseudo instructions do not exist on real
+// hardware.
+//
+// Each debug pseudo instruction is represented by a HLT instruction. The HLT
+// immediate field is used to identify the type of debug pseudo isntruction.
+// Each pseudo instruction use a custom encoding for additional arguments, as
+// described below.
+
+// Unreachable
+//
+// Instruction which should never be executed. This is used as a guard in parts
+// of the code that should not be reachable, such as in data encoded inline in
+// the instructions.
+const Instr kUnreachableOpcode = 0xdeb0;
+
+// Trace
+//  - parameter: TraceParameter stored as a uint32_t
+//  - command: TraceCommand stored as a uint32_t
+//
+// Allow for trace management in the generated code. See the corresponding
+// enums for more information on permitted actions.
+const Instr kTraceOpcode = 0xdeb2;
+const unsigned kTraceParamsOffset = 1 * kInstructionSize;
+const unsigned kTraceCommandOffset = 2 * kInstructionSize;
+const unsigned kTraceLength = 3 * kInstructionSize;
+
+// Log
+//  - parameter: TraceParameter stored as a uint32_t
+//
+// Output the requested information.
+const Instr kLogOpcode = 0xdeb3;
+const unsigned kLogParamsOffset = 1 * kInstructionSize;
+const unsigned kLogLength = 2 * kInstructionSize;
+
+// Trace commands.
+enum TraceCommand {
+  TRACE_ENABLE   = 1,
+  TRACE_DISABLE  = 2
+};
+
+// Trace parameters.
+enum TraceParameters {
+  LOG_DISASM     = 1 << 0,  // Log disassembly.
+  LOG_REGS       = 1 << 1,  // Log general purpose registers.
+  LOG_FP_REGS    = 1 << 2,  // Log floating-point registers.
+  LOG_SYS_REGS   = 1 << 3,  // Log the flags and system registers.
+
+  LOG_STATE      = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS,
+  LOG_ALL        = LOG_DISASM | LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS
+};
+
+// Debugger parameters
+enum DebugParameters {
+  DBG_ACTIVE = 1 << 0,  // The debugger is active.
+  DBG_BREAK  = 1 << 1   // The debugger is at a breakpoint.
+};
+
+// Forward declarations.
+class DebugCommand;
+class Token;
+class FormatToken;
+
+class Debugger : public Simulator {
+ public:
+  Debugger(Decoder* decoder, FILE* stream = stdout);
+
+  virtual void Run();
+  void VisitException(Instruction* instr);
+
+  inline int log_parameters() {
+    // The simulator can control disassembly, so make sure that the Debugger's
+    // log parameters agree with it.
+    if (disasm_trace()) {
+      log_parameters_ |= LOG_DISASM;
+    }
+    return log_parameters_;
+  }
+  inline void set_log_parameters(int parameters) {
+    set_disasm_trace((parameters & LOG_DISASM) != 0);
+    log_parameters_ = parameters;
+
+    update_pending_request();
+  }
+
+  inline int debug_parameters() { return debug_parameters_; }
+  inline void set_debug_parameters(int parameters) {
+    debug_parameters_ = parameters;
+
+    update_pending_request();
+  }
+
+  // Numbers of instructions to execute before the debugger shell is given
+  // back control.
+  inline int steps() { return steps_; }
+  inline void set_steps(int value) {
+    ASSERT(value > 1);
+    steps_ = value;
+  }
+
+  inline bool IsDebuggerRunning() {
+    return (debug_parameters_ & DBG_ACTIVE) != 0;
+  }
+
+  inline bool pending_request() { return pending_request_; }
+  inline void update_pending_request() {
+    const int kLoggingMask = LOG_STATE;
+    const bool logging = (log_parameters_ & kLoggingMask) != 0;
+    const bool debugging = IsDebuggerRunning();
+
+    pending_request_ = logging || debugging;
+  }
+
+  void PrintInstructions(void* address, int64_t count = 1);
+  void PrintMemory(const uint8_t* address,
+                   int64_t count,
+                   const FormatToken* format);
+
+ private:
+  void LogSystemRegisters();
+  void LogRegisters();
+  void LogFPRegisters();
+  void LogProcessorState();
+  char* ReadCommandLine(const char* prompt, char* buffer, int length);
+  void RunDebuggerShell();
+  void DoBreakpoint(Instruction* instr);
+  void DoUnreachable(Instruction* instr);
+  void DoTrace(Instruction* instr);
+  void DoLog(Instruction* instr);
+
+  int  log_parameters_;
+  int  debug_parameters_;
+  bool pending_request_;
+  int steps_;
+  DebugCommand* last_command_;
+  PrintDisassembler* disasm_;
+  Decoder* printer_;
+
+  // Length of the biggest command line accepted by the debugger shell.
+  static const int kMaxDebugShellLine = 256;
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_DEBUGGER_A64_H_
diff --git a/disas/libvixl/src/a64/decoder-a64.cc b/disas/libvixl/src/a64/decoder-a64.cc
new file mode 100644
index 0000000..9e9033c
--- /dev/null
+++ b/disas/libvixl/src/a64/decoder-a64.cc
@@ -0,0 +1,712 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/decoder-a64.h"
+
+namespace vixl {
+// Top-level instruction decode function.
+void Decoder::Decode(Instruction *instr) {
+  if (instr->Bits(28, 27) == 0) {
+    VisitUnallocated(instr);
+  } else {
+    switch (instr->Bits(27, 24)) {
+      // 0:   PC relative addressing.
+      case 0x0: DecodePCRelAddressing(instr); break;
+
+      // 1:   Add/sub immediate.
+      case 0x1: DecodeAddSubImmediate(instr); break;
+
+      // A:   Logical shifted register.
+      //      Add/sub with carry.
+      //      Conditional compare register.
+      //      Conditional compare immediate.
+      //      Conditional select.
+      //      Data processing 1 source.
+      //      Data processing 2 source.
+      // B:   Add/sub shifted register.
+      //      Add/sub extended register.
+      //      Data processing 3 source.
+      case 0xA:
+      case 0xB: DecodeDataProcessing(instr); break;
+
+      // 2:   Logical immediate.
+      //      Move wide immediate.
+      case 0x2: DecodeLogical(instr); break;
+
+      // 3:   Bitfield.
+      //      Extract.
+      case 0x3: DecodeBitfieldExtract(instr); break;
+
+      // 4:   Unconditional branch immediate.
+      //      Exception generation.
+      //      Compare and branch immediate.
+      // 5:   Compare and branch immediate.
+      //      Conditional branch.
+      //      System.
+      // 6,7: Unconditional branch.
+      //      Test and branch immediate.
+      case 0x4:
+      case 0x5:
+      case 0x6:
+      case 0x7: DecodeBranchSystemException(instr); break;
+
+      // 8,9: Load/store register pair post-index.
+      //      Load register literal.
+      //      Load/store register unscaled immediate.
+      //      Load/store register immediate post-index.
+      //      Load/store register immediate pre-index.
+      //      Load/store register offset.
+      //      Load/store exclusive.
+      // C,D: Load/store register pair offset.
+      //      Load/store register pair pre-index.
+      //      Load/store register unsigned immediate.
+      //      Advanced SIMD.
+      case 0x8:
+      case 0x9:
+      case 0xC:
+      case 0xD: DecodeLoadStore(instr); break;
+
+      // E:   FP fixed point conversion.
+      //      FP integer conversion.
+      //      FP data processing 1 source.
+      //      FP compare.
+      //      FP immediate.
+      //      FP data processing 2 source.
+      //      FP conditional compare.
+      //      FP conditional select.
+      //      Advanced SIMD.
+      // F:   FP data processing 3 source.
+      //      Advanced SIMD.
+      case 0xE:
+      case 0xF: DecodeFP(instr); break;
+    }
+  }
+}
+
+void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
+  visitors_.remove(new_visitor);
+  visitors_.push_front(new_visitor);
+}
+
+
+void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
+  visitors_.remove(new_visitor);
+  visitors_.push_back(new_visitor);
+}
+
+
+void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
+                                  DecoderVisitor* registered_visitor) {
+  visitors_.remove(new_visitor);
+  std::list<DecoderVisitor*>::iterator it;
+  for (it = visitors_.begin(); it != visitors_.end(); it++) {
+    if (*it == registered_visitor) {
+      visitors_.insert(it, new_visitor);
+      return;
+    }
+  }
+  // We reached the end of the list. The last element must be
+  // registered_visitor.
+  ASSERT(*it == registered_visitor);
+  visitors_.insert(it, new_visitor);
+}
+
+
+void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
+                                 DecoderVisitor* registered_visitor) {
+  visitors_.remove(new_visitor);
+  std::list<DecoderVisitor*>::iterator it;
+  for (it = visitors_.begin(); it != visitors_.end(); it++) {
+    if (*it == registered_visitor) {
+      it++;
+      visitors_.insert(it, new_visitor);
+      return;
+    }
+  }
+  // We reached the end of the list. The last element must be
+  // registered_visitor.
+  ASSERT(*it == registered_visitor);
+  visitors_.push_back(new_visitor);
+}
+
+
+void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
+  visitors_.remove(visitor);
+}
+
+
+void Decoder::DecodePCRelAddressing(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x0);
+  // We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
+  // decode.
+  ASSERT(instr->Bit(28) == 0x1);
+  VisitPCRelAddressing(instr);
+}
+
+
+void Decoder::DecodeBranchSystemException(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0x4) ||
+         (instr->Bits(27, 24) == 0x5) ||
+         (instr->Bits(27, 24) == 0x6) ||
+         (instr->Bits(27, 24) == 0x7) );
+
+  switch (instr->Bits(31, 29)) {
+    case 0:
+    case 4: {
+      VisitUnconditionalBranch(instr);
+      break;
+    }
+    case 1:
+    case 5: {
+      if (instr->Bit(25) == 0) {
+        VisitCompareBranch(instr);
+      } else {
+        VisitTestBranch(instr);
+      }
+      break;
+    }
+    case 2: {
+      if (instr->Bit(25) == 0) {
+        if ((instr->Bit(24) == 0x1) ||
+            (instr->Mask(0x01000010) == 0x00000010)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitConditionalBranch(instr);
+        }
+      } else {
+        VisitUnallocated(instr);
+      }
+      break;
+    }
+    case 6: {
+      if (instr->Bit(25) == 0) {
+        if (instr->Bit(24) == 0) {
+          if ((instr->Bits(4, 2) != 0) ||
+              (instr->Mask(0x00E0001D) == 0x00200001) ||
+              (instr->Mask(0x00E0001D) == 0x00400001) ||
+              (instr->Mask(0x00E0001E) == 0x00200002) ||
+              (instr->Mask(0x00E0001E) == 0x00400002) ||
+              (instr->Mask(0x00E0001C) == 0x00600000) ||
+              (instr->Mask(0x00E0001C) == 0x00800000) ||
+              (instr->Mask(0x00E0001F) == 0x00A00000) ||
+              (instr->Mask(0x00C0001C) == 0x00C00000)) {
+            VisitUnallocated(instr);
+          } else {
+            VisitException(instr);
+          }
+        } else {
+          if (instr->Bits(23, 22) == 0) {
+            const Instr masked_003FF0E0 = instr->Mask(0x003FF0E0);
+            if ((instr->Bits(21, 19) == 0x4) ||
+                (masked_003FF0E0 == 0x00033000) ||
+                (masked_003FF0E0 == 0x003FF020) ||
+                (masked_003FF0E0 == 0x003FF060) ||
+                (masked_003FF0E0 == 0x003FF0E0) ||
+                (instr->Mask(0x00388000) == 0x00008000) ||
+                (instr->Mask(0x0038E000) == 0x00000000) ||
+                (instr->Mask(0x0039E000) == 0x00002000) ||
+                (instr->Mask(0x003AE000) == 0x00002000) ||
+                (instr->Mask(0x003CE000) == 0x00042000) ||
+                (instr->Mask(0x003FFFC0) == 0x000320C0) ||
+                (instr->Mask(0x003FF100) == 0x00032100) ||
+                (instr->Mask(0x003FF200) == 0x00032200) ||
+                (instr->Mask(0x003FF400) == 0x00032400) ||
+                (instr->Mask(0x003FF800) == 0x00032800) ||
+                (instr->Mask(0x0038F000) == 0x00005000) ||
+                (instr->Mask(0x0038E000) == 0x00006000)) {
+              VisitUnallocated(instr);
+            } else {
+              VisitSystem(instr);
+            }
+          } else {
+            VisitUnallocated(instr);
+          }
+        }
+      } else {
+        if ((instr->Bit(24) == 0x1) ||
+            (instr->Bits(20, 16) != 0x1F) ||
+            (instr->Bits(15, 10) != 0) ||
+            (instr->Bits(4, 0) != 0) ||
+            (instr->Bits(24, 21) == 0x3) ||
+            (instr->Bits(24, 22) == 0x3)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitUnconditionalBranchToRegister(instr);
+        }
+      }
+      break;
+    }
+    case 3:
+    case 7: {
+      VisitUnallocated(instr);
+      break;
+    }
+  }
+}
+
+
+void Decoder::DecodeLoadStore(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0x8) ||
+         (instr->Bits(27, 24) == 0x9) ||
+         (instr->Bits(27, 24) == 0xC) ||
+         (instr->Bits(27, 24) == 0xD) );
+
+  if (instr->Bit(24) == 0) {
+    if (instr->Bit(28) == 0) {
+      if (instr->Bit(29) == 0) {
+        if (instr->Bit(26) == 0) {
+          // TODO: VisitLoadStoreExclusive.
+          VisitUnimplemented(instr);
+        } else {
+          DecodeAdvSIMDLoadStore(instr);
+        }
+      } else {
+        if ((instr->Bits(31, 30) == 0x3) ||
+            (instr->Mask(0xC4400000) == 0x40000000)) {
+          VisitUnallocated(instr);
+        } else {
+          if (instr->Bit(23) == 0) {
+            if (instr->Mask(0xC4400000) == 0xC0400000) {
+              VisitUnallocated(instr);
+            } else {
+              VisitLoadStorePairNonTemporal(instr);
+            }
+          } else {
+            VisitLoadStorePairPostIndex(instr);
+          }
+        }
+      }
+    } else {
+      if (instr->Bit(29) == 0) {
+        if (instr->Mask(0xC4000000) == 0xC4000000) {
+          VisitUnallocated(instr);
+        } else {
+          VisitLoadLiteral(instr);
+        }
+      } else {
+        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
+            (instr->Mask(0x44800000) == 0x44800000) ||
+            (instr->Mask(0x84800000) == 0x84800000)) {
+          VisitUnallocated(instr);
+        } else {
+          if (instr->Bit(21) == 0) {
+            switch (instr->Bits(11, 10)) {
+              case 0: {
+                VisitLoadStoreUnscaledOffset(instr);
+                break;
+              }
+              case 1: {
+                if (instr->Mask(0xC4C00000) == 0xC0800000) {
+                  VisitUnallocated(instr);
+                } else {
+                  VisitLoadStorePostIndex(instr);
+                }
+                break;
+              }
+              case 2: {
+                // TODO: VisitLoadStoreRegisterOffsetUnpriv.
+                VisitUnimplemented(instr);
+                break;
+              }
+              case 3: {
+                if (instr->Mask(0xC4C00000) == 0xC0800000) {
+                  VisitUnallocated(instr);
+                } else {
+                  VisitLoadStorePreIndex(instr);
+                }
+                break;
+              }
+            }
+          } else {
+            if (instr->Bits(11, 10) == 0x2) {
+              if (instr->Bit(14) == 0) {
+                VisitUnallocated(instr);
+              } else {
+                VisitLoadStoreRegisterOffset(instr);
+              }
+            } else {
+              VisitUnallocated(instr);
+            }
+          }
+        }
+      }
+    }
+  } else {
+    if (instr->Bit(28) == 0) {
+      if (instr->Bit(29) == 0) {
+        VisitUnallocated(instr);
+      } else {
+        if ((instr->Bits(31, 30) == 0x3) ||
+            (instr->Mask(0xC4400000) == 0x40000000)) {
+          VisitUnallocated(instr);
+        } else {
+          if (instr->Bit(23) == 0) {
+            VisitLoadStorePairOffset(instr);
+          } else {
+            VisitLoadStorePairPreIndex(instr);
+          }
+        }
+      }
+    } else {
+      if (instr->Bit(29) == 0) {
+        VisitUnallocated(instr);
+      } else {
+        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
+            (instr->Mask(0x44800000) == 0x44800000) ||
+            (instr->Mask(0x84800000) == 0x84800000)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitLoadStoreUnsignedOffset(instr);
+        }
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeLogical(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x2);
+
+  if (instr->Mask(0x80400000) == 0x00400000) {
+    VisitUnallocated(instr);
+  } else {
+    if (instr->Bit(23) == 0) {
+      VisitLogicalImmediate(instr);
+    } else {
+      if (instr->Bits(30, 29) == 0x1) {
+        VisitUnallocated(instr);
+      } else {
+        VisitMoveWideImmediate(instr);
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeBitfieldExtract(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x3);
+
+  if ((instr->Mask(0x80400000) == 0x80000000) ||
+      (instr->Mask(0x80400000) == 0x00400000) ||
+      (instr->Mask(0x80008000) == 0x00008000)) {
+    VisitUnallocated(instr);
+  } else if (instr->Bit(23) == 0) {
+    if ((instr->Mask(0x80200000) == 0x00200000) ||
+        (instr->Mask(0x60000000) == 0x60000000)) {
+      VisitUnallocated(instr);
+    } else {
+      VisitBitfield(instr);
+    }
+  } else {
+    if ((instr->Mask(0x60200000) == 0x00200000) ||
+        (instr->Mask(0x60000000) != 0x00000000)) {
+      VisitUnallocated(instr);
+    } else {
+      VisitExtract(instr);
+    }
+  }
+}
+
+
+void Decoder::DecodeAddSubImmediate(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x1);
+  if (instr->Bit(23) == 1) {
+    VisitUnallocated(instr);
+  } else {
+    VisitAddSubImmediate(instr);
+  }
+}
+
+
+void Decoder::DecodeDataProcessing(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0xA) ||
+         (instr->Bits(27, 24) == 0xB) );
+
+  if (instr->Bit(24) == 0) {
+    if (instr->Bit(28) == 0) {
+      if (instr->Mask(0x80008000) == 0x00008000) {
+        VisitUnallocated(instr);
+      } else {
+        VisitLogicalShifted(instr);
+      }
+    } else {
+      switch (instr->Bits(23, 21)) {
+        case 0: {
+          if (instr->Mask(0x0000FC00) != 0) {
+            VisitUnallocated(instr);
+          } else {
+            VisitAddSubWithCarry(instr);
+          }
+          break;
+        }
+        case 2: {
+          if ((instr->Bit(29) == 0) ||
+              (instr->Mask(0x00000410) != 0)) {
+            VisitUnallocated(instr);
+          } else {
+            if (instr->Bit(11) == 0) {
+              VisitConditionalCompareRegister(instr);
+            } else {
+              VisitConditionalCompareImmediate(instr);
+            }
+          }
+          break;
+        }
+        case 4: {
+          if (instr->Mask(0x20000800) != 0x00000000) {
+            VisitUnallocated(instr);
+          } else {
+            VisitConditionalSelect(instr);
+          }
+          break;
+        }
+        case 6: {
+          if (instr->Bit(29) == 0x1) {
+            VisitUnallocated(instr);
+          } else {
+            if (instr->Bit(30) == 0) {
+              if ((instr->Bit(15) == 0x1) ||
+                  (instr->Bits(15, 11) == 0) ||
+                  (instr->Bits(15, 12) == 0x1) ||
+                  (instr->Bits(15, 12) == 0x3) ||
+                  (instr->Bits(15, 13) == 0x3) ||
+                  (instr->Mask(0x8000EC00) == 0x00004C00) ||
+                  (instr->Mask(0x8000E800) == 0x80004000) ||
+                  (instr->Mask(0x8000E400) == 0x80004000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitDataProcessing2Source(instr);
+              }
+            } else {
+              if ((instr->Bit(13) == 1) ||
+                  (instr->Bits(20, 16) != 0) ||
+                  (instr->Bits(15, 14) != 0) ||
+                  (instr->Mask(0xA01FFC00) == 0x00000C00) ||
+                  (instr->Mask(0x201FF800) == 0x00001800)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitDataProcessing1Source(instr);
+              }
+            }
+            break;
+          }
+        }
+        case 1:
+        case 3:
+        case 5:
+        case 7: VisitUnallocated(instr); break;
+      }
+    }
+  } else {
+    if (instr->Bit(28) == 0) {
+     if (instr->Bit(21) == 0) {
+        if ((instr->Bits(23, 22) == 0x3) ||
+            (instr->Mask(0x80008000) == 0x00008000)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitAddSubShifted(instr);
+        }
+      } else {
+        if ((instr->Mask(0x00C00000) != 0x00000000) ||
+            (instr->Mask(0x00001400) == 0x00001400) ||
+            (instr->Mask(0x00001800) == 0x00001800)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitAddSubExtended(instr);
+        }
+      }
+    } else {
+      if ((instr->Bit(30) == 0x1) ||
+          (instr->Bits(30, 29) == 0x1) ||
+          (instr->Mask(0xE0600000) == 0x00200000) ||
+          (instr->Mask(0xE0608000) == 0x00400000) ||
+          (instr->Mask(0x60608000) == 0x00408000) ||
+          (instr->Mask(0x60E00000) == 0x00E00000) ||
+          (instr->Mask(0x60E00000) == 0x00800000) ||
+          (instr->Mask(0x60E00000) == 0x00600000)) {
+        VisitUnallocated(instr);
+      } else {
+        VisitDataProcessing3Source(instr);
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeFP(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0xE) ||
+         (instr->Bits(27, 24) == 0xF) );
+
+  if (instr->Bit(28) == 0) {
+    DecodeAdvSIMDDataProcessing(instr);
+  } else {
+    if (instr->Bit(29) == 1) {
+      VisitUnallocated(instr);
+    } else {
+      if (instr->Bits(31, 30) == 0x3) {
+        VisitUnallocated(instr);
+      } else if (instr->Bits(31, 30) == 0x1) {
+        DecodeAdvSIMDDataProcessing(instr);
+      } else {
+        if (instr->Bit(24) == 0) {
+          if (instr->Bit(21) == 0) {
+            if ((instr->Bit(23) == 1) ||
+                (instr->Bit(18) == 1) ||
+                (instr->Mask(0x80008000) == 0x00000000) ||
+                (instr->Mask(0x000E0000) == 0x00000000) ||
+                (instr->Mask(0x000E0000) == 0x000A0000) ||
+                (instr->Mask(0x00160000) == 0x00000000) ||
+                (instr->Mask(0x00160000) == 0x00120000)) {
+              VisitUnallocated(instr);
+            } else {
+              VisitFPFixedPointConvert(instr);
+            }
+          } else {
+            if (instr->Bits(15, 10) == 32) {
+              VisitUnallocated(instr);
+            } else if (instr->Bits(15, 10) == 0) {
+              if ((instr->Bits(23, 22) == 0x3) ||
+                  (instr->Mask(0x000E0000) == 0x000A0000) ||
+                  (instr->Mask(0x000E0000) == 0x000C0000) ||
+                  (instr->Mask(0x00160000) == 0x00120000) ||
+                  (instr->Mask(0x00160000) == 0x00140000) ||
+                  (instr->Mask(0x20C40000) == 0x00800000) ||
+                  (instr->Mask(0x20C60000) == 0x00840000) ||
+                  (instr->Mask(0xA0C60000) == 0x80060000) ||
+                  (instr->Mask(0xA0C60000) == 0x00860000) ||
+                  (instr->Mask(0xA0C60000) == 0x00460000) ||
+                  (instr->Mask(0xA0CE0000) == 0x80860000) ||
+                  (instr->Mask(0xA0CE0000) == 0x804E0000) ||
+                  (instr->Mask(0xA0CE0000) == 0x000E0000) ||
+                  (instr->Mask(0xA0D60000) == 0x00160000) ||
+                  (instr->Mask(0xA0D60000) == 0x80560000) ||
+                  (instr->Mask(0xA0D60000) == 0x80960000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPIntegerConvert(instr);
+              }
+            } else if (instr->Bits(14, 10) == 16) {
+              const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
+              if ((instr->Mask(0x80180000) != 0) ||
+                  (masked_A0DF8000 == 0x00020000) ||
+                  (masked_A0DF8000 == 0x00030000) ||
+                  (masked_A0DF8000 == 0x00068000) ||
+                  (masked_A0DF8000 == 0x00428000) ||
+                  (masked_A0DF8000 == 0x00430000) ||
+                  (masked_A0DF8000 == 0x00468000) ||
+                  (instr->Mask(0xA0D80000) == 0x00800000) ||
+                  (instr->Mask(0xA0DE0000) == 0x00C00000) ||
+                  (instr->Mask(0xA0DF0000) == 0x00C30000) ||
+                  (instr->Mask(0xA0DC0000) == 0x00C40000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPDataProcessing1Source(instr);
+              }
+            } else if (instr->Bits(13, 10) == 8) {
+              if ((instr->Bits(15, 14) != 0) ||
+                  (instr->Bits(2, 0) != 0) ||
+                  (instr->Mask(0x80800000) != 0x00000000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPCompare(instr);
+              }
+            } else if (instr->Bits(12, 10) == 4) {
+              if ((instr->Bits(9, 5) != 0) ||
+                  (instr->Mask(0x80800000) != 0x00000000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPImmediate(instr);
+              }
+            } else {
+              if (instr->Mask(0x80800000) != 0x00000000) {
+                VisitUnallocated(instr);
+              } else {
+                switch (instr->Bits(11, 10)) {
+                  case 1: {
+                    VisitFPConditionalCompare(instr);
+                    break;
+                  }
+                  case 2: {
+                    if ((instr->Bits(15, 14) == 0x3) ||
+                        (instr->Mask(0x00009000) == 0x00009000) ||
+                        (instr->Mask(0x0000A000) == 0x0000A000)) {
+                      VisitUnallocated(instr);
+                    } else {
+                      VisitFPDataProcessing2Source(instr);
+                    }
+                    break;
+                  }
+                  case 3: {
+                    VisitFPConditionalSelect(instr);
+                    break;
+                  }
+                  default: UNREACHABLE();
+                }
+              }
+            }
+          }
+        } else {
+          // Bit 30 == 1 has been handled earlier.
+          ASSERT(instr->Bit(30) == 0);
+          if (instr->Mask(0xA0800000) != 0) {
+            VisitUnallocated(instr);
+          } else {
+            VisitFPDataProcessing3Source(instr);
+          }
+        }
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) {
+  // TODO: Implement Advanced SIMD load/store instruction decode.
+  ASSERT(instr->Bits(29, 25) == 0x6);
+  VisitUnimplemented(instr);
+}
+
+
+void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) {
+  // TODO: Implement Advanced SIMD data processing instruction decode.
+  ASSERT(instr->Bits(27, 25) == 0x7);
+  VisitUnimplemented(instr);
+}
+
+
+#define DEFINE_VISITOR_CALLERS(A)                                              \
+  void Decoder::Visit##A(Instruction *instr) {                                 \
+    ASSERT(instr->Mask(A##FMask) == A##Fixed);                                 \
+    std::list<DecoderVisitor*>::iterator it;                                   \
+    for (it = visitors_.begin(); it != visitors_.end(); it++) {                \
+      (*it)->Visit##A(instr);                                                  \
+    }                                                                          \
+  }
+VISITOR_LIST(DEFINE_VISITOR_CALLERS)
+#undef DEFINE_VISITOR_CALLERS
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/decoder-a64.h b/disas/libvixl/src/a64/decoder-a64.h
new file mode 100644
index 0000000..bbbbd81
--- /dev/null
+++ b/disas/libvixl/src/a64/decoder-a64.h
@@ -0,0 +1,198 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_DECODER_A64_H_
+#define VIXL_A64_DECODER_A64_H_
+
+#include <list>
+
+#include "globals.h"
+#include "a64/instructions-a64.h"
+
+
+// List macro containing all visitors needed by the decoder class.
+
+#define VISITOR_LIST(V)             \
+  V(PCRelAddressing)                \
+  V(AddSubImmediate)                \
+  V(LogicalImmediate)               \
+  V(MoveWideImmediate)              \
+  V(Bitfield)                       \
+  V(Extract)                        \
+  V(UnconditionalBranch)            \
+  V(UnconditionalBranchToRegister)  \
+  V(CompareBranch)                  \
+  V(TestBranch)                     \
+  V(ConditionalBranch)              \
+  V(System)                         \
+  V(Exception)                      \
+  V(LoadStorePairPostIndex)         \
+  V(LoadStorePairOffset)            \
+  V(LoadStorePairPreIndex)          \
+  V(LoadStorePairNonTemporal)       \
+  V(LoadLiteral)                    \
+  V(LoadStoreUnscaledOffset)        \
+  V(LoadStorePostIndex)             \
+  V(LoadStorePreIndex)              \
+  V(LoadStoreRegisterOffset)        \
+  V(LoadStoreUnsignedOffset)        \
+  V(LogicalShifted)                 \
+  V(AddSubShifted)                  \
+  V(AddSubExtended)                 \
+  V(AddSubWithCarry)                \
+  V(ConditionalCompareRegister)     \
+  V(ConditionalCompareImmediate)    \
+  V(ConditionalSelect)              \
+  V(DataProcessing1Source)          \
+  V(DataProcessing2Source)          \
+  V(DataProcessing3Source)          \
+  V(FPCompare)                      \
+  V(FPConditionalCompare)           \
+  V(FPConditionalSelect)            \
+  V(FPImmediate)                    \
+  V(FPDataProcessing1Source)        \
+  V(FPDataProcessing2Source)        \
+  V(FPDataProcessing3Source)        \
+  V(FPIntegerConvert)               \
+  V(FPFixedPointConvert)            \
+  V(Unallocated)                    \
+  V(Unimplemented)
+
+namespace vixl {
+
+// The Visitor interface. Disassembler and simulator (and other tools)
+// must provide implementations for all of these functions.
+class DecoderVisitor {
+ public:
+  #define DECLARE(A) virtual void Visit##A(Instruction* instr) = 0;
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+  virtual ~DecoderVisitor() {}
+
+ private:
+  // Visitors are registered in a list.
+  std::list<DecoderVisitor*> visitors_;
+
+  friend class Decoder;
+};
+
+
+class Decoder: public DecoderVisitor {
+ public:
+  Decoder() {}
+
+  // Top-level instruction decoder function. Decodes an instruction and calls
+  // the visitor functions registered with the Decoder class.
+  void Decode(Instruction *instr);
+
+  // Register a new visitor class with the decoder.
+  // Decode() will call the corresponding visitor method from all registered
+  // visitor classes when decoding reaches the leaf node of the instruction
+  // decode tree.
+  // Visitors are called in the order.
+  // A visitor can only be registered once.
+  // Registering an already registered visitor will update its position.
+  //
+  //   d.AppendVisitor(V1);
+  //   d.AppendVisitor(V2);
+  //   d.PrependVisitor(V2);            // Move V2 at the start of the list.
+  //   d.InsertVisitorBefore(V3, V2);
+  //   d.AppendVisitor(V4);
+  //   d.AppendVisitor(V4);             // No effect.
+  //
+  //   d.Decode(i);
+  //
+  // will call in order visitor methods in V3, V2, V1, V4.
+  void AppendVisitor(DecoderVisitor* visitor);
+  void PrependVisitor(DecoderVisitor* visitor);
+  void InsertVisitorBefore(DecoderVisitor* new_visitor,
+                           DecoderVisitor* registered_visitor);
+  void InsertVisitorAfter(DecoderVisitor* new_visitor,
+                          DecoderVisitor* registered_visitor);
+
+  // Remove a previously registered visitor class from the list of visitors
+  // stored by the decoder.
+  void RemoveVisitor(DecoderVisitor* visitor);
+
+  #define DECLARE(A) void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+ private:
+  // Decode the PC relative addressing instruction, and call the corresponding
+  // visitors.
+  // On entry, instruction bits 27:24 = 0x0.
+  void DecodePCRelAddressing(Instruction* instr);
+
+  // Decode the add/subtract immediate instruction, and call the correspoding
+  // visitors.
+  // On entry, instruction bits 27:24 = 0x1.
+  void DecodeAddSubImmediate(Instruction* instr);
+
+  // Decode the branch, system command, and exception generation parts of
+  // the instruction tree, and call the corresponding visitors.
+  // On entry, instruction bits 27:24 = {0x4, 0x5, 0x6, 0x7}.
+  void DecodeBranchSystemException(Instruction* instr);
+
+  // Decode the load and store parts of the instruction tree, and call
+  // the corresponding visitors.
+  // On entry, instruction bits 27:24 = {0x8, 0x9, 0xC, 0xD}.
+  void DecodeLoadStore(Instruction* instr);
+
+  // Decode the logical immediate and move wide immediate parts of the
+  // instruction tree, and call the corresponding visitors.
+  // On entry, instruction bits 27:24 = 0x2.
+  void DecodeLogical(Instruction* instr);
+
+  // Decode the bitfield and extraction parts of the instruction tree,
+  // and call the corresponding visitors.
+  // On entry, instruction bits 27:24 = 0x3.
+  void DecodeBitfieldExtract(Instruction* instr);
+
+  // Decode the data processing parts of the instruction tree, and call the
+  // corresponding visitors.
+  // On entry, instruction bits 27:24 = {0x1, 0xA, 0xB}.
+  void DecodeDataProcessing(Instruction* instr);
+
+  // Decode the floating point parts of the instruction tree, and call the
+  // corresponding visitors.
+  // On entry, instruction bits 27:24 = {0xE, 0xF}.
+  void DecodeFP(Instruction* instr);
+
+  // Decode the Advanced SIMD (NEON) load/store part of the instruction tree,
+  // and call the corresponding visitors.
+  // On entry, instruction bits 29:25 = 0x6.
+  void DecodeAdvSIMDLoadStore(Instruction* instr);
+
+  // Decode the Advanced SIMD (NEON) data processing part of the instruction
+  // tree, and call the corresponding visitors.
+  // On entry, instruction bits 27:25 = 0x7.
+  void DecodeAdvSIMDDataProcessing(Instruction* instr);
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_DECODER_A64_H_
diff --git a/disas/libvixl/src/a64/disasm-a64.cc b/disas/libvixl/src/a64/disasm-a64.cc
new file mode 100644
index 0000000..4a49748
--- /dev/null
+++ b/disas/libvixl/src/a64/disasm-a64.cc
@@ -0,0 +1,1678 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/disasm-a64.h"
+
+namespace vixl {
+
+Disassembler::Disassembler() {
+  buffer_size_ = 256;
+  buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
+  buffer_pos_ = 0;
+  own_buffer_ = true;
+}
+
+
+Disassembler::Disassembler(char* text_buffer, int buffer_size) {
+  buffer_size_ = buffer_size;
+  buffer_ = text_buffer;
+  buffer_pos_ = 0;
+  own_buffer_ = false;
+}
+
+
+Disassembler::~Disassembler() {
+  if (own_buffer_) {
+    free(buffer_);
+  }
+}
+
+
+char* Disassembler::GetOutput() {
+  return buffer_;
+}
+
+
+void Disassembler::VisitAddSubImmediate(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
+                  (instr->ImmAddSub() == 0) ? true : false;
+  const char *mnemonic = "";
+  const char *form = "'Rds, 'Rns, 'IAddSub";
+  const char *form_cmp = "'Rns, 'IAddSub";
+  const char *form_mov = "'Rds, 'Rns";
+
+  switch (instr->Mask(AddSubImmediateMask)) {
+    case ADD_w_imm:
+    case ADD_x_imm: {
+      mnemonic = "add";
+      if (stack_op) {
+        mnemonic = "mov";
+        form = form_mov;
+      }
+      break;
+    }
+    case ADDS_w_imm:
+    case ADDS_x_imm: {
+      mnemonic = "adds";
+      if (rd_is_zr) {
+        mnemonic = "cmn";
+        form = form_cmp;
+      }
+      break;
+    }
+    case SUB_w_imm:
+    case SUB_x_imm: mnemonic = "sub"; break;
+    case SUBS_w_imm:
+    case SUBS_x_imm: {
+      mnemonic = "subs";
+      if (rd_is_zr) {
+        mnemonic = "cmp";
+        form = form_cmp;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitAddSubShifted(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm'HDP";
+  const char *form_cmp = "'Rn, 'Rm'HDP";
+  const char *form_neg = "'Rd, 'Rm'HDP";
+
+  switch (instr->Mask(AddSubShiftedMask)) {
+    case ADD_w_shift:
+    case ADD_x_shift: mnemonic = "add"; break;
+    case ADDS_w_shift:
+    case ADDS_x_shift: {
+      mnemonic = "adds";
+      if (rd_is_zr) {
+        mnemonic = "cmn";
+        form = form_cmp;
+      }
+      break;
+    }
+    case SUB_w_shift:
+    case SUB_x_shift: {
+      mnemonic = "sub";
+      if (rn_is_zr) {
+        mnemonic = "neg";
+        form = form_neg;
+      }
+      break;
+    }
+    case SUBS_w_shift:
+    case SUBS_x_shift: {
+      mnemonic = "subs";
+      if (rd_is_zr) {
+        mnemonic = "cmp";
+        form = form_cmp;
+      } else if (rn_is_zr) {
+        mnemonic = "negs";
+        form = form_neg;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitAddSubExtended(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  const char *mnemonic = "";
+  Extend mode = static_cast<Extend>(instr->ExtendMode());
+  const char *form = ((mode == UXTX) || (mode == SXTX)) ?
+                     "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
+  const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
+                         "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
+
+  switch (instr->Mask(AddSubExtendedMask)) {
+    case ADD_w_ext:
+    case ADD_x_ext: mnemonic = "add"; break;
+    case ADDS_w_ext:
+    case ADDS_x_ext: {
+      mnemonic = "adds";
+      if (rd_is_zr) {
+        mnemonic = "cmn";
+        form = form_cmp;
+      }
+      break;
+    }
+    case SUB_w_ext:
+    case SUB_x_ext: mnemonic = "sub"; break;
+    case SUBS_w_ext:
+    case SUBS_x_ext: {
+      mnemonic = "subs";
+      if (rd_is_zr) {
+        mnemonic = "cmp";
+        form = form_cmp;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm";
+  const char *form_neg = "'Rd, 'Rm";
+
+  switch (instr->Mask(AddSubWithCarryMask)) {
+    case ADC_w:
+    case ADC_x: mnemonic = "adc"; break;
+    case ADCS_w:
+    case ADCS_x: mnemonic = "adcs"; break;
+    case SBC_w:
+    case SBC_x: {
+      mnemonic = "sbc";
+      if (rn_is_zr) {
+        mnemonic = "ngc";
+        form = form_neg;
+      }
+      break;
+    }
+    case SBCS_w:
+    case SBCS_x: {
+      mnemonic = "sbcs";
+      if (rn_is_zr) {
+        mnemonic = "ngcs";
+        form = form_neg;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLogicalImmediate(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rds, 'Rn, 'ITri";
+
+  if (instr->ImmLogical() == 0) {
+    // The immediate encoded in the instruction is not in the expected format.
+    Format(instr, "unallocated", "(LogicalImmediate)");
+    return;
+  }
+
+  switch (instr->Mask(LogicalImmediateMask)) {
+    case AND_w_imm:
+    case AND_x_imm: mnemonic = "and"; break;
+    case ORR_w_imm:
+    case ORR_x_imm: {
+      mnemonic = "orr";
+      unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
+                                                        : kWRegSize;
+      if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
+        mnemonic = "mov";
+        form = "'Rds, 'ITri";
+      }
+      break;
+    }
+    case EOR_w_imm:
+    case EOR_x_imm: mnemonic = "eor"; break;
+    case ANDS_w_imm:
+    case ANDS_x_imm: {
+      mnemonic = "ands";
+      if (rd_is_zr) {
+        mnemonic = "tst";
+        form = "'Rn, 'ITri";
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
+  ASSERT((reg_size == kXRegSize) ||
+         ((reg_size == kWRegSize) && (value <= 0xffffffff)));
+
+  // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
+  if (((value & 0xffffffffffff0000UL) == 0UL) ||
+      ((value & 0xffffffff0000ffffUL) == 0UL) ||
+      ((value & 0xffff0000ffffffffUL) == 0UL) ||
+      ((value & 0x0000ffffffffffffUL) == 0UL)) {
+    return true;
+  }
+
+  // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
+  if ((reg_size == kXRegSize) &&
+      (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) ||
+       ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) ||
+       ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) ||
+       ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) {
+    return true;
+  }
+  if ((reg_size == kWRegSize) &&
+      (((value & 0xffff0000) == 0xffff0000) ||
+       ((value & 0x0000ffff) == 0x0000ffff))) {
+    return true;
+  }
+  return false;
+}
+
+
+void Disassembler::VisitLogicalShifted(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm'HLo";
+
+  switch (instr->Mask(LogicalShiftedMask)) {
+    case AND_w:
+    case AND_x: mnemonic = "and"; break;
+    case BIC_w:
+    case BIC_x: mnemonic = "bic"; break;
+    case EOR_w:
+    case EOR_x: mnemonic = "eor"; break;
+    case EON_w:
+    case EON_x: mnemonic = "eon"; break;
+    case BICS_w:
+    case BICS_x: mnemonic = "bics"; break;
+    case ANDS_w:
+    case ANDS_x: {
+      mnemonic = "ands";
+      if (rd_is_zr) {
+        mnemonic = "tst";
+        form = "'Rn, 'Rm'HLo";
+      }
+      break;
+    }
+    case ORR_w:
+    case ORR_x: {
+      mnemonic = "orr";
+      if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
+        mnemonic = "mov";
+        form = "'Rd, 'Rm";
+      }
+      break;
+    }
+    case ORN_w:
+    case ORN_x: {
+      mnemonic = "orn";
+      if (rn_is_zr) {
+        mnemonic = "mvn";
+        form = "'Rd, 'Rm'HLo";
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
+
+  switch (instr->Mask(ConditionalCompareRegisterMask)) {
+    case CCMN_w:
+    case CCMN_x: mnemonic = "ccmn"; break;
+    case CCMP_w:
+    case CCMP_x: mnemonic = "ccmp"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
+
+  switch (instr->Mask(ConditionalCompareImmediateMask)) {
+    case CCMN_w_imm:
+    case CCMN_x_imm: mnemonic = "ccmn"; break;
+    case CCMP_w_imm:
+    case CCMP_x_imm: mnemonic = "ccmp"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitConditionalSelect(Instruction* instr) {
+  bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
+  bool rn_is_rm = (instr->Rn() == instr->Rm());
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
+  const char *form_test = "'Rd, 'CInv";
+  const char *form_update = "'Rd, 'Rn, 'CInv";
+
+  Condition cond = static_cast<Condition>(instr->Condition());
+  bool invertible_cond = (cond != al) && (cond != nv);
+
+  switch (instr->Mask(ConditionalSelectMask)) {
+    case CSEL_w:
+    case CSEL_x: mnemonic = "csel"; break;
+    case CSINC_w:
+    case CSINC_x: {
+      mnemonic = "csinc";
+      if (rnm_is_zr && invertible_cond) {
+        mnemonic = "cset";
+        form = form_test;
+      } else if (rn_is_rm && invertible_cond) {
+        mnemonic = "cinc";
+        form = form_update;
+      }
+      break;
+    }
+    case CSINV_w:
+    case CSINV_x: {
+      mnemonic = "csinv";
+      if (rnm_is_zr && invertible_cond) {
+        mnemonic = "csetm";
+        form = form_test;
+      } else if (rn_is_rm && invertible_cond) {
+        mnemonic = "cinv";
+        form = form_update;
+      }
+      break;
+    }
+    case CSNEG_w:
+    case CSNEG_x: {
+      mnemonic = "csneg";
+      if (rn_is_rm && invertible_cond) {
+        mnemonic = "cneg";
+        form = form_update;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitBitfield(Instruction* instr) {
+  unsigned s = instr->ImmS();
+  unsigned r = instr->ImmR();
+  unsigned rd_size_minus_1 =
+    ((instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
+  const char *mnemonic = "";
+  const char *form = "";
+  const char *form_shift_right = "'Rd, 'Rn, 'IBr";
+  const char *form_extend = "'Rd, 'Wn";
+  const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
+  const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
+  const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
+
+  switch (instr->Mask(BitfieldMask)) {
+    case SBFM_w:
+    case SBFM_x: {
+      mnemonic = "sbfx";
+      form = form_bfx;
+      if (r == 0) {
+        form = form_extend;
+        if (s == 7) {
+          mnemonic = "sxtb";
+        } else if (s == 15) {
+          mnemonic = "sxth";
+        } else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
+          mnemonic = "sxtw";
+        } else {
+          form = form_bfx;
+        }
+      } else if (s == rd_size_minus_1) {
+        mnemonic = "asr";
+        form = form_shift_right;
+      } else if (s < r) {
+        mnemonic = "sbfiz";
+        form = form_bfiz;
+      }
+      break;
+    }
+    case UBFM_w:
+    case UBFM_x: {
+      mnemonic = "ubfx";
+      form = form_bfx;
+      if (r == 0) {
+        form = form_extend;
+        if (s == 7) {
+          mnemonic = "uxtb";
+        } else if (s == 15) {
+          mnemonic = "uxth";
+        } else {
+          form = form_bfx;
+        }
+      }
+      if (s == rd_size_minus_1) {
+        mnemonic = "lsr";
+        form = form_shift_right;
+      } else if (r == s + 1) {
+        mnemonic = "lsl";
+        form = form_lsl;
+      } else if (s < r) {
+        mnemonic = "ubfiz";
+        form = form_bfiz;
+      }
+      break;
+    }
+    case BFM_w:
+    case BFM_x: {
+      mnemonic = "bfxil";
+      form = form_bfx;
+      if (s < r) {
+        mnemonic = "bfi";
+        form = form_bfiz;
+      }
+    }
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitExtract(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
+
+  switch (instr->Mask(ExtractMask)) {
+    case EXTR_w:
+    case EXTR_x: {
+      if (instr->Rn() == instr->Rm()) {
+        mnemonic = "ror";
+        form = "'Rd, 'Rn, 'IExtract";
+      } else {
+        mnemonic = "extr";
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitPCRelAddressing(Instruction* instr) {
+  switch (instr->Mask(PCRelAddressingMask)) {
+    case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
+    // ADRP is not implemented.
+    default: Format(instr, "unimplemented", "(PCRelAddressing)");
+  }
+}
+
+
+void Disassembler::VisitConditionalBranch(Instruction* instr) {
+  switch (instr->Mask(ConditionalBranchMask)) {
+    case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Disassembler::VisitUnconditionalBranchToRegister(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Xn";
+
+  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
+    case BR: mnemonic = "br"; break;
+    case BLR: mnemonic = "blr"; break;
+    case RET: {
+      mnemonic = "ret";
+      if (instr->Rn() == kLinkRegCode) {
+        form = NULL;
+      }
+      break;
+    }
+    default: form = "(UnconditionalBranchToRegister)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'BImmUncn";
+
+  switch (instr->Mask(UnconditionalBranchMask)) {
+    case B: mnemonic = "b"; break;
+    case BL: mnemonic = "bl"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn";
+
+  switch (instr->Mask(DataProcessing1SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_w:           \
+    case A##_x: mnemonic = B; break;
+    FORMAT(RBIT, "rbit");
+    FORMAT(REV16, "rev16");
+    FORMAT(REV, "rev");
+    FORMAT(CLZ, "clz");
+    FORMAT(CLS, "cls");
+    #undef FORMAT
+    case REV32_x: mnemonic = "rev32"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitDataProcessing2Source(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Rd, 'Rn, 'Rm";
+
+  switch (instr->Mask(DataProcessing2SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_w:           \
+    case A##_x: mnemonic = B; break;
+    FORMAT(UDIV, "udiv");
+    FORMAT(SDIV, "sdiv");
+    FORMAT(LSLV, "lsl");
+    FORMAT(LSRV, "lsr");
+    FORMAT(ASRV, "asr");
+    FORMAT(RORV, "ror");
+    #undef FORMAT
+    default: form = "(DataProcessing2Source)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
+  bool ra_is_zr = RaIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
+  const char *form_rrr = "'Rd, 'Rn, 'Rm";
+  const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
+  const char *form_xww = "'Xd, 'Wn, 'Wm";
+  const char *form_xxx = "'Xd, 'Xn, 'Xm";
+
+  switch (instr->Mask(DataProcessing3SourceMask)) {
+    case MADD_w:
+    case MADD_x: {
+      mnemonic = "madd";
+      form = form_rrrr;
+      if (ra_is_zr) {
+        mnemonic = "mul";
+        form = form_rrr;
+      }
+      break;
+    }
+    case MSUB_w:
+    case MSUB_x: {
+      mnemonic = "msub";
+      form = form_rrrr;
+      if (ra_is_zr) {
+        mnemonic = "mneg";
+        form = form_rrr;
+      }
+      break;
+    }
+    case SMADDL_x: {
+      mnemonic = "smaddl";
+      if (ra_is_zr) {
+        mnemonic = "smull";
+        form = form_xww;
+      }
+      break;
+    }
+    case SMSUBL_x: {
+      mnemonic = "smsubl";
+      if (ra_is_zr) {
+        mnemonic = "smnegl";
+        form = form_xww;
+      }
+      break;
+    }
+    case UMADDL_x: {
+      mnemonic = "umaddl";
+      if (ra_is_zr) {
+        mnemonic = "umull";
+        form = form_xww;
+      }
+      break;
+    }
+    case UMSUBL_x: {
+      mnemonic = "umsubl";
+      if (ra_is_zr) {
+        mnemonic = "umnegl";
+        form = form_xww;
+      }
+      break;
+    }
+    case SMULH_x: {
+      mnemonic = "smulh";
+      form = form_xxx;
+      break;
+    }
+    case UMULH_x: {
+      mnemonic = "umulh";
+      form = form_xxx;
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitCompareBranch(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rt, 'BImmCmpa";
+
+  switch (instr->Mask(CompareBranchMask)) {
+    case CBZ_w:
+    case CBZ_x: mnemonic = "cbz"; break;
+    case CBNZ_w:
+    case CBNZ_x: mnemonic = "cbnz"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitTestBranch(Instruction* instr) {
+  const char *mnemonic = "";
+  // If the top bit of the immediate is clear, the tested register is
+  // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
+  // encoded in bit 31 of the instruction, we can reuse the Rt form, which
+  // uses bit 31 (normally "sf") to choose the register size.
+  const char *form = "'Rt, 'IS, 'BImmTest";
+
+  switch (instr->Mask(TestBranchMask)) {
+    case TBZ: mnemonic = "tbz"; break;
+    case TBNZ: mnemonic = "tbnz"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'IMoveImm";
+
+  // Print the shift separately for movk, to make it clear which half word will
+  // be overwritten. Movn and movz print the computed immediate, which includes
+  // shift calculation.
+  switch (instr->Mask(MoveWideImmediateMask)) {
+    case MOVN_w:
+    case MOVN_x: mnemonic = "movn"; break;
+    case MOVZ_w:
+    case MOVZ_x: mnemonic = "movz"; break;
+    case MOVK_w:
+    case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+#define LOAD_STORE_LIST(V)    \
+  V(STRB_w, "strb", "'Wt")    \
+  V(STRH_w, "strh", "'Wt")    \
+  V(STR_w, "str", "'Wt")      \
+  V(STR_x, "str", "'Xt")      \
+  V(LDRB_w, "ldrb", "'Wt")    \
+  V(LDRH_w, "ldrh", "'Wt")    \
+  V(LDR_w, "ldr", "'Wt")      \
+  V(LDR_x, "ldr", "'Xt")      \
+  V(LDRSB_x, "ldrsb", "'Xt")  \
+  V(LDRSH_x, "ldrsh", "'Xt")  \
+  V(LDRSW_x, "ldrsw", "'Xt")  \
+  V(LDRSB_w, "ldrsb", "'Wt")  \
+  V(LDRSH_w, "ldrsh", "'Wt")  \
+  V(STR_s, "str", "'St")      \
+  V(STR_d, "str", "'Dt")      \
+  V(LDR_s, "ldr", "'St")      \
+  V(LDR_d, "ldr", "'Dt")
+
+void Disassembler::VisitLoadStorePreIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePreIndex)";
+
+  switch (instr->Mask(LoadStorePreIndexMask)) {
+    #define LS_PREINDEX(A, B, C) \
+    case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
+    LOAD_STORE_LIST(LS_PREINDEX)
+    #undef LS_PREINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePostIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePostIndex)";
+
+  switch (instr->Mask(LoadStorePostIndexMask)) {
+    #define LS_POSTINDEX(A, B, C) \
+    case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
+    LOAD_STORE_LIST(LS_POSTINDEX)
+    #undef LS_POSTINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStoreUnsignedOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStoreUnsignedOffset)";
+
+  switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
+    #define LS_UNSIGNEDOFFSET(A, B, C) \
+    case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
+    LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
+    #undef LS_UNSIGNEDOFFSET
+    case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStoreRegisterOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStoreRegisterOffset)";
+
+  switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
+    #define LS_REGISTEROFFSET(A, B, C) \
+    case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
+    LOAD_STORE_LIST(LS_REGISTEROFFSET)
+    #undef LS_REGISTEROFFSET
+    case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStoreUnscaledOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Wt, ['Xns'ILS]";
+  const char *form_x = "'Xt, ['Xns'ILS]";
+  const char *form_s = "'St, ['Xns'ILS]";
+  const char *form_d = "'Dt, ['Xns'ILS]";
+
+  switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
+    case STURB_w:  mnemonic = "sturb"; break;
+    case STURH_w:  mnemonic = "sturh"; break;
+    case STUR_w:   mnemonic = "stur"; break;
+    case STUR_x:   mnemonic = "stur"; form = form_x; break;
+    case STUR_s:   mnemonic = "stur"; form = form_s; break;
+    case STUR_d:   mnemonic = "stur"; form = form_d; break;
+    case LDURB_w:  mnemonic = "ldurb"; break;
+    case LDURH_w:  mnemonic = "ldurh"; break;
+    case LDUR_w:   mnemonic = "ldur"; break;
+    case LDUR_x:   mnemonic = "ldur"; form = form_x; break;
+    case LDUR_s:   mnemonic = "ldur"; form = form_s; break;
+    case LDUR_d:   mnemonic = "ldur"; form = form_d; break;
+    case LDURSB_x: form = form_x;  // Fall through.
+    case LDURSB_w: mnemonic = "ldursb"; break;
+    case LDURSH_x: form = form_x;  // Fall through.
+    case LDURSH_w: mnemonic = "ldursh"; break;
+    case LDURSW_x: mnemonic = "ldursw"; form = form_x; break;
+    default: form = "(LoadStoreUnscaledOffset)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadLiteral(Instruction* instr) {
+  const char *mnemonic = "ldr";
+  const char *form = "(LoadLiteral)";
+
+  switch (instr->Mask(LoadLiteralMask)) {
+    case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
+    case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
+    case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
+    case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
+    default: mnemonic = "unimplemented";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+#define LOAD_STORE_PAIR_LIST(V)         \
+  V(STP_w, "stp", "'Wt, 'Wt2", "4")     \
+  V(LDP_w, "ldp", "'Wt, 'Wt2", "4")     \
+  V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \
+  V(STP_x, "stp", "'Xt, 'Xt2", "8")     \
+  V(LDP_x, "ldp", "'Xt, 'Xt2", "8")     \
+  V(STP_s, "stp", "'St, 'St2", "4")     \
+  V(LDP_s, "ldp", "'St, 'St2", "4")     \
+  V(STP_d, "stp", "'Dt, 'Dt2", "8")     \
+  V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
+
+void Disassembler::VisitLoadStorePairPostIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePairPostIndex)";
+
+  switch (instr->Mask(LoadStorePairPostIndexMask)) {
+    #define LSP_POSTINDEX(A, B, C, D) \
+    case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
+    LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
+    #undef LSP_POSTINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePairPreIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePairPreIndex)";
+
+  switch (instr->Mask(LoadStorePairPreIndexMask)) {
+    #define LSP_PREINDEX(A, B, C, D) \
+    case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
+    LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
+    #undef LSP_PREINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePairOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePairOffset)";
+
+  switch (instr->Mask(LoadStorePairOffsetMask)) {
+    #define LSP_OFFSET(A, B, C, D) \
+    case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
+    LOAD_STORE_PAIR_LIST(LSP_OFFSET)
+    #undef LSP_OFFSET
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePairNonTemporal(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form;
+
+  switch (instr->Mask(LoadStorePairNonTemporalMask)) {
+    case STNP_w: mnemonic = "stnp"; form = "'Wt, 'Wt2, ['Xns'ILP4]"; break;
+    case LDNP_w: mnemonic = "ldnp"; form = "'Wt, 'Wt2, ['Xns'ILP4]"; break;
+    case STNP_x: mnemonic = "stnp"; form = "'Xt, 'Xt2, ['Xns'ILP8]"; break;
+    case LDNP_x: mnemonic = "ldnp"; form = "'Xt, 'Xt2, ['Xns'ILP8]"; break;
+    case STNP_s: mnemonic = "stnp"; form = "'St, 'St2, ['Xns'ILP4]"; break;
+    case LDNP_s: mnemonic = "ldnp"; form = "'St, 'St2, ['Xns'ILP4]"; break;
+    case STNP_d: mnemonic = "stnp"; form = "'Dt, 'Dt2, ['Xns'ILP8]"; break;
+    case LDNP_d: mnemonic = "ldnp"; form = "'Dt, 'Dt2, ['Xns'ILP8]"; break;
+    default: form = "(LoadStorePairNonTemporal)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPCompare(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Fn, 'Fm";
+  const char *form_zero = "'Fn, #0.0";
+
+  switch (instr->Mask(FPCompareMask)) {
+    case FCMP_s_zero:
+    case FCMP_d_zero: form = form_zero;  // Fall through.
+    case FCMP_s:
+    case FCMP_d: mnemonic = "fcmp"; break;
+    default: form = "(FPCompare)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPConditionalCompare(Instruction* instr) {
+  const char *mnemonic = "unmplemented";
+  const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
+
+  switch (instr->Mask(FPConditionalCompareMask)) {
+    case FCCMP_s:
+    case FCCMP_d: mnemonic = "fccmp"; break;
+    case FCCMPE_s:
+    case FCCMPE_d: mnemonic = "fccmpe"; break;
+    default: form = "(FPConditionalCompare)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
+
+  switch (instr->Mask(FPConditionalSelectMask)) {
+    case FCSEL_s:
+    case FCSEL_d: mnemonic = "fcsel"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPDataProcessing1Source(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Fd, 'Fn";
+
+  switch (instr->Mask(FPDataProcessing1SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_s:           \
+    case A##_d: mnemonic = B; break;
+    FORMAT(FMOV, "fmov");
+    FORMAT(FABS, "fabs");
+    FORMAT(FNEG, "fneg");
+    FORMAT(FSQRT, "fsqrt");
+    FORMAT(FRINTN, "frintn");
+    FORMAT(FRINTP, "frintp");
+    FORMAT(FRINTM, "frintm");
+    FORMAT(FRINTZ, "frintz");
+    FORMAT(FRINTA, "frinta");
+    FORMAT(FRINTX, "frintx");
+    FORMAT(FRINTI, "frinti");
+    #undef FORMAT
+    case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
+    case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
+    default: form = "(FPDataProcessing1Source)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Fd, 'Fn, 'Fm";
+
+  switch (instr->Mask(FPDataProcessing2SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_s:           \
+    case A##_d: mnemonic = B; break;
+    FORMAT(FMUL, "fmul");
+    FORMAT(FDIV, "fdiv");
+    FORMAT(FADD, "fadd");
+    FORMAT(FSUB, "fsub");
+    FORMAT(FMAX, "fmax");
+    FORMAT(FMIN, "fmin");
+    FORMAT(FMAXNM, "fmaxnm");
+    FORMAT(FMINNM, "fminnm");
+    FORMAT(FNMUL, "fnmul");
+    #undef FORMAT
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
+
+  switch (instr->Mask(FPDataProcessing3SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_s:           \
+    case A##_d: mnemonic = B; break;
+    FORMAT(FMADD, "fmadd");
+    FORMAT(FMSUB, "fmsub");
+    FORMAT(FNMADD, "fnmadd");
+    FORMAT(FNMSUB, "fnmsub");
+    #undef FORMAT
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPImmediate(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "(FPImmediate)";
+
+  switch (instr->Mask(FPImmediateMask)) {
+    case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
+    case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(FPIntegerConvert)";
+  const char *form_rf = "'Rd, 'Fn";
+  const char *form_fr = "'Fd, 'Rn";
+
+  switch (instr->Mask(FPIntegerConvertMask)) {
+    case FMOV_ws:
+    case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
+    case FMOV_sw:
+    case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
+    case FCVTMS_ws:
+    case FCVTMS_xs:
+    case FCVTMS_wd:
+    case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
+    case FCVTMU_ws:
+    case FCVTMU_xs:
+    case FCVTMU_wd:
+    case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
+    case FCVTNS_ws:
+    case FCVTNS_xs:
+    case FCVTNS_wd:
+    case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
+    case FCVTNU_ws:
+    case FCVTNU_xs:
+    case FCVTNU_wd:
+    case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
+    case FCVTZU_xd:
+    case FCVTZU_ws:
+    case FCVTZU_wd:
+    case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
+    case FCVTZS_xd:
+    case FCVTZS_wd:
+    case FCVTZS_xs:
+    case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
+    case SCVTF_sw:
+    case SCVTF_sx:
+    case SCVTF_dw:
+    case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
+    case UCVTF_sw:
+    case UCVTF_sx:
+    case UCVTF_dw:
+    case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Fn, 'IFPFBits";
+  const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
+
+  switch (instr->Mask(FPFixedPointConvertMask)) {
+    case FCVTZS_ws_fixed:
+    case FCVTZS_xs_fixed:
+    case FCVTZS_wd_fixed:
+    case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
+    case FCVTZU_ws_fixed:
+    case FCVTZU_xs_fixed:
+    case FCVTZU_wd_fixed:
+    case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
+    case SCVTF_sw_fixed:
+    case SCVTF_sx_fixed:
+    case SCVTF_dw_fixed:
+    case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
+    case UCVTF_sw_fixed:
+    case UCVTF_sx_fixed:
+    case UCVTF_dw_fixed:
+    case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitSystem(Instruction* instr) {
+  // Some system instructions hijack their Op and Cp fields to represent a
+  // range of immediates instead of indicating a different instruction. This
+  // makes the decoding tricky.
+  const char *mnemonic = "unimplemented";
+  const char *form = "(System)";
+
+  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
+    switch (instr->Mask(SystemSysRegMask)) {
+      case MRS: {
+        mnemonic = "mrs";
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: form = "'Xt, nzcv"; break;
+          case FPCR: form = "'Xt, fpcr"; break;
+          default: form = "'Xt, (unknown)"; break;
+        }
+        break;
+      }
+      case MSR: {
+        mnemonic = "msr";
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: form = "nzcv, 'Xt"; break;
+          case FPCR: form = "fpcr, 'Xt"; break;
+          default: form = "(unknown), 'Xt"; break;
+        }
+        break;
+      }
+    }
+  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
+    ASSERT(instr->Mask(SystemHintMask) == HINT);
+    switch (instr->ImmHint()) {
+      case NOP: {
+        mnemonic = "nop";
+        form = NULL;
+        break;
+      }
+    }
+  }
+
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitException(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'IDebug";
+
+  switch (instr->Mask(ExceptionMask)) {
+    case HLT: mnemonic = "hlt"; break;
+    case BRK: mnemonic = "brk"; break;
+    case SVC: mnemonic = "svc"; break;
+    case HVC: mnemonic = "hvc"; break;
+    case SMC: mnemonic = "smc"; break;
+    case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
+    case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
+    case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
+    default: form = "(Exception)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitUnimplemented(Instruction* instr) {
+  Format(instr, "unimplemented", "(Unimplemented)");
+}
+
+
+void Disassembler::VisitUnallocated(Instruction* instr) {
+  Format(instr, "unallocated", "(Unallocated)");
+}
+
+
+void Disassembler::ProcessOutput(Instruction* /*instr*/) {
+  // The base disasm does nothing more than disassembling into a buffer.
+}
+
+
+void Disassembler::Format(Instruction* instr, const char* mnemonic,
+                          const char* format) {
+  ASSERT(mnemonic != NULL);
+  ResetOutput();
+  Substitute(instr, mnemonic);
+  if (format != NULL) {
+    buffer_[buffer_pos_++] = ' ';
+    Substitute(instr, format);
+  }
+  buffer_[buffer_pos_] = 0;
+  ProcessOutput(instr);
+}
+
+
+void Disassembler::Substitute(Instruction* instr, const char* string) {
+  char chr = *string++;
+  while (chr != '\0') {
+    if (chr == '\'') {
+      string += SubstituteField(instr, string);
+    } else {
+      buffer_[buffer_pos_++] = chr;
+    }
+    chr = *string++;
+  }
+}
+
+
+int Disassembler::SubstituteField(Instruction* instr, const char* format) {
+  switch (format[0]) {
+    case 'R':  // Register. X or W, selected by sf bit.
+    case 'F':  // FP Register. S or D, selected by type field.
+    case 'W':
+    case 'X':
+    case 'S':
+    case 'D': return SubstituteRegisterField(instr, format);
+    case 'I': return SubstituteImmediateField(instr, format);
+    case 'L': return SubstituteLiteralField(instr, format);
+    case 'H': return SubstituteShiftField(instr, format);
+    case 'P': return SubstitutePrefetchField(instr, format);
+    case 'C': return SubstituteConditionField(instr, format);
+    case 'E': return SubstituteExtendField(instr, format);
+    case 'A': return SubstitutePCRelAddressField(instr, format);
+    case 'B': return SubstituteBranchTargetField(instr, format);
+    case 'O': return SubstituteLSRegOffsetField(instr, format);
+    default: {
+      UNREACHABLE();
+      return 1;
+    }
+  }
+}
+
+
+int Disassembler::SubstituteRegisterField(Instruction* instr,
+                                          const char* format) {
+  unsigned reg_num = 0;
+  unsigned field_len = 2;
+  switch (format[1]) {
+    case 'd': reg_num = instr->Rd(); break;
+    case 'n': reg_num = instr->Rn(); break;
+    case 'm': reg_num = instr->Rm(); break;
+    case 'a': reg_num = instr->Ra(); break;
+    case 't': {
+      if (format[2] == '2') {
+        reg_num = instr->Rt2();
+        field_len = 3;
+      } else {
+        reg_num = instr->Rt();
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+
+  // Increase field length for registers tagged as stack.
+  if (format[2] == 's') {
+    field_len = 3;
+  }
+
+  char reg_type;
+  if (format[0] == 'R') {
+    // Register type is R: use sf bit to choose X and W.
+    reg_type = instr->SixtyFourBits() ? 'x' : 'w';
+  } else if (format[0] == 'F') {
+    // Floating-point register: use type field to choose S or D.
+    reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd';
+  } else {
+    // Register type is specified. Make it lower case.
+    reg_type = format[0] + 0x20;
+  }
+
+  if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) {
+    // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
+    AppendToOutput("%c%d", reg_type, reg_num);
+  } else if (format[2] == 's') {
+    // Disassemble w31/x31 as stack pointer wsp/sp.
+    AppendToOutput("%s", (reg_type == 'w') ? "wsp" : "sp");
+  } else {
+    // Disassemble w31/x31 as zero register wzr/xzr.
+    AppendToOutput("%czr", reg_type);
+  }
+
+  return field_len;
+}
+
+
+int Disassembler::SubstituteImmediateField(Instruction* instr,
+                                           const char* format) {
+  ASSERT(format[0] == 'I');
+
+  switch (format[1]) {
+    case 'M': {  // IMoveImm or IMoveLSL.
+      if (format[5] == 'I') {
+        uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
+        AppendToOutput("#0x%" PRIx64, imm);
+      } else {
+        ASSERT(format[5] == 'L');
+        AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
+        if (instr->ShiftMoveWide() > 0) {
+          AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
+        }
+      }
+      return 8;
+    }
+    case 'L': {
+      switch (format[2]) {
+        case 'L': {  // ILLiteral - Immediate Load Literal.
+          AppendToOutput("pc%+" PRId64,
+                         instr->ImmLLiteral() << kLiteralEntrySizeLog2);
+          return 9;
+        }
+        case 'S': {  // ILS - Immediate Load/Store.
+          if (instr->ImmLS() != 0) {
+            AppendToOutput(", #%" PRId64, instr->ImmLS());
+          }
+          return 3;
+        }
+        case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
+          if (instr->ImmLSPair() != 0) {
+            // format[3] is the scale value. Convert to a number.
+            int scale = format[3] - 0x30;
+            AppendToOutput(", #%" PRId64, instr->ImmLSPair() * scale);
+          }
+          return 4;
+        }
+        case 'U': {  // ILU - Immediate Load/Store Unsigned.
+          if (instr->ImmLSUnsigned() != 0) {
+            AppendToOutput(", #%" PRIu64,
+                           instr->ImmLSUnsigned() << instr->SizeLS());
+          }
+          return 3;
+        }
+      }
+    }
+    case 'C': {  // ICondB - Immediate Conditional Branch.
+      int64_t offset = instr->ImmCondBranch() << 2;
+      char sign = (offset >= 0) ? '+' : '-';
+      AppendToOutput("#%c0x%" PRIx64, sign, offset);
+      return 6;
+    }
+    case 'A': {  // IAddSub.
+      ASSERT(instr->ShiftAddSub() <= 1);
+      int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
+      AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
+      return 7;
+    }
+    case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
+      if (format[3] == 'F') {  // IFPFbits.
+        AppendToOutput("#%d", 64 - instr->FPScale());
+        return 8;
+      } else {
+        AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
+                       format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
+        return 9;
+      }
+    }
+    case 'T': {  // ITri - Immediate Triangular Encoded.
+      AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
+      return 4;
+    }
+    case 'N': {  // INzcv.
+      int nzcv = (instr->Nzcv() << Flags_offset);
+      AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
+                                  ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
+                                  ((nzcv & CFlag) == 0) ? 'c' : 'C',
+                                  ((nzcv & VFlag) == 0) ? 'v' : 'V');
+      return 5;
+    }
+    case 'P': {  // IP - Conditional compare.
+      AppendToOutput("#%d", instr->ImmCondCmp());
+      return 2;
+    }
+    case 'B': {  // Bitfields.
+      return SubstituteBitfieldImmediateField(instr, format);
+    }
+    case 'E': {  // IExtract.
+      AppendToOutput("#%d", instr->ImmS());
+      return 8;
+    }
+    case 'S': {  // IS - Test and branch bit.
+      AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
+                            instr->ImmTestBranchBit40());
+      return 2;
+    }
+    case 'D': {  // IDebug - HLT and BRK instructions.
+      AppendToOutput("#0x%x", instr->ImmException());
+      return 6;
+    }
+    default: {
+      UNIMPLEMENTED();
+      return 0;
+    }
+  }
+}
+
+
+int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
+                                                   const char* format) {
+  ASSERT((format[0] == 'I') && (format[1] == 'B'));
+  unsigned r = instr->ImmR();
+  unsigned s = instr->ImmS();
+
+  switch (format[2]) {
+    case 'r': {  // IBr.
+      AppendToOutput("#%d", r);
+      return 3;
+    }
+    case 's': {  // IBs+1 or IBs-r+1.
+      if (format[3] == '+') {
+        AppendToOutput("#%d", s + 1);
+        return 5;
+      } else {
+        ASSERT(format[3] == '-');
+        AppendToOutput("#%d", s - r + 1);
+        return 7;
+      }
+    }
+    case 'Z': {  // IBZ-r.
+      ASSERT((format[3] == '-') && (format[4] == 'r'));
+      unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize;
+      AppendToOutput("#%d", reg_size - r);
+      return 5;
+    }
+    default: {
+      UNREACHABLE();
+      return 0;
+    }
+  }
+}
+
+
+int Disassembler::SubstituteLiteralField(Instruction* instr,
+                                         const char* format) {
+  ASSERT(strncmp(format, "LValue", 6) == 0);
+  USE(format);
+
+  switch (instr->Mask(LoadLiteralMask)) {
+    case LDR_w_lit:
+    case LDR_x_lit:
+    case LDR_s_lit:
+    case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
+    default: UNREACHABLE();
+  }
+
+  return 6;
+}
+
+
+int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
+  ASSERT(format[0] == 'H');
+  ASSERT(instr->ShiftDP() <= 0x3);
+
+  switch (format[1]) {
+    case 'D': {  // HDP.
+      ASSERT(instr->ShiftDP() != ROR);
+    }  // Fall through.
+    case 'L': {  // HLo.
+      if (instr->ImmDPShift() != 0) {
+        const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
+        AppendToOutput(", %s #%" PRId64, shift_type[instr->ShiftDP()],
+                       instr->ImmDPShift());
+      }
+      return 3;
+    }
+    default:
+      UNIMPLEMENTED();
+      return 0;
+  }
+}
+
+
+int Disassembler::SubstituteConditionField(Instruction* instr,
+                                           const char* format) {
+  ASSERT(format[0] == 'C');
+  const char* condition_code[] = { "eq", "ne", "hs", "lo",
+                                   "mi", "pl", "vs", "vc",
+                                   "hi", "ls", "ge", "lt",
+                                   "gt", "le", "al", "nv" };
+  int cond;
+  switch (format[1]) {
+    case 'B': cond = instr->ConditionBranch(); break;
+    case 'I': {
+      cond = InvertCondition(static_cast<Condition>(instr->Condition()));
+      break;
+    }
+    default: cond = instr->Condition();
+  }
+  AppendToOutput("%s", condition_code[cond]);
+  return 4;
+}
+
+
+int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
+                                              const char* format) {
+  USE(format);
+  ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
+
+  int offset = instr->ImmPCRel();
+
+  // Only ADR (AddrPCRelByte) is supported.
+  ASSERT(strcmp(format, "AddrPCRelByte") == 0);
+
+  char sign = '+';
+  if (offset < 0) {
+    offset = -offset;
+    sign = '-';
+  }
+  // TODO: Extend this to support printing the target address.
+  AppendToOutput("#%c0x%x", sign, offset);
+  return 13;
+}
+
+
+int Disassembler::SubstituteBranchTargetField(Instruction* instr,
+                                              const char* format) {
+  ASSERT(strncmp(format, "BImm", 4) == 0);
+
+  int64_t offset = 0;
+  switch (format[5]) {
+    // BImmUncn - unconditional branch immediate.
+    case 'n': offset = instr->ImmUncondBranch(); break;
+    // BImmCond - conditional branch immediate.
+    case 'o': offset = instr->ImmCondBranch(); break;
+    // BImmCmpa - compare and branch immediate.
+    case 'm': offset = instr->ImmCmpBranch(); break;
+    // BImmTest - test and branch immediate.
+    case 'e': offset = instr->ImmTestBranch(); break;
+    default: UNIMPLEMENTED();
+  }
+  offset <<= kInstructionSizeLog2;
+  char sign = '+';
+  if (offset < 0) {
+    offset = -offset;
+    sign = '-';
+  }
+  AppendToOutput("#%c0x%" PRIx64, sign, offset);
+  return 8;
+}
+
+
+int Disassembler::SubstituteExtendField(Instruction* instr,
+                                        const char* format) {
+  ASSERT(strncmp(format, "Ext", 3) == 0);
+  ASSERT(instr->ExtendMode() <= 7);
+  USE(format);
+
+  const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
+                                "sxtb", "sxth", "sxtw", "sxtx" };
+
+  // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
+  // registers becomes lsl.
+  if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
+      (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
+       (instr->ExtendMode() == UXTX))) {
+    if (instr->ImmExtendShift() > 0) {
+      AppendToOutput(", lsl #%d", instr->ImmExtendShift());
+    }
+  } else {
+    AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
+    if (instr->ImmExtendShift() > 0) {
+      AppendToOutput(" #%d", instr->ImmExtendShift());
+    }
+  }
+  return 3;
+}
+
+
+int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
+                                             const char* format) {
+  ASSERT(strncmp(format, "Offsetreg", 9) == 0);
+  const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
+                                "undefined", "undefined", "sxtw", "sxtx" };
+  USE(format);
+
+  unsigned shift = instr->ImmShiftLS();
+  Extend ext = static_cast<Extend>(instr->ExtendMode());
+  char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
+
+  unsigned rm = instr->Rm();
+  if (rm == kZeroRegCode) {
+    AppendToOutput("%czr", reg_type);
+  } else {
+    AppendToOutput("%c%d", reg_type, rm);
+  }
+
+  // Extend mode UXTX is an alias for shift mode LSL here.
+  if (!((ext == UXTX) && (shift == 0))) {
+    AppendToOutput(", %s", extend_mode[ext]);
+    if (shift != 0) {
+      AppendToOutput(" #%d", instr->SizeLS());
+    }
+  }
+  return 9;
+}
+
+
+int Disassembler::SubstitutePrefetchField(Instruction* instr,
+                                          const char* format) {
+  ASSERT(format[0] == 'P');
+  USE(format);
+
+  int prefetch_mode = instr->PrefetchMode();
+
+  const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
+  int level = (prefetch_mode >> 1) + 1;
+  const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
+
+  AppendToOutput("p%sl%d%s", ls, level, ks);
+  return 6;
+}
+
+
+void Disassembler::ResetOutput() {
+  buffer_pos_ = 0;
+  buffer_[buffer_pos_] = 0;
+}
+
+
+void Disassembler::AppendToOutput(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
+  va_end(args);
+}
+
+
+void PrintDisassembler::ProcessOutput(Instruction* instr) {
+  fprintf(stream_, "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s\n",
+          reinterpret_cast<uint64_t>(instr),
+          instr->InstructionBits(),
+          GetOutput());
+}
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/disasm-a64.h b/disas/libvixl/src/a64/disasm-a64.h
new file mode 100644
index 0000000..857a5ac
--- /dev/null
+++ b/disas/libvixl/src/a64/disasm-a64.h
@@ -0,0 +1,109 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_DISASM_A64_H
+#define VIXL_A64_DISASM_A64_H
+
+#include "globals.h"
+#include "utils.h"
+#include "instructions-a64.h"
+#include "decoder-a64.h"
+
+namespace vixl {
+
+class Disassembler: public DecoderVisitor {
+ public:
+  Disassembler();
+  Disassembler(char* text_buffer, int buffer_size);
+  virtual ~Disassembler();
+  char* GetOutput();
+
+  // Declare all Visitor functions.
+  #define DECLARE(A)  void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+ protected:
+  virtual void ProcessOutput(Instruction* instr);
+
+ private:
+  void Format(Instruction* instr, const char* mnemonic, const char* format);
+  void Substitute(Instruction* instr, const char* string);
+  int SubstituteField(Instruction* instr, const char* format);
+  int SubstituteRegisterField(Instruction* instr, const char* format);
+  int SubstituteImmediateField(Instruction* instr, const char* format);
+  int SubstituteLiteralField(Instruction* instr, const char* format);
+  int SubstituteBitfieldImmediateField(Instruction* instr, const char* format);
+  int SubstituteShiftField(Instruction* instr, const char* format);
+  int SubstituteExtendField(Instruction* instr, const char* format);
+  int SubstituteConditionField(Instruction* instr, const char* format);
+  int SubstitutePCRelAddressField(Instruction* instr, const char* format);
+  int SubstituteBranchTargetField(Instruction* instr, const char* format);
+  int SubstituteLSRegOffsetField(Instruction* instr, const char* format);
+  int SubstitutePrefetchField(Instruction* instr, const char* format);
+
+  inline bool RdIsZROrSP(Instruction* instr) const {
+    return (instr->Rd() == kZeroRegCode);
+  }
+
+  inline bool RnIsZROrSP(Instruction* instr) const {
+    return (instr->Rn() == kZeroRegCode);
+  }
+
+  inline bool RmIsZROrSP(Instruction* instr) const {
+    return (instr->Rm() == kZeroRegCode);
+  }
+
+  inline bool RaIsZROrSP(Instruction* instr) const {
+    return (instr->Ra() == kZeroRegCode);
+  }
+
+  bool IsMovzMovnImm(unsigned reg_size, uint64_t value);
+
+  void ResetOutput();
+  void AppendToOutput(const char* string, ...);
+
+  char* buffer_;
+  uint32_t buffer_pos_;
+  uint32_t buffer_size_;
+  bool own_buffer_;
+};
+
+
+class PrintDisassembler: public Disassembler {
+ public:
+  explicit PrintDisassembler(FILE* stream) : stream_(stream) { }
+  ~PrintDisassembler() { }
+
+ protected:
+  virtual void ProcessOutput(Instruction* instr);
+
+ private:
+  FILE *stream_;
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_DISASM_A64_H
diff --git a/disas/libvixl/src/a64/instructions-a64.cc b/disas/libvixl/src/a64/instructions-a64.cc
new file mode 100644
index 0000000..e87fa3a
--- /dev/null
+++ b/disas/libvixl/src/a64/instructions-a64.cc
@@ -0,0 +1,238 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/instructions-a64.h"
+#include "a64/assembler-a64.h"
+
+namespace vixl {
+
+
+static uint64_t RotateRight(uint64_t value,
+                            unsigned int rotate,
+                            unsigned int width) {
+  ASSERT(width <= 64);
+  rotate &= 63;
+  return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) |
+         (value >> rotate);
+}
+
+
+static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
+                                    uint64_t value,
+                                    unsigned width) {
+  ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
+         (width == 32));
+  ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+  uint64_t result = value & ((1UL << width) - 1UL);
+  for (unsigned i = width; i < reg_size; i *= 2) {
+    result |= (result << i);
+  }
+  return result;
+}
+
+
+// Logical immediates can't encode zero, so a return value of zero is used to
+// indicate a failure case. Specifically, where the constraints on imm_s are
+// not met.
+uint64_t Instruction::ImmLogical() {
+  unsigned reg_size = SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t n = BitN();
+  int64_t imm_s = ImmSetBits();
+  int64_t imm_r = ImmRotate();
+
+  // An integer is constructed from the n, imm_s and imm_r bits according to
+  // the following table:
+  //
+  //  N   imms    immr    size        S             R
+  //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
+  //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
+  //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
+  //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
+  //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
+  //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
+  // (s bits must not be all set)
+  //
+  // A pattern is constructed of size bits, where the least significant S+1
+  // bits are set. The pattern is rotated right by R, and repeated across a
+  // 32 or 64-bit value, depending on destination register width.
+  //
+
+  if (n == 1) {
+    if (imm_s == 0x3F) {
+      return 0;
+    }
+    uint64_t bits = (1UL << (imm_s + 1)) - 1;
+    return RotateRight(bits, imm_r, 64);
+  } else {
+    if ((imm_s >> 1) == 0x1F) {
+      return 0;
+    }
+    for (int width = 0x20; width >= 0x2; width >>= 1) {
+      if ((imm_s & width) == 0) {
+        int mask = width - 1;
+        if ((imm_s & mask) == mask) {
+          return 0;
+        }
+        uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1;
+        return RepeatBitsAcrossReg(reg_size,
+                                   RotateRight(bits, imm_r & mask, width),
+                                   width);
+      }
+    }
+  }
+  UNREACHABLE();
+  return 0;
+}
+
+
+float Instruction::ImmFP32() {
+  //  ImmFP: abcdefgh (8 bits)
+  // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
+  // where B is b ^ 1
+  uint32_t bits = ImmFP();
+  uint32_t bit7 = (bits >> 7) & 0x1;
+  uint32_t bit6 = (bits >> 6) & 0x1;
+  uint32_t bit5_to_0 = bits & 0x3f;
+  uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
+
+  return rawbits_to_float(result);
+}
+
+
+double Instruction::ImmFP64() {
+  //  ImmFP: abcdefgh (8 bits)
+  // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
+  //         0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
+  // where B is b ^ 1
+  uint32_t bits = ImmFP();
+  uint64_t bit7 = (bits >> 7) & 0x1;
+  uint64_t bit6 = (bits >> 6) & 0x1;
+  uint64_t bit5_to_0 = bits & 0x3f;
+  uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
+
+  return rawbits_to_double(result);
+}
+
+
+LSDataSize CalcLSPairDataSize(LoadStorePairOp op) {
+  switch (op) {
+    case STP_x:
+    case LDP_x:
+    case STP_d:
+    case LDP_d: return LSDoubleWord;
+    default: return LSWord;
+  }
+}
+
+
+Instruction* Instruction::ImmPCOffsetTarget() {
+  ptrdiff_t offset;
+  if (IsPCRelAddressing()) {
+    // PC-relative addressing. Only ADR is supported.
+    offset = ImmPCRel();
+  } else {
+    // All PC-relative branches.
+    ASSERT(BranchType() != UnknownBranchType);
+    // Relative branch offsets are instruction-size-aligned.
+    offset = ImmBranch() << kInstructionSizeLog2;
+  }
+  return this + offset;
+}
+
+
+inline int Instruction::ImmBranch() const {
+  switch (BranchType()) {
+    case CondBranchType: return ImmCondBranch();
+    case UncondBranchType: return ImmUncondBranch();
+    case CompareBranchType: return ImmCmpBranch();
+    case TestBranchType: return ImmTestBranch();
+    default: UNREACHABLE();
+  }
+  return 0;
+}
+
+
+void Instruction::SetImmPCOffsetTarget(Instruction* target) {
+  if (IsPCRelAddressing()) {
+    SetPCRelImmTarget(target);
+  } else {
+    SetBranchImmTarget(target);
+  }
+}
+
+
+void Instruction::SetPCRelImmTarget(Instruction* target) {
+  // ADRP is not supported, so 'this' must point to an ADR instruction.
+  ASSERT(Mask(PCRelAddressingMask) == ADR);
+
+  Instr imm = Assembler::ImmPCRelAddress(target - this);
+
+  SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
+}
+
+
+void Instruction::SetBranchImmTarget(Instruction* target) {
+  ASSERT(((target - this) & 3) == 0);
+  Instr branch_imm = 0;
+  uint32_t imm_mask = 0;
+  int offset = (target - this) >> kInstructionSizeLog2;
+  switch (BranchType()) {
+    case CondBranchType: {
+      branch_imm = Assembler::ImmCondBranch(offset);
+      imm_mask = ImmCondBranch_mask;
+      break;
+    }
+    case UncondBranchType: {
+      branch_imm = Assembler::ImmUncondBranch(offset);
+      imm_mask = ImmUncondBranch_mask;
+      break;
+    }
+    case CompareBranchType: {
+      branch_imm = Assembler::ImmCmpBranch(offset);
+      imm_mask = ImmCmpBranch_mask;
+      break;
+    }
+    case TestBranchType: {
+      branch_imm = Assembler::ImmTestBranch(offset);
+      imm_mask = ImmTestBranch_mask;
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  SetInstructionBits(Mask(~imm_mask) | branch_imm);
+}
+
+
+void Instruction::SetImmLLiteral(Instruction* source) {
+  ASSERT(((source - this) & 3) == 0);
+  int offset = (source - this) >> kLiteralEntrySizeLog2;
+  Instr imm = Assembler::ImmLLiteral(offset);
+  Instr mask = ImmLLiteral_mask;
+
+  SetInstructionBits(Mask(~mask) | imm);
+}
+}  // namespace vixl
+
diff --git a/disas/libvixl/src/a64/instructions-a64.h b/disas/libvixl/src/a64/instructions-a64.h
new file mode 100644
index 0000000..0f31fcd
--- /dev/null
+++ b/disas/libvixl/src/a64/instructions-a64.h
@@ -0,0 +1,344 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_INSTRUCTIONS_A64_H_
+#define VIXL_A64_INSTRUCTIONS_A64_H_
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/constants-a64.h"
+
+namespace vixl {
+// ISA constants. --------------------------------------------------------------
+
+typedef uint32_t Instr;
+const unsigned kInstructionSize = 4;
+const unsigned kInstructionSizeLog2 = 2;
+const unsigned kLiteralEntrySize = 4;
+const unsigned kLiteralEntrySizeLog2 = 2;
+const unsigned kMaxLoadLiteralRange = 1 * MBytes;
+
+const unsigned kWRegSize = 32;
+const unsigned kWRegSizeLog2 = 5;
+const unsigned kWRegSizeInBytes = kWRegSize / 8;
+const unsigned kXRegSize = 64;
+const unsigned kXRegSizeLog2 = 6;
+const unsigned kXRegSizeInBytes = kXRegSize / 8;
+const unsigned kSRegSize = 32;
+const unsigned kSRegSizeLog2 = 5;
+const unsigned kSRegSizeInBytes = kSRegSize / 8;
+const unsigned kDRegSize = 64;
+const unsigned kDRegSizeLog2 = 6;
+const unsigned kDRegSizeInBytes = kDRegSize / 8;
+const int64_t kWRegMask = 0x00000000ffffffffL;
+const int64_t kXRegMask = 0xffffffffffffffffL;
+const int64_t kSRegMask = 0x00000000ffffffffL;
+const int64_t kDRegMask = 0xffffffffffffffffL;
+const int64_t kXSignMask = 0x1L << 63;
+const int64_t kWSignMask = 0x1L << 31;
+const int64_t kByteMask = 0xffL;
+const int64_t kHalfWordMask = 0xffffL;
+const int64_t kWordMask = 0xffffffffL;
+const uint64_t kXMaxUInt = 0xffffffffffffffffUL;
+const uint64_t kWMaxUInt = 0xffffffffUL;
+const int64_t kXMaxInt = 0x7fffffffffffffffL;
+const int64_t kXMinInt = 0x8000000000000000L;
+const int32_t kWMaxInt = 0x7fffffff;
+const int32_t kWMinInt = 0x80000000;
+const unsigned kLinkRegCode = 30;
+const unsigned kZeroRegCode = 31;
+const unsigned kSPRegInternalCode = 63;
+const unsigned kRegCodeMask = 0x1f;
+
+// AArch64 floating-point specifics. These match IEEE-754.
+const unsigned kDoubleMantissaBits = 52;
+const unsigned kDoubleExponentBits = 11;
+const unsigned kFloatMantissaBits = 23;
+const unsigned kFloatExponentBits = 8;
+
+const float kFP32PositiveInfinity = rawbits_to_float(0x7f800000);
+const float kFP32NegativeInfinity = rawbits_to_float(0xff800000);
+const double kFP64PositiveInfinity = rawbits_to_double(0x7ff0000000000000UL);
+const double kFP64NegativeInfinity = rawbits_to_double(0xfff0000000000000UL);
+
+// This value is a signalling NaN as both a double and as a float (taking the
+// least-significant word).
+static const double kFP64SignallingNaN = rawbits_to_double(0x7ff000007f800001);
+static const float kFP32SignallingNaN = rawbits_to_float(0x7f800001);
+
+// A similar value, but as a quiet NaN.
+static const double kFP64QuietNaN = rawbits_to_double(0x7ff800007fc00001);
+static const float kFP32QuietNaN = rawbits_to_float(0x7fc00001);
+
+enum LSDataSize {
+  LSByte        = 0,
+  LSHalfword    = 1,
+  LSWord        = 2,
+  LSDoubleWord  = 3
+};
+
+LSDataSize CalcLSPairDataSize(LoadStorePairOp op);
+
+enum ImmBranchType {
+  UnknownBranchType = 0,
+  CondBranchType    = 1,
+  UncondBranchType  = 2,
+  CompareBranchType = 3,
+  TestBranchType    = 4
+};
+
+enum AddrMode {
+  Offset,
+  PreIndex,
+  PostIndex
+};
+
+enum FPRounding {
+  // The first four values are encodable directly by FPCR<RMode>.
+  FPTieEven = 0x0,
+  FPPositiveInfinity = 0x1,
+  FPNegativeInfinity = 0x2,
+  FPZero = 0x3,
+
+  // The final rounding mode is only available when explicitly specified by the
+  // instruction (such as with fcvta). It cannot be set in FPCR.
+  FPTieAway
+};
+
+enum Reg31Mode {
+  Reg31IsStackPointer,
+  Reg31IsZeroRegister
+};
+
+// Instructions. ---------------------------------------------------------------
+
+class Instruction {
+ public:
+  inline Instr InstructionBits() const {
+    return *(reinterpret_cast<const Instr*>(this));
+  }
+
+  inline void SetInstructionBits(Instr new_instr) {
+    *(reinterpret_cast<Instr*>(this)) = new_instr;
+  }
+
+  inline int Bit(int pos) const {
+    return (InstructionBits() >> pos) & 1;
+  }
+
+  inline uint32_t Bits(int msb, int lsb) const {
+    return unsigned_bitextract_32(msb, lsb, InstructionBits());
+  }
+
+  inline int32_t SignedBits(int msb, int lsb) const {
+    int32_t bits = *(reinterpret_cast<const int32_t*>(this));
+    return signed_bitextract_32(msb, lsb, bits);
+  }
+
+  inline Instr Mask(uint32_t mask) const {
+    return InstructionBits() & mask;
+  }
+
+  #define DEFINE_GETTER(Name, HighBit, LowBit, Func)             \
+  inline int64_t Name() const { return Func(HighBit, LowBit); }
+  INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
+  #undef DEFINE_GETTER
+
+  // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
+  // formed from ImmPCRelLo and ImmPCRelHi.
+  int ImmPCRel() const {
+    int const offset = ((ImmPCRelHi() << ImmPCRelLo_width) | ImmPCRelLo());
+    int const width = ImmPCRelLo_width + ImmPCRelHi_width;
+    return signed_bitextract_32(width-1, 0, offset);
+  }
+
+  uint64_t ImmLogical();
+  float ImmFP32();
+  double ImmFP64();
+
+  inline LSDataSize SizeLSPair() const {
+    return CalcLSPairDataSize(
+             static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
+  }
+
+  // Helpers.
+  inline bool IsCondBranchImm() const {
+    return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
+  }
+
+  inline bool IsUncondBranchImm() const {
+    return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
+  }
+
+  inline bool IsCompareBranch() const {
+    return Mask(CompareBranchFMask) == CompareBranchFixed;
+  }
+
+  inline bool IsTestBranch() const {
+    return Mask(TestBranchFMask) == TestBranchFixed;
+  }
+
+  inline bool IsPCRelAddressing() const {
+    return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
+  }
+
+  inline bool IsLogicalImmediate() const {
+    return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
+  }
+
+  inline bool IsAddSubImmediate() const {
+    return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
+  }
+
+  inline bool IsAddSubExtended() const {
+    return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
+  }
+
+  inline bool IsLoadOrStore() const {
+    return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
+  }
+
+  inline bool IsMovn() const {
+    return (Mask(MoveWideImmediateMask) == MOVN_x) ||
+           (Mask(MoveWideImmediateMask) == MOVN_w);
+  }
+
+  // Indicate whether Rd can be the stack pointer or the zero register. This
+  // does not check that the instruction actually has an Rd field.
+  inline Reg31Mode RdMode() const {
+    // The following instructions use sp or wsp as Rd:
+    //  Add/sub (immediate) when not setting the flags.
+    //  Add/sub (extended) when not setting the flags.
+    //  Logical (immediate) when not setting the flags.
+    // Otherwise, r31 is the zero register.
+    if (IsAddSubImmediate() || IsAddSubExtended()) {
+      if (Mask(AddSubSetFlagsBit)) {
+        return Reg31IsZeroRegister;
+      } else {
+        return Reg31IsStackPointer;
+      }
+    }
+    if (IsLogicalImmediate()) {
+      // Of the logical (immediate) instructions, only ANDS (and its aliases)
+      // can set the flags. The others can all write into sp.
+      // Note that some logical operations are not available to
+      // immediate-operand instructions, so we have to combine two masks here.
+      if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
+        return Reg31IsZeroRegister;
+      } else {
+        return Reg31IsStackPointer;
+      }
+    }
+    return Reg31IsZeroRegister;
+  }
+
+  // Indicate whether Rn can be the stack pointer or the zero register. This
+  // does not check that the instruction actually has an Rn field.
+  inline Reg31Mode RnMode() const {
+    // The following instructions use sp or wsp as Rn:
+    //  All loads and stores.
+    //  Add/sub (immediate).
+    //  Add/sub (extended).
+    // Otherwise, r31 is the zero register.
+    if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
+      return Reg31IsStackPointer;
+    }
+    return Reg31IsZeroRegister;
+  }
+
+  inline ImmBranchType BranchType() const {
+    if (IsCondBranchImm()) {
+      return CondBranchType;
+    } else if (IsUncondBranchImm()) {
+      return UncondBranchType;
+    } else if (IsCompareBranch()) {
+      return CompareBranchType;
+    } else if (IsTestBranch()) {
+      return TestBranchType;
+    } else {
+      return UnknownBranchType;
+    }
+  }
+
+  // Find the target of this instruction. 'this' may be a branch or a
+  // PC-relative addressing instruction.
+  Instruction* ImmPCOffsetTarget();
+
+  // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
+  // a PC-relative addressing instruction.
+  void SetImmPCOffsetTarget(Instruction* target);
+  // Patch a literal load instruction to load from 'source'.
+  void SetImmLLiteral(Instruction* source);
+
+  inline uint8_t* LiteralAddress() {
+    int offset = ImmLLiteral() << kLiteralEntrySizeLog2;
+    return reinterpret_cast<uint8_t*>(this) + offset;
+  }
+
+  inline uint32_t Literal32() {
+    uint32_t literal;
+    memcpy(&literal, LiteralAddress(), sizeof(literal));
+
+    return literal;
+  }
+
+  inline uint64_t Literal64() {
+    uint64_t literal;
+    memcpy(&literal, LiteralAddress(), sizeof(literal));
+
+    return literal;
+  }
+
+  inline float LiteralFP32() {
+    return rawbits_to_float(Literal32());
+  }
+
+  inline double LiteralFP64() {
+    return rawbits_to_double(Literal64());
+  }
+
+  inline Instruction* NextInstruction() {
+    return this + kInstructionSize;
+  }
+
+  inline Instruction* InstructionAtOffset(int64_t offset) {
+    ASSERT(IsWordAligned(this + offset));
+    return this + offset;
+  }
+
+  template<typename T> static inline Instruction* Cast(T src) {
+    return reinterpret_cast<Instruction*>(src);
+  }
+
+ private:
+  inline int ImmBranch() const;
+
+  void SetPCRelImmTarget(Instruction* target);
+  void SetBranchImmTarget(Instruction* target);
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_INSTRUCTIONS_A64_H_
diff --git a/disas/libvixl/src/a64/instrument-a64.cc b/disas/libvixl/src/a64/instrument-a64.cc
new file mode 100644
index 0000000..507410d
--- /dev/null
+++ b/disas/libvixl/src/a64/instrument-a64.cc
@@ -0,0 +1,638 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/instrument-a64.h"
+
+namespace vixl {
+
+Counter::Counter(const char* name, CounterType type)
+    : count_(0), enabled_(false), type_(type) {
+  ASSERT(name != NULL);
+  strncpy(name_, name, kCounterNameMaxLength);
+}
+
+
+void Counter::Enable() {
+  enabled_ = true;
+}
+
+
+void Counter::Disable() {
+  enabled_ = false;
+}
+
+
+bool Counter::IsEnabled() {
+  return enabled_;
+}
+
+
+void Counter::Increment() {
+  if (enabled_) {
+    count_++;
+  }
+}
+
+
+uint64_t Counter::count() {
+  uint64_t result = count_;
+  if (type_ == Gauge) {
+    // If the counter is a Gauge, reset the count after reading.
+    count_ = 0;
+  }
+  return result;
+}
+
+
+const char* Counter::name() {
+  return name_;
+}
+
+
+CounterType Counter::type() {
+  return type_;
+}
+
+
+typedef struct {
+  const char* name;
+  CounterType type;
+} CounterDescriptor;
+
+
+static const CounterDescriptor kCounterList[] = {
+  {"Instruction", Cumulative},
+
+  {"Move Immediate", Gauge},
+  {"Add/Sub DP", Gauge},
+  {"Logical DP", Gauge},
+  {"Other Int DP", Gauge},
+  {"FP DP", Gauge},
+
+  {"Conditional Select", Gauge},
+  {"Conditional Compare", Gauge},
+
+  {"Unconditional Branch", Gauge},
+  {"Compare and Branch", Gauge},
+  {"Test and Branch", Gauge},
+  {"Conditional Branch", Gauge},
+
+  {"Load Integer", Gauge},
+  {"Load FP", Gauge},
+  {"Load Pair", Gauge},
+  {"Load Literal", Gauge},
+
+  {"Store Integer", Gauge},
+  {"Store FP", Gauge},
+  {"Store Pair", Gauge},
+
+  {"PC Addressing", Gauge},
+  {"Other", Gauge},
+};
+
+
+Instrument::Instrument(const char* datafile, uint64_t sample_period)
+    : output_stream_(stdout), sample_period_(sample_period) {
+
+  // Set up the output stream. If datafile is non-NULL, use that file. If it
+  // can't be opened, or datafile is NULL, use stdout.
+  if (datafile != NULL) {
+    output_stream_ = fopen(datafile, "w");
+    if (output_stream_ == NULL) {
+      printf("Can't open output file %s. Using stdout.\n", datafile);
+      output_stream_ = stdout;
+    }
+  }
+
+  static const int num_counters =
+    sizeof(kCounterList) / sizeof(CounterDescriptor);
+
+  // Dump an instrumentation description comment at the top of the file.
+  fprintf(output_stream_, "# counters=%d\n", num_counters);
+  fprintf(output_stream_, "# sample_period=%" PRIu64 "\n", sample_period_);
+
+  // Construct Counter objects from counter description array.
+  for (int i = 0; i < num_counters; i++) {
+    Counter* counter = new Counter(kCounterList[i].name, kCounterList[i].type);
+    counters_.push_back(counter);
+  }
+
+  DumpCounterNames();
+}
+
+
+Instrument::~Instrument() {
+  // Dump any remaining instruction data to the output file.
+  DumpCounters();
+
+  // Free all the counter objects.
+  std::list<Counter*>::iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    free(*it);
+  }
+
+  if (output_stream_ != stdout) {
+    fclose(output_stream_);
+  }
+}
+
+
+void Instrument::Update() {
+  // Increment the instruction counter, and dump all counters if a sample period
+  // has elapsed.
+  static Counter* counter = GetCounter("Instruction");
+  ASSERT(counter->type() == Cumulative);
+  counter->Increment();
+
+  if (counter->IsEnabled() && (counter->count() % sample_period_) == 0) {
+    DumpCounters();
+  }
+}
+
+
+void Instrument::DumpCounters() {
+  // Iterate through the counter objects, dumping their values to the output
+  // stream.
+  std::list<Counter*>::const_iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    fprintf(output_stream_, "%" PRIu64 ",", (*it)->count());
+  }
+  fprintf(output_stream_, "\n");
+  fflush(output_stream_);
+}
+
+
+void Instrument::DumpCounterNames() {
+  // Iterate through the counter objects, dumping the counter names to the
+  // output stream.
+  std::list<Counter*>::const_iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    fprintf(output_stream_, "%s,", (*it)->name());
+  }
+  fprintf(output_stream_, "\n");
+  fflush(output_stream_);
+}
+
+
+void Instrument::HandleInstrumentationEvent(unsigned event) {
+  switch (event) {
+    case InstrumentStateEnable: Enable(); break;
+    case InstrumentStateDisable: Disable(); break;
+    default: DumpEventMarker(event);
+  }
+}
+
+
+void Instrument::DumpEventMarker(unsigned marker) {
+  // Dumpan event marker to the output stream as a specially formatted comment
+  // line.
+  static Counter* counter = GetCounter("Instruction");
+
+  fprintf(output_stream_, "# %c%c @ %" PRId64 "\n", marker & 0xff,
+          (marker >> 8) & 0xff, counter->count());
+}
+
+
+Counter* Instrument::GetCounter(const char* name) {
+  // Get a Counter object by name from the counter list.
+  std::list<Counter*>::const_iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    if (strcmp((*it)->name(), name) == 0) {
+      return *it;
+    }
+  }
+
+  // A Counter by that name does not exist: print an error message to stderr
+  // and the output file, and exit.
+  static const char* error_message =
+    "# Error: Unknown counter \"%s\". Exiting.\n";
+  fprintf(stderr, error_message, name);
+  fprintf(output_stream_, error_message, name);
+  exit(1);
+}
+
+
+void Instrument::Enable() {
+  std::list<Counter*>::iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    (*it)->Enable();
+  }
+}
+
+
+void Instrument::Disable() {
+  std::list<Counter*>::iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    (*it)->Disable();
+  }
+}
+
+
+void Instrument::VisitPCRelAddressing(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("PC Addressing");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitLogicalImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Logical DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitMoveWideImmediate(Instruction* instr) {
+  Update();
+  static Counter* counter = GetCounter("Move Immediate");
+
+  if (instr->IsMovn() && (instr->Rd() == kZeroRegCode)) {
+    unsigned imm = instr->ImmMoveWide();
+    HandleInstrumentationEvent(imm);
+  } else {
+    counter->Increment();
+  }
+}
+
+
+void Instrument::VisitBitfield(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitExtract(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnconditionalBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Unconditional Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnconditionalBranchToRegister(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Unconditional Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitCompareBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Compare and Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitTestBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Test and Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitSystem(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+void Instrument::VisitException(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+void Instrument::InstrumentLoadStorePair(Instruction* instr) {
+  static Counter* load_pair_counter = GetCounter("Load Pair");
+  static Counter* store_pair_counter = GetCounter("Store Pair");
+
+  if (instr->Mask(LoadStorePairLBit) != 0) {
+    load_pair_counter->Increment();
+  } else {
+    store_pair_counter->Increment();
+  }
+}
+
+
+void Instrument::VisitLoadStorePairPostIndex(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadStorePairOffset(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadStorePairPreIndex(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadStorePairNonTemporal(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadLiteral(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Load Literal");
+  counter->Increment();
+}
+
+
+void Instrument::InstrumentLoadStore(Instruction* instr) {
+  static Counter* load_int_counter = GetCounter("Load Integer");
+  static Counter* store_int_counter = GetCounter("Store Integer");
+  static Counter* load_fp_counter = GetCounter("Load FP");
+  static Counter* store_fp_counter = GetCounter("Store FP");
+
+  switch (instr->Mask(LoadStoreOpMask)) {
+    case STRB_w:    // Fall through.
+    case STRH_w:    // Fall through.
+    case STR_w:     // Fall through.
+    case STR_x:     store_int_counter->Increment(); break;
+    case STR_s:     // Fall through.
+    case STR_d:     store_fp_counter->Increment(); break;
+    case LDRB_w:    // Fall through.
+    case LDRH_w:    // Fall through.
+    case LDR_w:     // Fall through.
+    case LDR_x:     // Fall through.
+    case LDRSB_x:   // Fall through.
+    case LDRSH_x:   // Fall through.
+    case LDRSW_x:   // Fall through.
+    case LDRSB_w:   // Fall through.
+    case LDRSH_w:   load_int_counter->Increment(); break;
+    case LDR_s:     // Fall through.
+    case LDR_d:     load_fp_counter->Increment(); break;
+  }
+}
+
+
+void Instrument::VisitLoadStoreUnscaledOffset(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStorePostIndex(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStorePreIndex(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStoreRegisterOffset(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStoreUnsignedOffset(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLogicalShifted(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Logical DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubShifted(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubExtended(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubWithCarry(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalCompareRegister(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Compare");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalCompareImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Compare");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalSelect(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Select");
+  counter->Increment();
+}
+
+
+void Instrument::VisitDataProcessing1Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitDataProcessing2Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitDataProcessing3Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPCompare(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPConditionalCompare(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Compare");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPConditionalSelect(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Select");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPDataProcessing1Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPDataProcessing2Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPDataProcessing3Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPIntegerConvert(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPFixedPointConvert(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnallocated(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnimplemented(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+}  // namespace v8::internal
diff --git a/disas/libvixl/src/a64/instrument-a64.h b/disas/libvixl/src/a64/instrument-a64.h
new file mode 100644
index 0000000..bee965b
--- /dev/null
+++ b/disas/libvixl/src/a64/instrument-a64.h
@@ -0,0 +1,108 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_INSTRUMENT_A64_H_
+#define VIXL_A64_INSTRUMENT_A64_H_
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/decoder-a64.h"
+#include "a64/constants-a64.h"
+#include "a64/instrument-a64.h"
+
+namespace vixl {
+
+const int kCounterNameMaxLength = 256;
+const uint64_t kDefaultInstrumentationSamplingPeriod = 1 << 22;
+
+
+enum InstrumentState {
+  InstrumentStateDisable = 0,
+  InstrumentStateEnable = 1
+};
+
+
+enum CounterType {
+  Gauge = 0,      // Gauge counters reset themselves after reading.
+  Cumulative = 1  // Cumulative counters keep their value after reading.
+};
+
+
+class Counter {
+ public:
+  Counter(const char* name, CounterType type = Gauge);
+  ~Counter();
+
+  void Increment();
+  void Enable();
+  void Disable();
+  bool IsEnabled();
+  uint64_t count();
+  const char* name();
+  CounterType type();
+
+ private:
+  char name_[kCounterNameMaxLength];
+  uint64_t count_;
+  bool enabled_;
+  CounterType type_;
+};
+
+
+class Instrument: public DecoderVisitor {
+ public:
+  explicit Instrument(const char* datafile = NULL,
+    uint64_t sample_period = kDefaultInstrumentationSamplingPeriod);
+  ~Instrument();
+
+  void Enable();
+  void Disable();
+
+  // Declare all Visitor functions.
+  #define DECLARE(A) void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+ private:
+  void Update();
+  void DumpCounters();
+  void DumpCounterNames();
+  void DumpEventMarker(unsigned marker);
+  void HandleInstrumentationEvent(unsigned event);
+  Counter* GetCounter(const char* name);
+
+  void InstrumentLoadStore(Instruction* instr);
+  void InstrumentLoadStorePair(Instruction* instr);
+
+  std::list<Counter*> counters_;
+
+  FILE *output_stream_;
+  uint64_t sample_period_;
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_INSTRUMENT_A64_H_
diff --git a/disas/libvixl/src/a64/macro-assembler-a64.cc b/disas/libvixl/src/a64/macro-assembler-a64.cc
new file mode 100644
index 0000000..39a925c
--- /dev/null
+++ b/disas/libvixl/src/a64/macro-assembler-a64.cc
@@ -0,0 +1,1108 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/macro-assembler-a64.h"
+namespace vixl {
+
+void MacroAssembler::And(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, (S == SetFlags) ? ANDS : AND);
+}
+
+
+void MacroAssembler::Tst(const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  And(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void MacroAssembler::Bic(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, (S == SetFlags) ? BICS : BIC);
+}
+
+
+void MacroAssembler::Orr(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, ORR);
+}
+
+
+void MacroAssembler::Orn(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, ORN);
+}
+
+
+void MacroAssembler::Eor(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, EOR);
+}
+
+
+void MacroAssembler::Eon(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, EON);
+}
+
+
+void MacroAssembler::LogicalMacro(const Register& rd,
+                                  const Register& rn,
+                                  const Operand& operand,
+                                  LogicalOp op) {
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    unsigned reg_size = rd.size();
+    ASSERT(rd.Is64Bits() || is_uint32(immediate));
+
+    // If the operation is NOT, invert the operation and immediate.
+    if ((op & NOT) == NOT) {
+      op = static_cast<LogicalOp>(op & ~NOT);
+      immediate = ~immediate;
+      if (rd.Is32Bits()) {
+        immediate &= kWRegMask;
+      }
+    }
+
+    // Special cases for all set or all clear immediates.
+    if (immediate == 0) {
+      switch (op) {
+        case AND:
+          Mov(rd, 0);
+          return;
+        case ORR:  // Fall through.
+        case EOR:
+          Mov(rd, rn);
+          return;
+        case ANDS:  // Fall through.
+        case BICS:
+          break;
+        default:
+          UNREACHABLE();
+      }
+    } else if ((rd.Is64Bits() && (immediate == -1L)) ||
+               (rd.Is32Bits() && (immediate == 0xffffffffL))) {
+      switch (op) {
+        case AND:
+          Mov(rd, rn);
+          return;
+        case ORR:
+          Mov(rd, immediate);
+          return;
+        case EOR:
+          Mvn(rd, rn);
+          return;
+        case ANDS:  // Fall through.
+        case BICS:
+          break;
+        default:
+          UNREACHABLE();
+      }
+    }
+
+    unsigned n, imm_s, imm_r;
+    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
+      // Immediate can be encoded in the instruction.
+      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
+    } else {
+      // Immediate can't be encoded: synthesize using move immediate.
+      Register temp = AppropriateTempFor(rn);
+      Mov(temp, immediate);
+      if (rd.Is(sp)) {
+        // If rd is the stack pointer we cannot use it as the destination
+        // register so we use the temp register as an intermediate again.
+        Logical(temp, rn, Operand(temp), op);
+        Mov(sp, temp);
+      } else {
+        Logical(rd, rn, Operand(temp), op);
+      }
+    }
+  } else if (operand.IsExtendedRegister()) {
+    ASSERT(operand.reg().size() <= rd.size());
+    // Add/sub extended supports shift <= 4. We want to support exactly the
+    // same modes here.
+    ASSERT(operand.shift_amount() <= 4);
+    ASSERT(operand.reg().Is64Bits() ||
+           ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
+    Register temp = AppropriateTempFor(rn, operand.reg());
+    EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    Logical(rd, rn, Operand(temp), op);
+  } else {
+    // The operand can be encoded in the instruction.
+    ASSERT(operand.IsShiftedRegister());
+    Logical(rd, rn, operand, op);
+  }
+}
+
+
+void MacroAssembler::Mov(const Register& rd, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate()) {
+    // Call the macro assembler for generic immediates.
+    Mov(rd, operand.immediate());
+  } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
+    // Emit a shift instruction if moving a shifted register. This operation
+    // could also be achieved using an orr instruction (like orn used by Mvn),
+    // but using a shift instruction makes the disassembly clearer.
+    EmitShift(rd, operand.reg(), operand.shift(), operand.shift_amount());
+  } else if (operand.IsExtendedRegister()) {
+    // Emit an extend instruction if moving an extended register. This handles
+    // extend with post-shift operations, too.
+    EmitExtendShift(rd, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+  } else {
+    // Otherwise, emit a register move only if the registers are distinct, or
+    // if they are not X registers. Note that mov(w0, w0) is not a no-op
+    // because it clears the top word of x0.
+    // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
+    if (!rd.Is(operand.reg()) || !rd.Is64Bits()) {
+      mov(rd, operand.reg());
+    }
+  }
+}
+
+
+void MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate()) {
+    // Call the macro assembler for generic immediates.
+    Mvn(rd, operand.immediate());
+  } else if (operand.IsExtendedRegister()) {
+    // Emit two instructions for the extend case. This differs from Mov, as
+    // the extend and invert can't be achieved in one instruction.
+    Register temp = AppropriateTempFor(rd, operand.reg());
+    EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    mvn(rd, Operand(temp));
+  } else {
+    // Otherwise, register and shifted register cases can be handled by the
+    // assembler directly, using orn.
+    mvn(rd, operand);
+  }
+}
+
+
+void MacroAssembler::Mov(const Register& rd, uint64_t imm) {
+  ASSERT(allow_macro_instructions_);
+  ASSERT(is_uint32(imm) || is_int32(imm) || rd.Is64Bits());
+
+  // Immediates on Aarch64 can be produced using an initial value, and zero to
+  // three move keep operations.
+  //
+  // Initial values can be generated with:
+  //  1. 64-bit move zero (movz).
+  //  2. 32-bit move negative (movn).
+  //  3. 64-bit move negative.
+  //  4. 32-bit orr immediate.
+  //  5. 64-bit orr immediate.
+  // Move-keep may then be used to modify each of the 16-bit nybbles.
+  //
+  // The code below supports all five initial value generators, and
+  // applying move-keep operations to move-zero initial values only.
+
+  unsigned reg_size = rd.size();
+  unsigned n, imm_s, imm_r;
+  if (IsImmMovz(imm, reg_size) && !rd.IsSP()) {
+    // Immediate can be represented in a move zero instruction.
+    movz(rd, imm);
+  } else if (IsImmMovn(imm, reg_size) && !rd.IsSP()) {
+    // Immediate can be represented in a move negative instruction. Movn can't
+    // write to the stack pointer.
+    movn(rd, rd.Is64Bits() ? ~imm : (~imm & kWRegMask));
+  } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
+    // Immediate can be represented in a logical orr instruction.
+    ASSERT(!rd.IsZero());
+    LogicalImmediate(rd, AppropriateZeroRegFor(rd), n, imm_s, imm_r, ORR);
+  } else {
+    // Generic immediate case. Imm will be represented by
+    //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
+    // A move-zero is generated for the first non-zero immX, and a move-keep
+    // for subsequent non-zero immX.
+
+    // Use a temporary register when moving to the stack pointer.
+    Register temp = rd.IsSP() ? AppropriateTempFor(rd) : rd;
+
+    ASSERT((reg_size % 16) == 0);
+    bool first_mov_done = false;
+    for (unsigned i = 0; i < (temp.size() / 16); i++) {
+      uint64_t imm16 = (imm >> (16 * i)) & 0xffffL;
+      if (imm16 != 0) {
+        if (!first_mov_done) {
+          // Move the first non-zero 16-bit chunk into the destination register.
+          movz(temp, imm16, 16 * i);
+          first_mov_done = true;
+        } else {
+          // Construct a wider constant.
+          movk(temp, imm16, 16 * i);
+        }
+      }
+    }
+
+    if (rd.IsSP()) {
+      mov(rd, temp);
+    }
+
+    ASSERT(first_mov_done);
+  }
+}
+
+
+// The movz instruction can generate immediates containing an arbitrary 16-bit
+// value, with remaining bits set, eg. 0x00001234, 0x0000123400000000.
+bool MacroAssembler::IsImmMovz(uint64_t imm, unsigned reg_size) {
+  if (reg_size == kXRegSize) {
+    if (((imm & 0xffffffffffff0000UL) == 0UL) ||
+        ((imm & 0xffffffff0000ffffUL) == 0UL) ||
+        ((imm & 0xffff0000ffffffffUL) == 0UL) ||
+        ((imm & 0x0000ffffffffffffUL) == 0UL)) {
+      return true;
+    }
+  } else {
+    ASSERT(reg_size == kWRegSize);
+    imm &= kWRegMask;
+    if (((imm & 0xffff0000) == 0) ||
+        ((imm & 0x0000ffff) == 0)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+// The movn instruction can generate immediates containing an arbitrary 16-bit
+// value, with remaining bits set, eg. 0xffff1234, 0xffff1234ffffffff.
+bool MacroAssembler::IsImmMovn(uint64_t imm, unsigned reg_size) {
+  return IsImmMovz(~imm, reg_size);
+}
+
+
+void MacroAssembler::Ccmp(const Register& rn,
+                          const Operand& operand,
+                          StatusFlags nzcv,
+                          Condition cond) {
+  ASSERT(allow_macro_instructions_);
+  ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
+}
+
+
+void MacroAssembler::Ccmn(const Register& rn,
+                          const Operand& operand,
+                          StatusFlags nzcv,
+                          Condition cond) {
+  ASSERT(allow_macro_instructions_);
+  ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
+}
+
+
+void MacroAssembler::ConditionalCompareMacro(const Register& rn,
+                                             const Operand& operand,
+                                             StatusFlags nzcv,
+                                             Condition cond,
+                                             ConditionalCompareOp op) {
+  ASSERT((cond != al) && (cond != nv));
+  if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) ||
+      (operand.IsImmediate() && IsImmConditionalCompare(operand.immediate()))) {
+    // The immediate can be encoded in the instruction, or the operand is an
+    // unshifted register: call the assembler.
+    ConditionalCompare(rn, operand, nzcv, cond, op);
+  } else {
+    // The operand isn't directly supported by the instruction: perform the
+    // operation on a temporary register.
+    Register temp(NoReg);
+    if (operand.IsImmediate()) {
+      temp = AppropriateTempFor(rn);
+      Mov(temp, operand.immediate());
+    } else if (operand.IsShiftedRegister()) {
+      ASSERT(operand.shift() != ROR);
+      ASSERT(is_uintn(rn.size() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
+                      operand.shift_amount()));
+      temp = AppropriateTempFor(rn, operand.reg());
+      EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
+    } else {
+      ASSERT(operand.IsExtendedRegister());
+      ASSERT(operand.reg().size() <= rn.size());
+      // Add/sub extended support a shift <= 4. We want to support exactly the
+      // same modes.
+      ASSERT(operand.shift_amount() <= 4);
+      ASSERT(operand.reg().Is64Bits() ||
+             ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
+      temp = AppropriateTempFor(rn, operand.reg());
+      EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    }
+    ConditionalCompare(rn, Operand(temp), nzcv, cond, op);
+  }
+}
+
+
+void MacroAssembler::Add(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate() && (operand.immediate() < 0)) {
+    AddSubMacro(rd, rn, -operand.immediate(), S, SUB);
+  } else {
+    AddSubMacro(rd, rn, operand, S, ADD);
+  }
+}
+
+
+void MacroAssembler::Sub(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate() && (operand.immediate() < 0)) {
+    AddSubMacro(rd, rn, -operand.immediate(), S, ADD);
+  } else {
+    AddSubMacro(rd, rn, operand, S, SUB);
+  }
+}
+
+
+void MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  Add(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  Sub(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void MacroAssembler::Neg(const Register& rd,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate()) {
+    Mov(rd, -operand.immediate());
+  } else {
+    Sub(rd, AppropriateZeroRegFor(rd), operand, S);
+  }
+}
+
+
+void MacroAssembler::AddSubMacro(const Register& rd,
+                                 const Register& rn,
+                                 const Operand& operand,
+                                 FlagsUpdate S,
+                                 AddSubOp op) {
+  if ((operand.IsImmediate() && !IsImmAddSub(operand.immediate())) ||
+      (rn.IsZero() && !operand.IsShiftedRegister())                ||
+      (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
+    Register temp = AppropriateTempFor(rn);
+    Mov(temp, operand);
+    AddSub(rd, rn, temp, S, op);
+  } else {
+    AddSub(rd, rn, operand, S, op);
+  }
+}
+
+
+void MacroAssembler::Adc(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  AddSubWithCarryMacro(rd, rn, operand, S, ADC);
+}
+
+
+void MacroAssembler::Sbc(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  AddSubWithCarryMacro(rd, rn, operand, S, SBC);
+}
+
+
+void MacroAssembler::Ngc(const Register& rd,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  Register zr = AppropriateZeroRegFor(rd);
+  Sbc(rd, zr, operand, S);
+}
+
+
+void MacroAssembler::AddSubWithCarryMacro(const Register& rd,
+                                          const Register& rn,
+                                          const Operand& operand,
+                                          FlagsUpdate S,
+                                          AddSubWithCarryOp op) {
+  ASSERT(rd.size() == rn.size());
+
+  if (operand.IsImmediate() ||
+      (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
+    // Add/sub with carry (immediate or ROR shifted register.)
+    Register temp = AppropriateTempFor(rn);
+    Mov(temp, operand);
+    AddSubWithCarry(rd, rn, Operand(temp), S, op);
+  } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
+    // Add/sub with carry (shifted register).
+    ASSERT(operand.reg().size() == rd.size());
+    ASSERT(operand.shift() != ROR);
+    ASSERT(is_uintn(rd.size() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
+                    operand.shift_amount()));
+    Register temp = AppropriateTempFor(rn, operand.reg());
+    EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
+    AddSubWithCarry(rd, rn, Operand(temp), S, op);
+  } else if (operand.IsExtendedRegister()) {
+    // Add/sub with carry (extended register).
+    ASSERT(operand.reg().size() <= rd.size());
+    // Add/sub extended supports a shift <= 4. We want to support exactly the
+    // same modes.
+    ASSERT(operand.shift_amount() <= 4);
+    ASSERT(operand.reg().Is64Bits() ||
+           ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
+    Register temp = AppropriateTempFor(rn, operand.reg());
+    EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    AddSubWithCarry(rd, rn, Operand(temp), S, op);
+  } else {
+    // The addressing mode is directly supported by the instruction.
+    AddSubWithCarry(rd, rn, operand, S, op);
+  }
+}
+
+
+#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                         \
+void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) {  \
+  LoadStoreMacro(REG, addr, OP);                                      \
+}
+LS_MACRO_LIST(DEFINE_FUNCTION)
+#undef DEFINE_FUNCTION
+
+void MacroAssembler::LoadStoreMacro(const CPURegister& rt,
+                                    const MemOperand& addr,
+                                    LoadStoreOp op) {
+  int64_t offset = addr.offset();
+  LSDataSize size = CalcLSDataSize(op);
+
+  // Check if an immediate offset fits in the immediate field of the
+  // appropriate instruction. If not, emit two instructions to perform
+  // the operation.
+  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, size) &&
+      !IsImmLSUnscaled(offset)) {
+    // Immediate offset that can't be encoded using unsigned or unscaled
+    // addressing modes.
+    Register temp = AppropriateTempFor(addr.base());
+    Mov(temp, addr.offset());
+    LoadStore(rt, MemOperand(addr.base(), temp), op);
+  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
+    // Post-index beyond unscaled addressing range.
+    LoadStore(rt, MemOperand(addr.base()), op);
+    Add(addr.base(), addr.base(), Operand(offset));
+  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
+    // Pre-index beyond unscaled addressing range.
+    Add(addr.base(), addr.base(), Operand(offset));
+    LoadStore(rt, MemOperand(addr.base()), op);
+  } else {
+    // Encodable in one load/store instruction.
+    LoadStore(rt, addr, op);
+  }
+}
+
+
+void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1,
+                          const CPURegister& src2, const CPURegister& src3) {
+  ASSERT(allow_macro_instructions_);
+  ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
+  ASSERT(src0.IsValid());
+
+  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
+  int size = src0.SizeInBytes();
+
+  PrepareForPush(count, size);
+  PushHelper(count, size, src0, src1, src2, src3);
+}
+
+
+void MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1,
+                         const CPURegister& dst2, const CPURegister& dst3) {
+  // It is not valid to pop into the same register more than once in one
+  // instruction, not even into the zero register.
+  ASSERT(allow_macro_instructions_);
+  ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
+  ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
+  ASSERT(dst0.IsValid());
+
+  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
+  int size = dst0.SizeInBytes();
+
+  PrepareForPop(count, size);
+  PopHelper(count, size, dst0, dst1, dst2, dst3);
+}
+
+
+void MacroAssembler::PushCPURegList(CPURegList registers) {
+  int size = registers.RegisterSizeInBytes();
+
+  PrepareForPush(registers.Count(), size);
+  // Push up to four registers at a time because if the current stack pointer is
+  // sp and reg_size is 32, registers must be pushed in blocks of four in order
+  // to maintain the 16-byte alignment for sp.
+  ASSERT(allow_macro_instructions_);
+  while (!registers.IsEmpty()) {
+    int count_before = registers.Count();
+    const CPURegister& src0 = registers.PopHighestIndex();
+    const CPURegister& src1 = registers.PopHighestIndex();
+    const CPURegister& src2 = registers.PopHighestIndex();
+    const CPURegister& src3 = registers.PopHighestIndex();
+    int count = count_before - registers.Count();
+    PushHelper(count, size, src0, src1, src2, src3);
+  }
+}
+
+
+void MacroAssembler::PopCPURegList(CPURegList registers) {
+  int size = registers.RegisterSizeInBytes();
+
+  PrepareForPop(registers.Count(), size);
+  // Pop up to four registers at a time because if the current stack pointer is
+  // sp and reg_size is 32, registers must be pushed in blocks of four in order
+  // to maintain the 16-byte alignment for sp.
+  ASSERT(allow_macro_instructions_);
+  while (!registers.IsEmpty()) {
+    int count_before = registers.Count();
+    const CPURegister& dst0 = registers.PopLowestIndex();
+    const CPURegister& dst1 = registers.PopLowestIndex();
+    const CPURegister& dst2 = registers.PopLowestIndex();
+    const CPURegister& dst3 = registers.PopLowestIndex();
+    int count = count_before - registers.Count();
+    PopHelper(count, size, dst0, dst1, dst2, dst3);
+  }
+}
+
+
+void MacroAssembler::PushMultipleTimes(int count, Register src) {
+  ASSERT(allow_macro_instructions_);
+  int size = src.SizeInBytes();
+
+  PrepareForPush(count, size);
+  // Push up to four registers at a time if possible because if the current
+  // stack pointer is sp and the register size is 32, registers must be pushed
+  // in blocks of four in order to maintain the 16-byte alignment for sp.
+  while (count >= 4) {
+    PushHelper(4, size, src, src, src, src);
+    count -= 4;
+  }
+  if (count >= 2) {
+    PushHelper(2, size, src, src, NoReg, NoReg);
+    count -= 2;
+  }
+  if (count == 1) {
+    PushHelper(1, size, src, NoReg, NoReg, NoReg);
+    count -= 1;
+  }
+  ASSERT(count == 0);
+}
+
+
+void MacroAssembler::PushHelper(int count, int size,
+                                const CPURegister& src0,
+                                const CPURegister& src1,
+                                const CPURegister& src2,
+                                const CPURegister& src3) {
+  // Ensure that we don't unintentionally modify scratch or debug registers.
+  InstructionAccurateScope scope(this);
+
+  ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
+  ASSERT(size == src0.SizeInBytes());
+
+  // When pushing multiple registers, the store order is chosen such that
+  // Push(a, b) is equivalent to Push(a) followed by Push(b).
+  switch (count) {
+    case 1:
+      ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
+      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
+      break;
+    case 2:
+      ASSERT(src2.IsNone() && src3.IsNone());
+      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
+      break;
+    case 3:
+      ASSERT(src3.IsNone());
+      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
+      str(src0, MemOperand(StackPointer(), 2 * size));
+      break;
+    case 4:
+      // Skip over 4 * size, then fill in the gap. This allows four W registers
+      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
+      // all times.
+      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
+      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void MacroAssembler::PopHelper(int count, int size,
+                               const CPURegister& dst0,
+                               const CPURegister& dst1,
+                               const CPURegister& dst2,
+                               const CPURegister& dst3) {
+  // Ensure that we don't unintentionally modify scratch or debug registers.
+  InstructionAccurateScope scope(this);
+
+  ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
+  ASSERT(size == dst0.SizeInBytes());
+
+  // When popping multiple registers, the load order is chosen such that
+  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
+  switch (count) {
+    case 1:
+      ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
+      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
+      break;
+    case 2:
+      ASSERT(dst2.IsNone() && dst3.IsNone());
+      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
+      break;
+    case 3:
+      ASSERT(dst3.IsNone());
+      ldr(dst2, MemOperand(StackPointer(), 2 * size));
+      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
+      break;
+    case 4:
+      // Load the higher addresses first, then load the lower addresses and skip
+      // the whole block in the second instruction. This allows four W registers
+      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
+      // all times.
+      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
+      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void MacroAssembler::PrepareForPush(int count, int size) {
+  if (sp.Is(StackPointer())) {
+    // If the current stack pointer is sp, then it must be aligned to 16 bytes
+    // on entry and the total size of the specified registers must also be a
+    // multiple of 16 bytes.
+    ASSERT((count * size) % 16 == 0);
+  } else {
+    // Even if the current stack pointer is not the system stack pointer (sp),
+    // the system stack pointer will still be modified in order to comply with
+    // ABI rules about accessing memory below the system stack pointer.
+    BumpSystemStackPointer(count * size);
+  }
+}
+
+
+void MacroAssembler::PrepareForPop(int count, int size) {
+  USE(count);
+  USE(size);
+  if (sp.Is(StackPointer())) {
+    // If the current stack pointer is sp, then it must be aligned to 16 bytes
+    // on entry and the total size of the specified registers must also be a
+    // multiple of 16 bytes.
+    ASSERT((count * size) % 16 == 0);
+  }
+}
+
+void MacroAssembler::Poke(const Register& src, const Operand& offset) {
+  ASSERT(allow_macro_instructions_);
+  if (offset.IsImmediate()) {
+    ASSERT(offset.immediate() >= 0);
+  }
+
+  Str(src, MemOperand(StackPointer(), offset));
+}
+
+
+void MacroAssembler::Peek(const Register& dst, const Operand& offset) {
+  ASSERT(allow_macro_instructions_);
+  if (offset.IsImmediate()) {
+    ASSERT(offset.immediate() >= 0);
+  }
+
+  Ldr(dst, MemOperand(StackPointer(), offset));
+}
+
+
+void MacroAssembler::Claim(const Operand& size) {
+  ASSERT(allow_macro_instructions_);
+  if (size.IsImmediate()) {
+    ASSERT(size.immediate() >= 0);
+    if (sp.Is(StackPointer())) {
+      ASSERT((size.immediate() % 16) == 0);
+    }
+  }
+
+  if (!sp.Is(StackPointer())) {
+    BumpSystemStackPointer(size);
+  }
+
+  Sub(StackPointer(), StackPointer(), size);
+}
+
+
+void MacroAssembler::Drop(const Operand& size) {
+  ASSERT(allow_macro_instructions_);
+  if (size.IsImmediate()) {
+    ASSERT(size.immediate() >= 0);
+    if (sp.Is(StackPointer())) {
+      ASSERT((size.immediate() % 16) == 0);
+    }
+  }
+
+  Add(StackPointer(), StackPointer(), size);
+}
+
+
+void MacroAssembler::PushCalleeSavedRegisters() {
+  // Ensure that the macro-assembler doesn't use any scratch registers.
+  InstructionAccurateScope scope(this);
+
+  // This method must not be called unless the current stack pointer is sp.
+  ASSERT(sp.Is(StackPointer()));
+
+  MemOperand tos(sp, -2 * kXRegSizeInBytes, PreIndex);
+
+  stp(d14, d15, tos);
+  stp(d12, d13, tos);
+  stp(d10, d11, tos);
+  stp(d8, d9, tos);
+
+  stp(x29, x30, tos);
+  stp(x27, x28, tos);
+  stp(x25, x26, tos);
+  stp(x23, x24, tos);
+  stp(x21, x22, tos);
+  stp(x19, x20, tos);
+}
+
+
+void MacroAssembler::PopCalleeSavedRegisters() {
+  // Ensure that the macro-assembler doesn't use any scratch registers.
+  InstructionAccurateScope scope(this);
+
+  // This method must not be called unless the current stack pointer is sp.
+  ASSERT(sp.Is(StackPointer()));
+
+  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
+
+  ldp(x19, x20, tos);
+  ldp(x21, x22, tos);
+  ldp(x23, x24, tos);
+  ldp(x25, x26, tos);
+  ldp(x27, x28, tos);
+  ldp(x29, x30, tos);
+
+  ldp(d8, d9, tos);
+  ldp(d10, d11, tos);
+  ldp(d12, d13, tos);
+  ldp(d14, d15, tos);
+}
+
+void MacroAssembler::BumpSystemStackPointer(const Operand& space) {
+  ASSERT(!sp.Is(StackPointer()));
+  // TODO: Several callers rely on this not using scratch registers, so we use
+  // the assembler directly here. However, this means that large immediate
+  // values of 'space' cannot be handled.
+  InstructionAccurateScope scope(this);
+  sub(sp, StackPointer(), space);
+}
+
+
+// This is the main Printf implementation. All callee-saved registers are
+// preserved, but NZCV and the caller-saved registers may be clobbered.
+void MacroAssembler::PrintfNoPreserve(const char * format,
+                                      const CPURegister& arg0,
+                                      const CPURegister& arg1,
+                                      const CPURegister& arg2,
+                                      const CPURegister& arg3) {
+  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
+  // in most cases anyway, so this restriction shouldn't be too serious.
+  ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
+
+  // We cannot print Tmp0() or Tmp1() as they're used internally by the macro
+  // assembler. We cannot print the stack pointer because it is typically used
+  // to preserve caller-saved registers (using other Printf variants which
+  // depend on this helper).
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg0));
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg1));
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg2));
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg3));
+
+  static const int kMaxArgCount = 4;
+  // Assume that we have the maximum number of arguments until we know
+  // otherwise.
+  int arg_count = kMaxArgCount;
+
+  // The provided arguments.
+  CPURegister args[kMaxArgCount] = {arg0, arg1, arg2, arg3};
+
+  // The PCS registers where the arguments need to end up.
+  CPURegister pcs[kMaxArgCount];
+
+  // Promote FP arguments to doubles, and integer arguments to X registers.
+  // Note that FP and integer arguments cannot be mixed, but we'll check
+  // AreSameSizeAndType once we've processed these promotions.
+  for (int i = 0; i < kMaxArgCount; i++) {
+    if (args[i].IsRegister()) {
+      // Note that we use x1 onwards, because x0 will hold the format string.
+      pcs[i] = Register::XRegFromCode(i + 1);
+      // For simplicity, we handle all integer arguments as X registers. An X
+      // register argument takes the same space as a W register argument in the
+      // PCS anyway. The only limitation is that we must explicitly clear the
+      // top word for W register arguments as the callee will expect it to be
+      // clear.
+      if (!args[i].Is64Bits()) {
+        const Register& as_x = args[i].X();
+        And(as_x, as_x, 0x00000000ffffffff);
+        args[i] = as_x;
+      }
+    } else if (args[i].IsFPRegister()) {
+      pcs[i] = FPRegister::DRegFromCode(i);
+      // C and C++ varargs functions (such as printf) implicitly promote float
+      // arguments to doubles.
+      if (!args[i].Is64Bits()) {
+        FPRegister s(args[i]);
+        const FPRegister& as_d = args[i].D();
+        Fcvt(as_d, s);
+        args[i] = as_d;
+      }
+    } else {
+      // This is the first empty (NoCPUReg) argument, so use it to set the
+      // argument count and bail out.
+      arg_count = i;
+      break;
+    }
+  }
+  ASSERT((arg_count >= 0) && (arg_count <= kMaxArgCount));
+  // Check that every remaining argument is NoCPUReg.
+  for (int i = arg_count; i < kMaxArgCount; i++) {
+    ASSERT(args[i].IsNone());
+  }
+  ASSERT((arg_count == 0) || AreSameSizeAndType(args[0], args[1],
+                                                args[2], args[3],
+                                                pcs[0], pcs[1],
+                                                pcs[2], pcs[3]));
+
+  // Move the arguments into the appropriate PCS registers.
+  //
+  // Arranging an arbitrary list of registers into x1-x4 (or d0-d3) is
+  // surprisingly complicated.
+  //
+  //  * For even numbers of registers, we push the arguments and then pop them
+  //    into their final registers. This maintains 16-byte stack alignment in
+  //    case sp is the stack pointer, since we're only handling X or D registers
+  //    at this point.
+  //
+  //  * For odd numbers of registers, we push and pop all but one register in
+  //    the same way, but the left-over register is moved directly, since we
+  //    can always safely move one register without clobbering any source.
+  if (arg_count >= 4) {
+    Push(args[3], args[2], args[1], args[0]);
+  } else if (arg_count >= 2) {
+    Push(args[1], args[0]);
+  }
+
+  if ((arg_count % 2) != 0) {
+    // Move the left-over register directly.
+    const CPURegister& leftover_arg = args[arg_count - 1];
+    const CPURegister& leftover_pcs = pcs[arg_count - 1];
+    if (leftover_arg.IsRegister()) {
+      Mov(Register(leftover_pcs), Register(leftover_arg));
+    } else {
+      Fmov(FPRegister(leftover_pcs), FPRegister(leftover_arg));
+    }
+  }
+
+  if (arg_count >= 4) {
+    Pop(pcs[0], pcs[1], pcs[2], pcs[3]);
+  } else if (arg_count >= 2) {
+    Pop(pcs[0], pcs[1]);
+  }
+
+  // Load the format string into x0, as per the procedure-call standard.
+  //
+  // To make the code as portable as possible, the format string is encoded
+  // directly in the instruction stream. It might be cleaner to encode it in a
+  // literal pool, but since Printf is usually used for debugging, it is
+  // beneficial for it to be minimally dependent on other features.
+  Label format_address;
+  Adr(x0, &format_address);
+
+  // Emit the format string directly in the instruction stream.
+  { BlockLiteralPoolScope scope(this);
+    Label after_data;
+    B(&after_data);
+    Bind(&format_address);
+    EmitStringData(format);
+    Unreachable();
+    Bind(&after_data);
+  }
+
+  // We don't pass any arguments on the stack, but we still need to align the C
+  // stack pointer to a 16-byte boundary for PCS compliance.
+  if (!sp.Is(StackPointer())) {
+    Bic(sp, StackPointer(), 0xf);
+  }
+
+  // Actually call printf. This part needs special handling for the simulator,
+  // since the system printf function will use a different instruction set and
+  // the procedure-call standard will not be compatible.
+#ifdef USE_SIMULATOR
+  { InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
+    hlt(kPrintfOpcode);
+    dc32(pcs[0].type());
+  }
+#else
+  Mov(Tmp0(), reinterpret_cast<uintptr_t>(printf));
+  Blr(Tmp0());
+#endif
+}
+
+
+void MacroAssembler::Printf(const char * format,
+                            const CPURegister& arg0,
+                            const CPURegister& arg1,
+                            const CPURegister& arg2,
+                            const CPURegister& arg3) {
+  // Preserve all caller-saved registers as well as NZCV.
+  // If sp is the stack pointer, PushCPURegList asserts that the size of each
+  // list is a multiple of 16 bytes.
+  PushCPURegList(kCallerSaved);
+  PushCPURegList(kCallerSavedFP);
+  // Use Tmp0() as a scratch register. It is not accepted by Printf so it will
+  // never overlap an argument register.
+  Mrs(Tmp0(), NZCV);
+  Push(Tmp0(), xzr);
+
+  PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
+
+  Pop(xzr, Tmp0());
+  Msr(NZCV, Tmp0());
+  PopCPURegList(kCallerSavedFP);
+  PopCPURegList(kCallerSaved);
+}
+
+void MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
+  ASSERT(allow_macro_instructions_);
+
+#ifdef USE_SIMULATOR
+  // The arguments to the trace pseudo instruction need to be contiguous in
+  // memory, so make sure we don't try to emit a literal pool.
+  InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
+
+  Label start;
+  bind(&start);
+
+  // Refer to instructions-a64.h for a description of the marker and its
+  // arguments.
+  hlt(kTraceOpcode);
+
+  ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
+  dc32(parameters);
+
+  ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
+  dc32(command);
+#else
+  // Emit nothing on real hardware.
+  USE(parameters);
+  USE(command);
+#endif
+}
+
+
+void MacroAssembler::Log(TraceParameters parameters) {
+  ASSERT(allow_macro_instructions_);
+
+#ifdef USE_SIMULATOR
+  // The arguments to the log pseudo instruction need to be contiguous in
+  // memory, so make sure we don't try to emit a literal pool.
+  InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
+
+  Label start;
+  bind(&start);
+
+  // Refer to instructions-a64.h for a description of the marker and its
+  // arguments.
+  hlt(kLogOpcode);
+
+  ASSERT(SizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
+  dc32(parameters);
+#else
+  // Emit nothing on real hardware.
+  USE(parameters);
+#endif
+}
+
+
+void MacroAssembler::EnableInstrumentation() {
+  ASSERT(!isprint(InstrumentStateEnable));
+  InstructionAccurateScope scope(this, 1);
+  movn(xzr, InstrumentStateEnable);
+}
+
+
+void MacroAssembler::DisableInstrumentation() {
+  ASSERT(!isprint(InstrumentStateDisable));
+  InstructionAccurateScope scope(this, 1);
+  movn(xzr, InstrumentStateDisable);
+}
+
+
+void MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
+  ASSERT(strlen(marker_name) == 2);
+
+  // We allow only printable characters in the marker names. Unprintable
+  // characters are reserved for controlling features of the instrumentation.
+  ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
+
+  InstructionAccurateScope scope(this, 1);
+  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/macro-assembler-a64.h b/disas/libvixl/src/a64/macro-assembler-a64.h
new file mode 100644
index 0000000..f266063
--- /dev/null
+++ b/disas/libvixl/src/a64/macro-assembler-a64.h
@@ -0,0 +1,1175 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_MACRO_ASSEMBLER_A64_H_
+#define VIXL_A64_MACRO_ASSEMBLER_A64_H_
+
+#include "globals.h"
+#include "a64/assembler-a64.h"
+#include "a64/debugger-a64.h"
+
+
+#define LS_MACRO_LIST(V)                                      \
+  V(Ldrb, Register&, rt, LDRB_w)                              \
+  V(Strb, Register&, rt, STRB_w)                              \
+  V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w)  \
+  V(Ldrh, Register&, rt, LDRH_w)                              \
+  V(Strh, Register&, rt, STRH_w)                              \
+  V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w)  \
+  V(Ldr, CPURegister&, rt, LoadOpFor(rt))                     \
+  V(Str, CPURegister&, rt, StoreOpFor(rt))                    \
+  V(Ldrsw, Register&, rt, LDRSW_x)
+
+namespace vixl {
+
+class MacroAssembler : public Assembler {
+ public:
+  MacroAssembler(byte * buffer, unsigned buffer_size)
+      : Assembler(buffer, buffer_size),
+#ifdef DEBUG
+        allow_macro_instructions_(true),
+#endif
+        sp_(sp), tmp0_(ip0), tmp1_(ip1), fptmp0_(d31) {}
+
+  // Logical macros.
+  void And(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Bic(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Orr(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Orn(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Eor(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Eon(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Tst(const Register& rn, const Operand& operand);
+  void LogicalMacro(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    LogicalOp op);
+
+  // Add and sub macros.
+  void Add(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Sub(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Cmn(const Register& rn, const Operand& operand);
+  void Cmp(const Register& rn, const Operand& operand);
+  void Neg(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void AddSubMacro(const Register& rd,
+                   const Register& rn,
+                   const Operand& operand,
+                   FlagsUpdate S,
+                   AddSubOp op);
+
+  // Add/sub with carry macros.
+  void Adc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Sbc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Ngc(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void AddSubWithCarryMacro(const Register& rd,
+                            const Register& rn,
+                            const Operand& operand,
+                            FlagsUpdate S,
+                            AddSubWithCarryOp op);
+
+  // Move macros.
+  void Mov(const Register& rd, uint64_t imm);
+  void Mov(const Register& rd, const Operand& operand);
+  void Mvn(const Register& rd, uint64_t imm) {
+    Mov(rd, ~imm);
+  };
+  void Mvn(const Register& rd, const Operand& operand);
+  bool IsImmMovn(uint64_t imm, unsigned reg_size);
+  bool IsImmMovz(uint64_t imm, unsigned reg_size);
+
+  // Conditional compare macros.
+  void Ccmp(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+  void Ccmn(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+  void ConditionalCompareMacro(const Register& rn,
+                               const Operand& operand,
+                               StatusFlags nzcv,
+                               Condition cond,
+                               ConditionalCompareOp op);
+
+  // Load/store macros.
+#define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
+  void FN(const REGTYPE REG, const MemOperand& addr);
+  LS_MACRO_LIST(DECLARE_FUNCTION)
+#undef DECLARE_FUNCTION
+
+  void LoadStoreMacro(const CPURegister& rt,
+                      const MemOperand& addr,
+                      LoadStoreOp op);
+
+  // Push or pop up to 4 registers of the same width to or from the stack,
+  // using the current stack pointer as set by SetStackPointer.
+  //
+  // If an argument register is 'NoReg', all further arguments are also assumed
+  // to be 'NoReg', and are thus not pushed or popped.
+  //
+  // Arguments are ordered such that "Push(a, b);" is functionally equivalent
+  // to "Push(a); Push(b);".
+  //
+  // It is valid to push the same register more than once, and there is no
+  // restriction on the order in which registers are specified.
+  //
+  // It is not valid to pop into the same register more than once in one
+  // operation, not even into the zero register.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then it
+  // must be aligned to 16 bytes on entry and the total size of the specified
+  // registers must also be a multiple of 16 bytes.
+  //
+  // Even if the current stack pointer is not the system stack pointer (sp),
+  // Push (and derived methods) will still modify the system stack pointer in
+  // order to comply with ABI rules about accessing memory below the system
+  // stack pointer.
+  //
+  // Other than the registers passed into Pop, the stack pointer and (possibly)
+  // the system stack pointer, these methods do not modify any other registers.
+  // Scratch registers such as Tmp0() and Tmp1() are preserved.
+  void Push(const CPURegister& src0, const CPURegister& src1 = NoReg,
+            const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg);
+  void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg,
+           const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg);
+
+  // Alternative forms of Push and Pop, taking a RegList or CPURegList that
+  // specifies the registers that are to be pushed or popped. Higher-numbered
+  // registers are associated with higher memory addresses (as in the A32 push
+  // and pop instructions).
+  //
+  // (Push|Pop)SizeRegList allow you to specify the register size as a
+  // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
+  // supported.
+  //
+  // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
+  void PushCPURegList(CPURegList registers);
+  void PopCPURegList(CPURegList registers);
+
+  void PushSizeRegList(RegList registers, unsigned reg_size,
+      CPURegister::RegisterType type = CPURegister::kRegister) {
+    PushCPURegList(CPURegList(type, reg_size, registers));
+  }
+  void PopSizeRegList(RegList registers, unsigned reg_size,
+      CPURegister::RegisterType type = CPURegister::kRegister) {
+    PopCPURegList(CPURegList(type, reg_size, registers));
+  }
+  void PushXRegList(RegList regs) {
+    PushSizeRegList(regs, kXRegSize);
+  }
+  void PopXRegList(RegList regs) {
+    PopSizeRegList(regs, kXRegSize);
+  }
+  void PushWRegList(RegList regs) {
+    PushSizeRegList(regs, kWRegSize);
+  }
+  void PopWRegList(RegList regs) {
+    PopSizeRegList(regs, kWRegSize);
+  }
+  inline void PushDRegList(RegList regs) {
+    PushSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
+  }
+  inline void PopDRegList(RegList regs) {
+    PopSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
+  }
+  inline void PushSRegList(RegList regs) {
+    PushSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
+  }
+  inline void PopSRegList(RegList regs) {
+    PopSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
+  }
+
+  // Push the specified register 'count' times.
+  void PushMultipleTimes(int count, Register src);
+
+  // Poke 'src' onto the stack. The offset is in bytes.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then sp
+  // must be aligned to 16 bytes.
+  void Poke(const Register& src, const Operand& offset);
+
+  // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then sp
+  // must be aligned to 16 bytes.
+  void Peek(const Register& dst, const Operand& offset);
+
+  // Claim or drop stack space without actually accessing memory.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then it
+  // must be aligned to 16 bytes and the size claimed or dropped must be a
+  // multiple of 16 bytes.
+  void Claim(const Operand& size);
+  void Drop(const Operand& size);
+
+  // Preserve the callee-saved registers (as defined by AAPCS64).
+  //
+  // Higher-numbered registers are pushed before lower-numbered registers, and
+  // thus get higher addresses.
+  // Floating-point registers are pushed before general-purpose registers, and
+  // thus get higher addresses.
+  //
+  // This method must not be called unless StackPointer() is sp, and it is
+  // aligned to 16 bytes.
+  void PushCalleeSavedRegisters();
+
+  // Restore the callee-saved registers (as defined by AAPCS64).
+  //
+  // Higher-numbered registers are popped after lower-numbered registers, and
+  // thus come from higher addresses.
+  // Floating-point registers are popped after general-purpose registers, and
+  // thus come from higher addresses.
+  //
+  // This method must not be called unless StackPointer() is sp, and it is
+  // aligned to 16 bytes.
+  void PopCalleeSavedRegisters();
+
+  // Remaining instructions are simple pass-through calls to the assembler.
+  void Adr(const Register& rd, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    adr(rd, label);
+  }
+  void Asr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    asr(rd, rn, shift);
+  }
+  void Asr(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    asrv(rd, rn, rm);
+  }
+  void B(Label* label) {
+    b(label);
+  }
+  void B(Label* label, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT((cond != al) && (cond != nv));
+    b(label, cond);
+  }
+  void Bfi(const Register& rd,
+           const Register& rn,
+           unsigned lsb,
+           unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    bfi(rd, rn, lsb, width);
+  }
+  void Bfxil(const Register& rd,
+             const Register& rn,
+             unsigned lsb,
+             unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    bfxil(rd, rn, lsb, width);
+  }
+  void Bind(Label* label) {
+    ASSERT(allow_macro_instructions_);
+    bind(label);
+  }
+  void Bl(Label* label) {
+    ASSERT(allow_macro_instructions_);
+    bl(label);
+  }
+  void Blr(const Register& xn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xn.IsZero());
+    blr(xn);
+  }
+  void Br(const Register& xn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xn.IsZero());
+    br(xn);
+  }
+  void Brk(int code = 0) {
+    ASSERT(allow_macro_instructions_);
+    brk(code);
+  }
+  void Cbnz(const Register& rt, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    cbnz(rt, label);
+  }
+  void Cbz(const Register& rt, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    cbz(rt, label);
+  }
+  void Cinc(const Register& rd, const Register& rn, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cinc(rd, rn, cond);
+  }
+  void Cinv(const Register& rd, const Register& rn, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cinv(rd, rn, cond);
+  }
+  void Cls(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cls(rd, rn);
+  }
+  void Clz(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    clz(rd, rn);
+  }
+  void Cneg(const Register& rd, const Register& rn, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cneg(rd, rn, cond);
+  }
+  void Csel(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csel(rd, rn, rm, cond);
+  }
+  void Cset(const Register& rd, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    cset(rd, cond);
+  }
+  void Csetm(const Register& rd, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    csetm(rd, cond);
+  }
+  void Csinc(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csinc(rd, rn, rm, cond);
+  }
+  void Csinv(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csinv(rd, rn, rm, cond);
+  }
+  void Csneg(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csneg(rd, rn, rm, cond);
+  }
+  void Extr(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            unsigned lsb) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    extr(rd, rn, rm, lsb);
+  }
+  void Fabs(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fabs(fd, fn);
+  }
+  void Fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fadd(fd, fn, fm);
+  }
+  void Fccmp(const FPRegister& fn,
+             const FPRegister& fm,
+             StatusFlags nzcv,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT((cond != al) && (cond != nv));
+    fccmp(fn, fm, nzcv, cond);
+  }
+  void Fcmp(const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fcmp(fn, fm);
+  }
+  void Fcmp(const FPRegister& fn, double value) {
+    ASSERT(allow_macro_instructions_);
+    if (value != 0.0) {
+      FPRegister tmp = AppropriateTempFor(fn);
+      Fmov(tmp, value);
+      fcmp(fn, tmp);
+    } else {
+      fcmp(fn, value);
+    }
+  }
+  void Fcsel(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT((cond != al) && (cond != nv));
+    fcsel(fd, fn, fm, cond);
+  }
+  void Fcvt(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fcvt(fd, fn);
+  }
+  void Fcvtms(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtms(rd, fn);
+  }
+  void Fcvtmu(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtmu(rd, fn);
+  }
+  void Fcvtns(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtns(rd, fn);
+  }
+  void Fcvtnu(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtnu(rd, fn);
+  }
+  void Fcvtzs(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtzs(rd, fn);
+  }
+  void Fcvtzu(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtzu(rd, fn);
+  }
+  void Fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fdiv(fd, fn, fm);
+  }
+  void Fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fmax(fd, fn, fm);
+  }
+  void Fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fmin(fd, fn, fm);
+  }
+  void Fmov(FPRegister fd, FPRegister fn) {
+    ASSERT(allow_macro_instructions_);
+    // Only emit an instruction if fd and fn are different, and they are both D
+    // registers. fmov(s0, s0) is not a no-op because it clears the top word of
+    // d0. Technically, fmov(d0, d0) is not a no-op either because it clears
+    // the top of q0, but FPRegister does not currently support Q registers.
+    if (!fd.Is(fn) || !fd.Is64Bits()) {
+      fmov(fd, fn);
+    }
+  }
+  void Fmov(FPRegister fd, Register rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rn.IsZero());
+    fmov(fd, rn);
+  }
+  void Fmov(FPRegister fd, double imm) {
+    ASSERT(allow_macro_instructions_);
+    fmov(fd, imm);
+  }
+  void Fmov(Register rd, FPRegister fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fmov(rd, fn);
+  }
+  void Fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fmul(fd, fn, fm);
+  }
+  void Fmsub(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             const FPRegister& fa) {
+    ASSERT(allow_macro_instructions_);
+    fmsub(fd, fn, fm, fa);
+  }
+  void Fneg(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fneg(fd, fn);
+  }
+  void Frintn(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    frintn(fd, fn);
+  }
+  void Frintz(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    frintz(fd, fn);
+  }
+  void Fsqrt(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fsqrt(fd, fn);
+  }
+  void Fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fsub(fd, fn, fm);
+  }
+  void Hint(SystemHint code) {
+    ASSERT(allow_macro_instructions_);
+    hint(code);
+  }
+  void Hlt(int code) {
+    ASSERT(allow_macro_instructions_);
+    hlt(code);
+  }
+  void Ldnp(const CPURegister& rt,
+            const CPURegister& rt2,
+            const MemOperand& src) {
+    ASSERT(allow_macro_instructions_);
+    ldnp(rt, rt2, src);
+  }
+  void Ldp(const CPURegister& rt,
+           const CPURegister& rt2,
+           const MemOperand& src) {
+    ASSERT(allow_macro_instructions_);
+    ldp(rt, rt2, src);
+  }
+  void Ldpsw(const Register& rt, const Register& rt2, const MemOperand& src) {
+    ASSERT(allow_macro_instructions_);
+    ldpsw(rt, rt2, src);
+  }
+  void Ldr(const FPRegister& ft, double imm) {
+    ASSERT(allow_macro_instructions_);
+    ldr(ft, imm);
+  }
+  void Ldr(const Register& rt, uint64_t imm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    ldr(rt, imm);
+  }
+  void Lsl(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    lsl(rd, rn, shift);
+  }
+  void Lsl(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    lslv(rd, rn, rm);
+  }
+  void Lsr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    lsr(rd, rn, shift);
+  }
+  void Lsr(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    lsrv(rd, rn, rm);
+  }
+  void Madd(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    madd(rd, rn, rm, ra);
+  }
+  void Mneg(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    mneg(rd, rn, rm);
+  }
+  void Mov(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    mov(rd, rn);
+  }
+  void Mrs(const Register& rt, SystemRegister sysreg) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    mrs(rt, sysreg);
+  }
+  void Msr(SystemRegister sysreg, const Register& rt) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    msr(sysreg, rt);
+  }
+  void Msub(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    msub(rd, rn, rm, ra);
+  }
+  void Mul(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    mul(rd, rn, rm);
+  }
+  void Nop() {
+    ASSERT(allow_macro_instructions_);
+    nop();
+  }
+  void Rbit(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rbit(rd, rn);
+  }
+  void Ret(const Register& xn = lr) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xn.IsZero());
+    ret(xn);
+  }
+  void Rev(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rev(rd, rn);
+  }
+  void Rev16(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rev16(rd, rn);
+  }
+  void Rev32(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rev32(rd, rn);
+  }
+  void Ror(const Register& rd, const Register& rs, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rs.IsZero());
+    ror(rd, rs, shift);
+  }
+  void Ror(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    rorv(rd, rn, rm);
+  }
+  void Sbfiz(const Register& rd,
+             const Register& rn,
+             unsigned lsb,
+             unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sbfiz(rd, rn, lsb, width);
+  }
+  void Sbfx(const Register& rd,
+            const Register& rn,
+            unsigned lsb,
+            unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sbfx(rd, rn, lsb, width);
+  }
+  void Scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rn.IsZero());
+    scvtf(fd, rn, fbits);
+  }
+  void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    sdiv(rd, rn, rm);
+  }
+  void Smaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    smaddl(rd, rn, rm, ra);
+  }
+  void Smsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    smsubl(rd, rn, rm, ra);
+  }
+  void Smull(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    smull(rd, rn, rm);
+  }
+  void Smulh(const Register& xd, const Register& xn, const Register& xm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xd.IsZero());
+    ASSERT(!xn.IsZero());
+    ASSERT(!xm.IsZero());
+    smulh(xd, xn, xm);
+  }
+  void Stnp(const CPURegister& rt,
+            const CPURegister& rt2,
+            const MemOperand& dst) {
+    ASSERT(allow_macro_instructions_);
+    stnp(rt, rt2, dst);
+  }
+  void Stp(const CPURegister& rt,
+           const CPURegister& rt2,
+           const MemOperand& dst) {
+    ASSERT(allow_macro_instructions_);
+    stp(rt, rt2, dst);
+  }
+  void Sxtb(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sxtb(rd, rn);
+  }
+  void Sxth(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sxth(rd, rn);
+  }
+  void Sxtw(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sxtw(rd, rn);
+  }
+  void Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    tbnz(rt, bit_pos, label);
+  }
+  void Tbz(const Register& rt, unsigned bit_pos, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    tbz(rt, bit_pos, label);
+  }
+  void Ubfiz(const Register& rd,
+             const Register& rn,
+             unsigned lsb,
+             unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ubfiz(rd, rn, lsb, width);
+  }
+  void Ubfx(const Register& rd,
+            const Register& rn,
+            unsigned lsb,
+            unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ubfx(rd, rn, lsb, width);
+  }
+  void Ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rn.IsZero());
+    ucvtf(fd, rn, fbits);
+  }
+  void Udiv(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    udiv(rd, rn, rm);
+  }
+  void Umaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    umaddl(rd, rn, rm, ra);
+  }
+  void Umsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    umsubl(rd, rn, rm, ra);
+  }
+  void Unreachable() {
+    ASSERT(allow_macro_instructions_);
+#ifdef USE_SIMULATOR
+    hlt(kUnreachableOpcode);
+#else
+    // Branch to 0 to generate a segfault.
+    // lr - kInstructionSize is the address of the offending instruction.
+    blr(xzr);
+#endif
+  }
+  void Uxtb(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    uxtb(rd, rn);
+  }
+  void Uxth(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    uxth(rd, rn);
+  }
+  void Uxtw(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    uxtw(rd, rn);
+  }
+
+  // Push the system stack pointer (sp) down to allow the same to be done to
+  // the current stack pointer (according to StackPointer()). This must be
+  // called _before_ accessing the memory.
+  //
+  // This is necessary when pushing or otherwise adding things to the stack, to
+  // satisfy the AAPCS64 constraint that the memory below the system stack
+  // pointer is not accessed.
+  //
+  // This method asserts that StackPointer() is not sp, since the call does
+  // not make sense in that context.
+  //
+  // TODO: This method can only accept values of 'space' that can be encoded in
+  // one instruction. Refer to the implementation for details.
+  void BumpSystemStackPointer(const Operand& space);
+
+#if DEBUG
+  void SetAllowMacroInstructions(bool value) {
+    allow_macro_instructions_ = value;
+  }
+
+  bool AllowMacroInstructions() const {
+    return allow_macro_instructions_;
+  }
+#endif
+
+  // Set the current stack pointer, but don't generate any code.
+  // Note that this does not directly affect LastStackPointer().
+  void SetStackPointer(const Register& stack_pointer) {
+    ASSERT(!AreAliased(stack_pointer, Tmp0(), Tmp1()));
+    sp_ = stack_pointer;
+  }
+
+  // Return the current stack pointer, as set by SetStackPointer.
+  const Register& StackPointer() const {
+    return sp_;
+  }
+
+  // Set the registers used internally by the MacroAssembler as scratch
+  // registers. These registers are used to implement behaviours which are not
+  // directly supported by A64, and where an intermediate result is required.
+  //
+  // Both tmp0 and tmp1 may be set to any X register except for xzr, sp,
+  // and StackPointer(). Also, they must not be the same register (though they
+  // may both be NoReg).
+  //
+  // It is valid to set either or both of these registers to NoReg if you don't
+  // want the MacroAssembler to use any scratch registers. In a debug build, the
+  // Assembler will assert that any registers it uses are valid. Be aware that
+  // this check is not present in release builds. If this is a problem, use the
+  // Assembler directly.
+  void SetScratchRegisters(const Register& tmp0, const Register& tmp1) {
+    ASSERT(!AreAliased(xzr, sp, tmp0, tmp1));
+    ASSERT(!AreAliased(StackPointer(), tmp0, tmp1));
+    tmp0_ = tmp0;
+    tmp1_ = tmp1;
+  }
+
+  const Register& Tmp0() const {
+    return tmp0_;
+  }
+
+  const Register& Tmp1() const {
+    return tmp1_;
+  }
+
+  void SetFPScratchRegister(const FPRegister& fptmp0) {
+    fptmp0_ = fptmp0;
+  }
+
+  const FPRegister& FPTmp0() const {
+    return fptmp0_;
+  }
+
+  const Register AppropriateTempFor(
+      const Register& target,
+      const CPURegister& forbidden = NoCPUReg) const {
+    Register candidate = forbidden.Is(Tmp0()) ? Tmp1() : Tmp0();
+    ASSERT(!candidate.Is(target));
+    return Register(candidate.code(), target.size());
+  }
+
+  const FPRegister AppropriateTempFor(
+      const FPRegister& target,
+      const CPURegister& forbidden = NoCPUReg) const {
+    USE(forbidden);
+    FPRegister candidate = FPTmp0();
+    ASSERT(!candidate.Is(forbidden));
+    ASSERT(!candidate.Is(target));
+    return FPRegister(candidate.code(), target.size());
+  }
+
+  // Like printf, but print at run-time from generated code.
+  //
+  // The caller must ensure that arguments for floating-point placeholders
+  // (such as %e, %f or %g) are FPRegisters, and that arguments for integer
+  // placeholders are Registers.
+  //
+  // A maximum of four arguments may be given to any single Printf call. The
+  // arguments must be of the same type, but they do not need to have the same
+  // size.
+  //
+  // The following registers cannot be printed:
+  //    Tmp0(), Tmp1(), StackPointer(), sp.
+  //
+  // This function automatically preserves caller-saved registers so that
+  // calling code can use Printf at any point without having to worry about
+  // corruption. The preservation mechanism generates a lot of code. If this is
+  // a problem, preserve the important registers manually and then call
+  // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
+  // implicitly preserved.
+  //
+  // This function assumes (and asserts) that the current stack pointer is
+  // callee-saved, not caller-saved. This is most likely the case anyway, as a
+  // caller-saved stack pointer doesn't make a lot of sense.
+  void Printf(const char * format,
+              const CPURegister& arg0 = NoCPUReg,
+              const CPURegister& arg1 = NoCPUReg,
+              const CPURegister& arg2 = NoCPUReg,
+              const CPURegister& arg3 = NoCPUReg);
+
+  // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
+  //
+  // The return code from the system printf call will be returned in x0.
+  void PrintfNoPreserve(const char * format,
+                        const CPURegister& arg0 = NoCPUReg,
+                        const CPURegister& arg1 = NoCPUReg,
+                        const CPURegister& arg2 = NoCPUReg,
+                        const CPURegister& arg3 = NoCPUReg);
+
+  // Trace control when running the debug simulator.
+  //
+  // For example:
+  //
+  // __ Trace(LOG_REGS, TRACE_ENABLE);
+  // Will add registers to the trace if it wasn't already the case.
+  //
+  // __ Trace(LOG_DISASM, TRACE_DISABLE);
+  // Will stop logging disassembly. It has no effect if the disassembly wasn't
+  // already being logged.
+  void Trace(TraceParameters parameters, TraceCommand command);
+
+  // Log the requested data independently of what is being traced.
+  //
+  // For example:
+  //
+  // __ Log(LOG_FLAGS)
+  // Will output the flags.
+  void Log(TraceParameters parameters);
+
+  // Enable or disable instrumentation when an Instrument visitor is attached to
+  // the simulator.
+  void EnableInstrumentation();
+  void DisableInstrumentation();
+
+  // Add a marker to the instrumentation data produced by an Instrument visitor.
+  // The name is a two character string that will be attached to the marker in
+  // the output data.
+  void AnnotateInstrumentation(const char* marker_name);
+
+ private:
+  // The actual Push and Pop implementations. These don't generate any code
+  // other than that required for the push or pop. This allows
+  // (Push|Pop)CPURegList to bundle together setup code for a large block of
+  // registers.
+  //
+  // Note that size is per register, and is specified in bytes.
+  void PushHelper(int count, int size,
+                  const CPURegister& src0, const CPURegister& src1,
+                  const CPURegister& src2, const CPURegister& src3);
+  void PopHelper(int count, int size,
+                 const CPURegister& dst0, const CPURegister& dst1,
+                 const CPURegister& dst2, const CPURegister& dst3);
+
+  // Perform necessary maintenance operations before a push or pop.
+  //
+  // Note that size is per register, and is specified in bytes.
+  void PrepareForPush(int count, int size);
+  void PrepareForPop(int count, int size);
+
+#if DEBUG
+  // Tell whether any of the macro instruction can be used. When false the
+  // MacroAssembler will assert if a method which can emit a variable number
+  // of instructions is called.
+  bool allow_macro_instructions_;
+#endif
+
+  // The register to use as a stack pointer for stack operations.
+  Register sp_;
+
+  // Scratch registers used internally by the MacroAssembler.
+  Register tmp0_;
+  Register tmp1_;
+  FPRegister fptmp0_;
+};
+
+
+// Use this scope when you need a one-to-one mapping between methods and
+// instructions. This scope prevents the MacroAssembler from being called and
+// literal pools from being emitted. It also asserts the number of instructions
+// emitted is what you specified when creating the scope.
+class InstructionAccurateScope {
+ public:
+  explicit InstructionAccurateScope(MacroAssembler* masm)
+      : masm_(masm), size_(0) {
+    masm_->BlockLiteralPool();
+#ifdef DEBUG
+    old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
+    masm_->SetAllowMacroInstructions(false);
+#endif
+  }
+
+  InstructionAccurateScope(MacroAssembler* masm, int count)
+      : masm_(masm), size_(count * kInstructionSize) {
+    masm_->BlockLiteralPool();
+#ifdef DEBUG
+    masm_->bind(&start_);
+    old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
+    masm_->SetAllowMacroInstructions(false);
+#endif
+  }
+
+  ~InstructionAccurateScope() {
+    masm_->ReleaseLiteralPool();
+#ifdef DEBUG
+    if (start_.IsBound()) {
+      ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_);
+    }
+    masm_->SetAllowMacroInstructions(old_allow_macro_instructions_);
+#endif
+  }
+
+ private:
+  MacroAssembler* masm_;
+  uint64_t size_;
+#ifdef DEBUG
+  Label start_;
+  bool old_allow_macro_instructions_;
+#endif
+};
+
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_MACRO_ASSEMBLER_A64_H_
diff --git a/disas/libvixl/src/a64/simulator-a64.cc b/disas/libvixl/src/a64/simulator-a64.cc
new file mode 100644
index 0000000..f08e0ed
--- /dev/null
+++ b/disas/libvixl/src/a64/simulator-a64.cc
@@ -0,0 +1,2077 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <math.h>
+#include "a64/simulator-a64.h"
+
+namespace vixl {
+
+const Instruction* Simulator::kEndOfSimAddress = NULL;
+
+void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
+  int width = msb - lsb + 1;
+  ASSERT(is_uintn(width, bits) || is_intn(width, bits));
+
+  bits <<= lsb;
+  uint32_t mask = ((1 << width) - 1) << lsb;
+  ASSERT((mask & write_ignore_mask_) == 0);
+
+  value_ = (value_ & ~mask) | (bits & mask);
+}
+
+
+SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
+  switch (id) {
+    case NZCV:
+      return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
+    case FPCR:
+      return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
+    default:
+      UNREACHABLE();
+      return SimSystemRegister();
+  }
+}
+
+
+Simulator::Simulator(Decoder* decoder, FILE* stream) {
+  // Ensure shift operations act as the simulator expects.
+  ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
+  ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7FFFFFFF);
+
+  // Setup the decoder.
+  decoder_ = decoder;
+  decoder_->AppendVisitor(this);
+
+  ResetState();
+
+  // Allocate and setup the simulator stack.
+  stack_ = reinterpret_cast<byte*>(malloc(stack_size_));
+  stack_limit_ = stack_ + stack_protection_size_;
+  byte* tos = stack_ + stack_size_ - stack_protection_size_;
+  // The stack pointer must be 16 bytes aligned.
+  set_sp(reinterpret_cast<int64_t>(tos) & ~0xfUL);
+
+  stream_ = stream;
+  print_disasm_ = new PrintDisassembler(stream_);
+  coloured_trace_ = false;
+  disasm_trace_ = false;
+
+  // Set the sample period to 10, as the VIXL examples and tests are short.
+  instrumentation_ = new Instrument("vixl_stats.csv", 10);
+}
+
+
+void Simulator::ResetState() {
+  // Reset the system registers.
+  nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
+  fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
+
+  // Reset registers to 0.
+  pc_ = NULL;
+  pc_modified_ = false;
+  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
+    set_xreg(i, 0xbadbeef);
+  }
+  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
+    // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
+    set_dreg_bits(i, 0x7ff000007f800001UL);
+  }
+  // Returning to address 0 exits the Simulator.
+  set_lr(reinterpret_cast<int64_t>(kEndOfSimAddress));
+}
+
+
+Simulator::~Simulator() {
+  free(stack_);
+  // The decoder may outlive the simulator.
+  decoder_->RemoveVisitor(print_disasm_);
+  delete print_disasm_;
+
+  decoder_->RemoveVisitor(instrumentation_);
+  delete instrumentation_;
+}
+
+
+void Simulator::Run() {
+  while (pc_ != kEndOfSimAddress) {
+    ExecuteInstruction();
+  }
+}
+
+
+void Simulator::RunFrom(Instruction* first) {
+  pc_ = first;
+  pc_modified_ = false;
+  Run();
+}
+
+
+const char* Simulator::xreg_names[] = {
+"x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
+"x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
+"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+"x24", "x25", "x26", "x27", "x28", "x29", "lr",  "xzr", "sp"};
+
+
+const char* Simulator::wreg_names[] = {
+"w0",  "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",
+"w8",  "w9",  "w10", "w11", "w12", "w13", "w14", "w15",
+"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
+"w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr", "wsp"};
+
+const char* Simulator::sreg_names[] = {
+"s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
+"s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
+"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
+
+const char* Simulator::dreg_names[] = {
+"d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
+"d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
+"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
+
+const char* Simulator::vreg_names[] = {
+"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"};
+
+
+
+const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
+  ASSERT(code < kNumberOfRegisters);
+  // If the code represents the stack pointer, index the name after zr.
+  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
+    code = kZeroRegCode + 1;
+  }
+  return wreg_names[code];
+}
+
+
+const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
+  ASSERT(code < kNumberOfRegisters);
+  // If the code represents the stack pointer, index the name after zr.
+  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
+    code = kZeroRegCode + 1;
+  }
+  return xreg_names[code];
+}
+
+
+const char* Simulator::SRegNameForCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return sreg_names[code];
+}
+
+
+const char* Simulator::DRegNameForCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return dreg_names[code];
+}
+
+
+const char* Simulator::VRegNameForCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return vreg_names[code];
+}
+
+
+// Helpers ---------------------------------------------------------------------
+int64_t Simulator::AddWithCarry(unsigned reg_size,
+                                bool set_flags,
+                                int64_t src1,
+                                int64_t src2,
+                                int64_t carry_in) {
+  ASSERT((carry_in == 0) || (carry_in == 1));
+  ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
+
+  uint64_t u1, u2;
+  int64_t result;
+  int64_t signed_sum = src1 + src2 + carry_in;
+
+  uint32_t N, Z, C, V;
+
+  if (reg_size == kWRegSize) {
+    u1 = static_cast<uint64_t>(src1) & kWRegMask;
+    u2 = static_cast<uint64_t>(src2) & kWRegMask;
+
+    result = signed_sum & kWRegMask;
+    // Compute the C flag by comparing the sum to the max unsigned integer.
+    C = ((kWMaxUInt - u1) < (u2 + carry_in)) ||
+        ((kWMaxUInt - u1 - carry_in) < u2);
+    // Overflow iff the sign bit is the same for the two inputs and different
+    // for the result.
+    int64_t s_src1 = src1 << (kXRegSize - kWRegSize);
+    int64_t s_src2 = src2 << (kXRegSize - kWRegSize);
+    int64_t s_result = result << (kXRegSize - kWRegSize);
+    V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0);
+
+  } else {
+    u1 = static_cast<uint64_t>(src1);
+    u2 = static_cast<uint64_t>(src2);
+
+    result = signed_sum;
+    // Compute the C flag by comparing the sum to the max unsigned integer.
+    C = ((kXMaxUInt - u1) < (u2 + carry_in)) ||
+        ((kXMaxUInt - u1 - carry_in) < u2);
+    // Overflow iff the sign bit is the same for the two inputs and different
+    // for the result.
+    V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
+  }
+
+  N = CalcNFlag(result, reg_size);
+  Z = CalcZFlag(result);
+
+  if (set_flags) {
+    nzcv().SetN(N);
+    nzcv().SetZ(Z);
+    nzcv().SetC(C);
+    nzcv().SetV(V);
+  }
+  return result;
+}
+
+
+int64_t Simulator::ShiftOperand(unsigned reg_size,
+                                int64_t value,
+                                Shift shift_type,
+                                unsigned amount) {
+  if (amount == 0) {
+    return value;
+  }
+  int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
+  switch (shift_type) {
+    case LSL:
+      return (value << amount) & mask;
+    case LSR:
+      return static_cast<uint64_t>(value) >> amount;
+    case ASR: {
+      // Shift used to restore the sign.
+      unsigned s_shift = kXRegSize - reg_size;
+      // Value with its sign restored.
+      int64_t s_value = (value << s_shift) >> s_shift;
+      return (s_value >> amount) & mask;
+    }
+    case ROR: {
+      if (reg_size == kWRegSize) {
+        value &= kWRegMask;
+      }
+      return (static_cast<uint64_t>(value) >> amount) |
+             ((value & ((1L << amount) - 1L)) << (reg_size - amount));
+    }
+    default:
+      UNIMPLEMENTED();
+      return 0;
+  }
+}
+
+
+int64_t Simulator::ExtendValue(unsigned reg_size,
+                               int64_t value,
+                               Extend extend_type,
+                               unsigned left_shift) {
+  switch (extend_type) {
+    case UXTB:
+      value &= kByteMask;
+      break;
+    case UXTH:
+      value &= kHalfWordMask;
+      break;
+    case UXTW:
+      value &= kWordMask;
+      break;
+    case SXTB:
+      value = (value << 56) >> 56;
+      break;
+    case SXTH:
+      value = (value << 48) >> 48;
+      break;
+    case SXTW:
+      value = (value << 32) >> 32;
+      break;
+    case UXTX:
+    case SXTX:
+      break;
+    default:
+      UNREACHABLE();
+  }
+  int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
+  return (value << left_shift) & mask;
+}
+
+
+void Simulator::FPCompare(double val0, double val1) {
+  AssertSupportedFPCR();
+
+  // TODO: This assumes that the C++ implementation handles comparisons in the
+  // way that we expect (as per AssertSupportedFPCR()).
+  if ((isnan(val0) != 0) || (isnan(val1) != 0)) {
+    nzcv().SetRawValue(FPUnorderedFlag);
+  } else if (val0 < val1) {
+    nzcv().SetRawValue(FPLessThanFlag);
+  } else if (val0 > val1) {
+    nzcv().SetRawValue(FPGreaterThanFlag);
+  } else if (val0 == val1) {
+    nzcv().SetRawValue(FPEqualFlag);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+
+void Simulator::PrintSystemRegisters(bool print_all) {
+  static bool first_run = true;
+
+  // Define some colour codes to use for the register dump.
+  // TODO: Find a more elegant way of defining these.
+  char const * const clr_normal     = (coloured_trace_) ? ("\033[m") : ("");
+  char const * const clr_flag_name  = (coloured_trace_) ? ("\033[1;30m") : ("");
+  char const * const clr_flag_value = (coloured_trace_) ? ("\033[1;37m") : ("");
+
+  static SimSystemRegister last_nzcv;
+  if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) {
+    fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
+            clr_flag_name,
+            clr_flag_value,
+            N(), Z(), C(), V(),
+            clr_normal);
+  }
+  last_nzcv = nzcv();
+
+  static SimSystemRegister last_fpcr;
+  if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) {
+    static const char * rmode[] = {
+      "0b00 (Round to Nearest)",
+      "0b01 (Round towards Plus Infinity)",
+      "0b10 (Round towards Minus Infinity)",
+      "0b11 (Round towards Zero)"
+    };
+    ASSERT(fpcr().RMode() <= (sizeof(rmode) / sizeof(rmode[0])));
+    fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
+            clr_flag_name,
+            clr_flag_value,
+            fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
+            clr_normal);
+  }
+  last_fpcr = fpcr();
+
+  first_run = false;
+}
+
+
+void Simulator::PrintRegisters(bool print_all_regs) {
+  static bool first_run = true;
+  static int64_t last_regs[kNumberOfRegisters];
+
+  // Define some colour codes to use for the register dump.
+  // TODO: Find a more elegant way of defining these.
+  char const * const clr_normal    = (coloured_trace_) ? ("\033[m") : ("");
+  char const * const clr_reg_name  = (coloured_trace_) ? ("\033[1;34m") : ("");
+  char const * const clr_reg_value = (coloured_trace_) ? ("\033[1;36m") : ("");
+
+  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
+    if (print_all_regs || first_run || (last_regs[i] != registers_[i].x)) {
+      fprintf(stream_,
+              "# %s%4s:%s 0x%016" PRIx64 "%s\n",
+              clr_reg_name,
+              XRegNameForCode(i, Reg31IsStackPointer),
+              clr_reg_value,
+              registers_[i].x,
+              clr_normal);
+    }
+    // Cache the new register value so the next run can detect any changes.
+    last_regs[i] = registers_[i].x;
+  }
+  first_run = false;
+}
+
+
+void Simulator::PrintFPRegisters(bool print_all_regs) {
+  static bool first_run = true;
+  static uint64_t last_regs[kNumberOfFPRegisters];
+
+  // Define some colour codes to use for the register dump.
+  // TODO: Find a more elegant way of defining these.
+  char const * const clr_normal    = (coloured_trace_) ? ("\033[m") : ("");
+  char const * const clr_reg_name  = (coloured_trace_) ? ("\033[1;33m") : ("");
+  char const * const clr_reg_value = (coloured_trace_) ? ("\033[1;35m") : ("");
+
+  // Print as many rows of registers as necessary, keeping each individual
+  // register in the same column each time (to make it easy to visually scan
+  // for changes).
+  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
+    if (print_all_regs || first_run ||
+        (last_regs[i] != double_to_rawbits(fpregisters_[i].d))) {
+      fprintf(stream_,
+              "# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
+              clr_reg_name,
+              VRegNameForCode(i),
+              clr_reg_value,
+              double_to_rawbits(fpregisters_[i].d),
+              clr_normal,
+              clr_reg_name,
+              DRegNameForCode(i),
+              clr_reg_value,
+              fpregisters_[i].d,
+              clr_reg_name,
+              SRegNameForCode(i),
+              clr_reg_value,
+              fpregisters_[i].s,
+              clr_normal);
+    }
+    // Cache the new register value so the next run can detect any changes.
+    last_regs[i] = double_to_rawbits(fpregisters_[i].d);
+  }
+  first_run = false;
+}
+
+
+void Simulator::PrintProcessorState() {
+  PrintSystemRegisters();
+  PrintRegisters();
+  PrintFPRegisters();
+}
+
+
+// Visitors---------------------------------------------------------------------
+
+void Simulator::VisitUnimplemented(Instruction* instr) {
+  printf("Unimplemented instruction at 0x%p: 0x%08" PRIx32 "\n",
+         reinterpret_cast<void*>(instr), instr->InstructionBits());
+  UNIMPLEMENTED();
+}
+
+
+void Simulator::VisitUnallocated(Instruction* instr) {
+  printf("Unallocated instruction at 0x%p: 0x%08" PRIx32 "\n",
+         reinterpret_cast<void*>(instr), instr->InstructionBits());
+  UNIMPLEMENTED();
+}
+
+
+void Simulator::VisitPCRelAddressing(Instruction* instr) {
+  switch (instr->Mask(PCRelAddressingMask)) {
+    case ADR:
+      set_reg(kXRegSize,
+              instr->Rd(),
+              reinterpret_cast<int64_t>(instr->ImmPCOffsetTarget()));
+      break;
+    case ADRP:  // Not implemented in the assembler.
+      UNIMPLEMENTED();
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitUnconditionalBranch(Instruction* instr) {
+  switch (instr->Mask(UnconditionalBranchMask)) {
+    case BL:
+      set_lr(reinterpret_cast<int64_t>(instr->NextInstruction()));
+      // Fall through.
+    case B:
+      set_pc(instr->ImmPCOffsetTarget());
+      break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitConditionalBranch(Instruction* instr) {
+  ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
+  if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
+    set_pc(instr->ImmPCOffsetTarget());
+  }
+}
+
+
+void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
+  Instruction* target = Instruction::Cast(xreg(instr->Rn()));
+
+  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
+    case BLR:
+      set_lr(reinterpret_cast<int64_t>(instr->NextInstruction()));
+      // Fall through.
+    case BR:
+    case RET: set_pc(target); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitTestBranch(Instruction* instr) {
+  unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
+                     instr->ImmTestBranchBit40();
+  bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
+  switch (instr->Mask(TestBranchMask)) {
+    case TBZ: break;
+    case TBNZ: take_branch = !take_branch; break;
+    default: UNIMPLEMENTED();
+  }
+  if (take_branch) {
+    set_pc(instr->ImmPCOffsetTarget());
+  }
+}
+
+
+void Simulator::VisitCompareBranch(Instruction* instr) {
+  unsigned rt = instr->Rt();
+  bool take_branch = false;
+  switch (instr->Mask(CompareBranchMask)) {
+    case CBZ_w: take_branch = (wreg(rt) == 0); break;
+    case CBZ_x: take_branch = (xreg(rt) == 0); break;
+    case CBNZ_w: take_branch = (wreg(rt) != 0); break;
+    case CBNZ_x: take_branch = (xreg(rt) != 0); break;
+    default: UNIMPLEMENTED();
+  }
+  if (take_branch) {
+    set_pc(instr->ImmPCOffsetTarget());
+  }
+}
+
+
+void Simulator::AddSubHelper(Instruction* instr, int64_t op2) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  bool set_flags = instr->FlagsUpdate();
+  int64_t new_val = 0;
+  Instr operation = instr->Mask(AddSubOpMask);
+
+  switch (operation) {
+    case ADD:
+    case ADDS: {
+      new_val = AddWithCarry(reg_size,
+                             set_flags,
+                             reg(reg_size, instr->Rn(), instr->RnMode()),
+                             op2);
+      break;
+    }
+    case SUB:
+    case SUBS: {
+      new_val = AddWithCarry(reg_size,
+                             set_flags,
+                             reg(reg_size, instr->Rn(), instr->RnMode()),
+                             ~op2,
+                             1);
+      break;
+    }
+    default: UNREACHABLE();
+  }
+
+  set_reg(reg_size, instr->Rd(), new_val, instr->RdMode());
+}
+
+
+void Simulator::VisitAddSubShifted(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op2 = ShiftOperand(reg_size,
+                             reg(reg_size, instr->Rm()),
+                             static_cast<Shift>(instr->ShiftDP()),
+                             instr->ImmDPShift());
+  AddSubHelper(instr, op2);
+}
+
+
+void Simulator::VisitAddSubImmediate(Instruction* instr) {
+  int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
+  AddSubHelper(instr, op2);
+}
+
+
+void Simulator::VisitAddSubExtended(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op2 = ExtendValue(reg_size,
+                            reg(reg_size, instr->Rm()),
+                            static_cast<Extend>(instr->ExtendMode()),
+                            instr->ImmExtendShift());
+  AddSubHelper(instr, op2);
+}
+
+
+void Simulator::VisitAddSubWithCarry(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op2 = reg(reg_size, instr->Rm());
+  int64_t new_val;
+
+  if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
+    op2 = ~op2;
+  }
+
+  new_val = AddWithCarry(reg_size,
+                         instr->FlagsUpdate(),
+                         reg(reg_size, instr->Rn()),
+                         op2,
+                         C());
+
+  set_reg(reg_size, instr->Rd(), new_val);
+}
+
+
+void Simulator::VisitLogicalShifted(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  Shift shift_type = static_cast<Shift>(instr->ShiftDP());
+  unsigned shift_amount = instr->ImmDPShift();
+  int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
+                             shift_amount);
+  if (instr->Mask(NOT) == NOT) {
+    op2 = ~op2;
+  }
+  LogicalHelper(instr, op2);
+}
+
+
+void Simulator::VisitLogicalImmediate(Instruction* instr) {
+  LogicalHelper(instr, instr->ImmLogical());
+}
+
+
+void Simulator::LogicalHelper(Instruction* instr, int64_t op2) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op1 = reg(reg_size, instr->Rn());
+  int64_t result = 0;
+  bool update_flags = false;
+
+  // Switch on the logical operation, stripping out the NOT bit, as it has a
+  // different meaning for logical immediate instructions.
+  switch (instr->Mask(LogicalOpMask & ~NOT)) {
+    case ANDS: update_flags = true;  // Fall through.
+    case AND: result = op1 & op2; break;
+    case ORR: result = op1 | op2; break;
+    case EOR: result = op1 ^ op2; break;
+    default:
+      UNIMPLEMENTED();
+  }
+
+  if (update_flags) {
+    nzcv().SetN(CalcNFlag(result, reg_size));
+    nzcv().SetZ(CalcZFlag(result));
+    nzcv().SetC(0);
+    nzcv().SetV(0);
+  }
+
+  set_reg(reg_size, instr->Rd(), result, instr->RdMode());
+}
+
+
+void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
+}
+
+
+void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
+  ConditionalCompareHelper(instr, instr->ImmCondCmp());
+}
+
+
+void Simulator::ConditionalCompareHelper(Instruction* instr, int64_t op2) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op1 = reg(reg_size, instr->Rn());
+
+  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
+    // If the condition passes, set the status flags to the result of comparing
+    // the operands.
+    if (instr->Mask(ConditionalCompareMask) == CCMP) {
+      AddWithCarry(reg_size, true, op1, ~op2, 1);
+    } else {
+      ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
+      AddWithCarry(reg_size, true, op1, op2, 0);
+    }
+  } else {
+    // If the condition fails, set the status flags to the nzcv immediate.
+    nzcv().SetFlags(instr->Nzcv());
+  }
+}
+
+
+void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
+  int offset = instr->ImmLSUnsigned() << instr->SizeLS();
+  LoadStoreHelper(instr, offset, Offset);
+}
+
+
+void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
+  LoadStoreHelper(instr, instr->ImmLS(), Offset);
+}
+
+
+void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
+  LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
+}
+
+
+void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
+  LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
+}
+
+
+void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
+  Extend ext = static_cast<Extend>(instr->ExtendMode());
+  ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
+  unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
+
+  int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
+                               shift_amount);
+  LoadStoreHelper(instr, offset, Offset);
+}
+
+
+void Simulator::LoadStoreHelper(Instruction* instr,
+                                int64_t offset,
+                                AddrMode addrmode) {
+  unsigned srcdst = instr->Rt();
+  uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode);
+  int num_bytes = 1 << instr->SizeLS();
+
+  LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
+  switch (op) {
+    case LDRB_w:
+    case LDRH_w:
+    case LDR_w:
+    case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break;
+    case STRB_w:
+    case STRH_w:
+    case STR_w:
+    case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break;
+    case LDRSB_w: {
+      set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead8(address), SXTB));
+      break;
+    }
+    case LDRSB_x: {
+      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead8(address), SXTB));
+      break;
+    }
+    case LDRSH_w: {
+      set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead16(address), SXTH));
+      break;
+    }
+    case LDRSH_x: {
+      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead16(address), SXTH));
+      break;
+    }
+    case LDRSW_x: {
+      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
+      break;
+    }
+    case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break;
+    case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break;
+    case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break;
+    case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
+  LoadStorePairHelper(instr, Offset);
+}
+
+
+void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
+  LoadStorePairHelper(instr, PreIndex);
+}
+
+
+void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
+  LoadStorePairHelper(instr, PostIndex);
+}
+
+
+void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
+  LoadStorePairHelper(instr, Offset);
+}
+
+
+void Simulator::LoadStorePairHelper(Instruction* instr,
+                                    AddrMode addrmode) {
+  unsigned rt = instr->Rt();
+  unsigned rt2 = instr->Rt2();
+  int offset = instr->ImmLSPair() << instr->SizeLSPair();
+  uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode);
+
+  LoadStorePairOp op =
+    static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
+
+  // 'rt' and 'rt2' can only be aliased for stores.
+  ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
+
+  switch (op) {
+    case LDP_w: {
+      set_wreg(rt, MemoryRead32(address));
+      set_wreg(rt2, MemoryRead32(address + kWRegSizeInBytes));
+      break;
+    }
+    case LDP_s: {
+      set_sreg(rt, MemoryReadFP32(address));
+      set_sreg(rt2, MemoryReadFP32(address + kSRegSizeInBytes));
+      break;
+    }
+    case LDP_x: {
+      set_xreg(rt, MemoryRead64(address));
+      set_xreg(rt2, MemoryRead64(address + kXRegSizeInBytes));
+      break;
+    }
+    case LDP_d: {
+      set_dreg(rt, MemoryReadFP64(address));
+      set_dreg(rt2, MemoryReadFP64(address + kDRegSizeInBytes));
+      break;
+    }
+    case LDPSW_x: {
+      set_xreg(rt, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
+      set_xreg(rt2, ExtendValue(kXRegSize,
+               MemoryRead32(address + kWRegSizeInBytes), SXTW));
+      break;
+    }
+    case STP_w: {
+      MemoryWrite32(address, wreg(rt));
+      MemoryWrite32(address + kWRegSizeInBytes, wreg(rt2));
+      break;
+    }
+    case STP_s: {
+      MemoryWriteFP32(address, sreg(rt));
+      MemoryWriteFP32(address + kSRegSizeInBytes, sreg(rt2));
+      break;
+    }
+    case STP_x: {
+      MemoryWrite64(address, xreg(rt));
+      MemoryWrite64(address + kXRegSizeInBytes, xreg(rt2));
+      break;
+    }
+    case STP_d: {
+      MemoryWriteFP64(address, dreg(rt));
+      MemoryWriteFP64(address + kDRegSizeInBytes, dreg(rt2));
+      break;
+    }
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitLoadLiteral(Instruction* instr) {
+  uint8_t* address = instr->LiteralAddress();
+  unsigned rt = instr->Rt();
+
+  switch (instr->Mask(LoadLiteralMask)) {
+    case LDR_w_lit: set_wreg(rt, MemoryRead32(address));  break;
+    case LDR_x_lit: set_xreg(rt, MemoryRead64(address));  break;
+    case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address));  break;
+    case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address));  break;
+    default: UNREACHABLE();
+  }
+}
+
+
+uint8_t* Simulator::AddressModeHelper(unsigned addr_reg,
+                                      int64_t offset,
+                                      AddrMode addrmode) {
+  uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
+  ASSERT((sizeof(uintptr_t) == kXRegSizeInBytes) ||
+         (address < 0x100000000UL));
+  if ((addr_reg == 31) && ((address % 16) != 0)) {
+    // When the base register is SP the stack pointer is required to be
+    // quadword aligned prior to the address calculation and write-backs.
+    // Misalignment will cause a stack alignment fault.
+    ALIGNMENT_EXCEPTION();
+  }
+  if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
+    ASSERT(offset != 0);
+    set_xreg(addr_reg, address + offset, Reg31IsStackPointer);
+  }
+
+  if ((addrmode == Offset) || (addrmode == PreIndex)) {
+    address += offset;
+  }
+
+  return reinterpret_cast<uint8_t*>(address);
+}
+
+
+uint64_t Simulator::MemoryRead(const uint8_t* address, unsigned num_bytes) {
+  ASSERT(address != NULL);
+  ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
+  uint64_t read = 0;
+  memcpy(&read, address, num_bytes);
+  return read;
+}
+
+
+uint8_t Simulator::MemoryRead8(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint8_t));
+}
+
+
+uint16_t Simulator::MemoryRead16(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint16_t));
+}
+
+
+uint32_t Simulator::MemoryRead32(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint32_t));
+}
+
+
+float Simulator::MemoryReadFP32(uint8_t* address) {
+  return rawbits_to_float(MemoryRead32(address));
+}
+
+
+uint64_t Simulator::MemoryRead64(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint64_t));
+}
+
+
+double Simulator::MemoryReadFP64(uint8_t* address) {
+  return rawbits_to_double(MemoryRead64(address));
+}
+
+
+void Simulator::MemoryWrite(uint8_t* address,
+                            uint64_t value,
+                            unsigned num_bytes) {
+  ASSERT(address != NULL);
+  ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
+  memcpy(address, &value, num_bytes);
+}
+
+
+void Simulator::MemoryWrite32(uint8_t* address, uint32_t value) {
+  MemoryWrite(address, value, sizeof(uint32_t));
+}
+
+
+void Simulator::MemoryWriteFP32(uint8_t* address, float value) {
+  MemoryWrite32(address, float_to_rawbits(value));
+}
+
+
+void Simulator::MemoryWrite64(uint8_t* address, uint64_t value) {
+  MemoryWrite(address, value, sizeof(uint64_t));
+}
+
+
+void Simulator::MemoryWriteFP64(uint8_t* address, double value) {
+  MemoryWrite64(address, double_to_rawbits(value));
+}
+
+
+void Simulator::VisitMoveWideImmediate(Instruction* instr) {
+  MoveWideImmediateOp mov_op =
+    static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
+  int64_t new_xn_val = 0;
+
+  bool is_64_bits = instr->SixtyFourBits() == 1;
+  // Shift is limited for W operations.
+  ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
+
+  // Get the shifted immediate.
+  int64_t shift = instr->ShiftMoveWide() * 16;
+  int64_t shifted_imm16 = instr->ImmMoveWide() << shift;
+
+  // Compute the new value.
+  switch (mov_op) {
+    case MOVN_w:
+    case MOVN_x: {
+        new_xn_val = ~shifted_imm16;
+        if (!is_64_bits) new_xn_val &= kWRegMask;
+      break;
+    }
+    case MOVK_w:
+    case MOVK_x: {
+        unsigned reg_code = instr->Rd();
+        int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
+                                         : wreg(reg_code);
+        new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
+      break;
+    }
+    case MOVZ_w:
+    case MOVZ_x: {
+        new_xn_val = shifted_imm16;
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  // Update the destination register.
+  set_xreg(instr->Rd(), new_xn_val);
+}
+
+
+void Simulator::VisitConditionalSelect(Instruction* instr) {
+  uint64_t new_val = xreg(instr->Rn());
+
+  if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
+    new_val = xreg(instr->Rm());
+    switch (instr->Mask(ConditionalSelectMask)) {
+      case CSEL_w:
+      case CSEL_x: break;
+      case CSINC_w:
+      case CSINC_x: new_val++; break;
+      case CSINV_w:
+      case CSINV_x: new_val = ~new_val; break;
+      case CSNEG_w:
+      case CSNEG_x: new_val = -new_val; break;
+      default: UNIMPLEMENTED();
+    }
+  }
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  set_reg(reg_size, instr->Rd(), new_val);
+}
+
+
+void Simulator::VisitDataProcessing1Source(Instruction* instr) {
+  unsigned dst = instr->Rd();
+  unsigned src = instr->Rn();
+
+  switch (instr->Mask(DataProcessing1SourceMask)) {
+    case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSize)); break;
+    case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSize)); break;
+    case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break;
+    case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break;
+    case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break;
+    case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break;
+    case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break;
+    case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSize)); break;
+    case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSize)); break;
+    case CLS_w: {
+      set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSize));
+      break;
+    }
+    case CLS_x: {
+      set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSize));
+      break;
+    }
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+uint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) {
+  ASSERT((num_bits == kWRegSize) || (num_bits == kXRegSize));
+  uint64_t result = 0;
+  for (unsigned i = 0; i < num_bits; i++) {
+    result = (result << 1) | (value & 1);
+    value >>= 1;
+  }
+  return result;
+}
+
+
+uint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) {
+  // Split the 64-bit value into an 8-bit array, where b[0] is the least
+  // significant byte, and b[7] is the most significant.
+  uint8_t bytes[8];
+  uint64_t mask = 0xff00000000000000UL;
+  for (int i = 7; i >= 0; i--) {
+    bytes[i] = (value & mask) >> (i * 8);
+    mask >>= 8;
+  }
+
+  // Permutation tables for REV instructions.
+  //  permute_table[Reverse16] is used by REV16_x, REV16_w
+  //  permute_table[Reverse32] is used by REV32_x, REV_w
+  //  permute_table[Reverse64] is used by REV_x
+  ASSERT((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2));
+  static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1},
+                                               {4, 5, 6, 7, 0, 1, 2, 3},
+                                               {0, 1, 2, 3, 4, 5, 6, 7} };
+  uint64_t result = 0;
+  for (int i = 0; i < 8; i++) {
+    result <<= 8;
+    result |= bytes[permute_table[mode][i]];
+  }
+  return result;
+}
+
+
+void Simulator::VisitDataProcessing2Source(Instruction* instr) {
+  Shift shift_op = NO_SHIFT;
+  int64_t result = 0;
+  switch (instr->Mask(DataProcessing2SourceMask)) {
+    case SDIV_w: result = wreg(instr->Rn()) / wreg(instr->Rm()); break;
+    case SDIV_x: result = xreg(instr->Rn()) / xreg(instr->Rm()); break;
+    case UDIV_w: {
+      uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
+      uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
+      result = rn / rm;
+      break;
+    }
+    case UDIV_x: {
+      uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
+      uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
+      result = rn / rm;
+      break;
+    }
+    case LSLV_w:
+    case LSLV_x: shift_op = LSL; break;
+    case LSRV_w:
+    case LSRV_x: shift_op = LSR; break;
+    case ASRV_w:
+    case ASRV_x: shift_op = ASR; break;
+    case RORV_w:
+    case RORV_x: shift_op = ROR; break;
+    default: UNIMPLEMENTED();
+  }
+
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  if (shift_op != NO_SHIFT) {
+    // Shift distance encoded in the least-significant five/six bits of the
+    // register.
+    int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
+    unsigned shift = wreg(instr->Rm()) & mask;
+    result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
+                          shift);
+  }
+  set_reg(reg_size, instr->Rd(), result);
+}
+
+
+// The algorithm used is adapted from the one described in section 8.2 of
+//   Hacker's Delight, by Henry S. Warren, Jr.
+// It assumes that a right shift on a signed integer is an arithmetic shift.
+static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
+  uint64_t u0, v0, w0;
+  int64_t u1, v1, w1, w2, t;
+
+  u0 = u & 0xffffffffL;
+  u1 = u >> 32;
+  v0 = v & 0xffffffffL;
+  v1 = v >> 32;
+
+  w0 = u0 * v0;
+  t = u1 * v0 + (w0 >> 32);
+  w1 = t & 0xffffffffL;
+  w2 = t >> 32;
+  w1 = u0 * v1 + w1;
+
+  return u1 * v1 + w2 + (w1 >> 32);
+}
+
+
+void Simulator::VisitDataProcessing3Source(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+
+  int64_t result = 0;
+  uint64_t rn;
+  uint64_t rm;
+  switch (instr->Mask(DataProcessing3SourceMask)) {
+    case MADD_w:
+    case MADD_x:
+      result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
+      break;
+    case MSUB_w:
+    case MSUB_x:
+      result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
+      break;
+    case SMADDL_x:
+      result = xreg(instr->Ra()) + (wreg(instr->Rn()) * wreg(instr->Rm()));
+      break;
+    case SMSUBL_x:
+      result = xreg(instr->Ra()) - (wreg(instr->Rn()) * wreg(instr->Rm()));
+      break;
+    case UMADDL_x:
+      rn = static_cast<uint32_t>(wreg(instr->Rn()));
+      rm = static_cast<uint32_t>(wreg(instr->Rm()));
+      result = xreg(instr->Ra()) + (rn * rm);
+      break;
+    case UMSUBL_x:
+      rn = static_cast<uint32_t>(wreg(instr->Rn()));
+      rm = static_cast<uint32_t>(wreg(instr->Rm()));
+      result = xreg(instr->Ra()) - (rn * rm);
+      break;
+    case SMULH_x:
+      result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
+      break;
+    default: UNIMPLEMENTED();
+  }
+  set_reg(reg_size, instr->Rd(), result);
+}
+
+
+void Simulator::VisitBitfield(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
+  int64_t R = instr->ImmR();
+  int64_t S = instr->ImmS();
+  int64_t diff = S - R;
+  int64_t mask;
+  if (diff >= 0) {
+    mask = diff < reg_size - 1 ? (1L << (diff + 1)) - 1
+                               : reg_mask;
+  } else {
+    mask = ((1L << (S + 1)) - 1);
+    mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
+    diff += reg_size;
+  }
+
+  // inzero indicates if the extracted bitfield is inserted into the
+  // destination register value or in zero.
+  // If extend is true, extend the sign of the extracted bitfield.
+  bool inzero = false;
+  bool extend = false;
+  switch (instr->Mask(BitfieldMask)) {
+    case BFM_x:
+    case BFM_w:
+      break;
+    case SBFM_x:
+    case SBFM_w:
+      inzero = true;
+      extend = true;
+      break;
+    case UBFM_x:
+    case UBFM_w:
+      inzero = true;
+      break;
+    default:
+      UNIMPLEMENTED();
+  }
+
+  int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
+  int64_t src = reg(reg_size, instr->Rn());
+  // Rotate source bitfield into place.
+  int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
+  // Determine the sign extension.
+  int64_t topbits = ((1L << (reg_size - diff - 1)) - 1) << (diff + 1);
+  int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
+
+  // Merge sign extension, dest/zero and bitfield.
+  result = signbits | (result & mask) | (dst & ~mask);
+
+  set_reg(reg_size, instr->Rd(), result);
+}
+
+
+void Simulator::VisitExtract(Instruction* instr) {
+  unsigned lsb = instr->ImmS();
+  unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
+                                                    : kWRegSize;
+  set_reg(reg_size,
+          instr->Rd(),
+          (static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb) |
+          (reg(reg_size, instr->Rn()) << (reg_size - lsb)));
+}
+
+
+void Simulator::VisitFPImmediate(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned dest = instr->Rd();
+  switch (instr->Mask(FPImmediateMask)) {
+    case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
+    case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitFPIntegerConvert(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned dst = instr->Rd();
+  unsigned src = instr->Rn();
+
+  FPRounding round = RMode();
+
+  switch (instr->Mask(FPIntegerConvertMask)) {
+    case FCVTMS_ws:
+      set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMS_xs:
+      set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMS_wd:
+      set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMS_xd:
+      set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_ws:
+      set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_xs:
+      set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_wd:
+      set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_xd:
+      set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
+    case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
+    case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
+    case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
+    case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
+    case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
+    case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
+    case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
+    case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
+    case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
+    case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
+    case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
+    case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
+    case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
+    case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
+    case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
+    case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
+    case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
+    case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
+    case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
+
+    // A 32-bit input can be handled in the same way as a 64-bit input, since
+    // the sign- or zero-extension will not affect the conversion.
+    case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
+    case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
+    case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
+    case UCVTF_dw: {
+      set_dreg(dst, UFixedToDouble(static_cast<uint32_t>(wreg(src)), 0, round));
+      break;
+    }
+    case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
+    case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
+    case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
+    case UCVTF_sw: {
+      set_sreg(dst, UFixedToFloat(static_cast<uint32_t>(wreg(src)), 0, round));
+      break;
+    }
+
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned dst = instr->Rd();
+  unsigned src = instr->Rn();
+  int fbits = 64 - instr->FPScale();
+
+  FPRounding round = RMode();
+
+  switch (instr->Mask(FPFixedPointConvertMask)) {
+    // A 32-bit input can be handled in the same way as a 64-bit input, since
+    // the sign- or zero-extension will not affect the conversion.
+    case SCVTF_dx_fixed:
+      set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
+      break;
+    case SCVTF_dw_fixed:
+      set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
+      break;
+    case UCVTF_dx_fixed:
+      set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
+      break;
+    case UCVTF_dw_fixed: {
+      set_dreg(dst,
+               UFixedToDouble(static_cast<uint32_t>(wreg(src)), fbits, round));
+      break;
+    }
+    case SCVTF_sx_fixed:
+      set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
+      break;
+    case SCVTF_sw_fixed:
+      set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
+      break;
+    case UCVTF_sx_fixed:
+      set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
+      break;
+    case UCVTF_sw_fixed: {
+      set_sreg(dst,
+               UFixedToFloat(static_cast<uint32_t>(wreg(src)), fbits, round));
+      break;
+    }
+    default: UNREACHABLE();
+  }
+}
+
+
+int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kWMaxInt) {
+    return kWMaxInt;
+  } else if (value < kWMinInt) {
+    return kWMinInt;
+  }
+  return isnan(value) ? 0 : static_cast<int32_t>(value);
+}
+
+
+int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kXMaxInt) {
+    return kXMaxInt;
+  } else if (value < kXMinInt) {
+    return kXMinInt;
+  }
+  return isnan(value) ? 0 : static_cast<int64_t>(value);
+}
+
+
+uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kWMaxUInt) {
+    return kWMaxUInt;
+  } else if (value < 0.0) {
+    return 0;
+  }
+  return isnan(value) ? 0 : static_cast<uint32_t>(value);
+}
+
+
+uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kXMaxUInt) {
+    return kXMaxUInt;
+  } else if (value < 0.0) {
+    return 0;
+  }
+  return isnan(value) ? 0 : static_cast<uint64_t>(value);
+}
+
+
+void Simulator::VisitFPCompare(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
+  double fn_val = fpreg(reg_size, instr->Rn());
+
+  switch (instr->Mask(FPCompareMask)) {
+    case FCMP_s:
+    case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
+    case FCMP_s_zero:
+    case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPConditionalCompare(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  switch (instr->Mask(FPConditionalCompareMask)) {
+    case FCCMP_s:
+    case FCCMP_d: {
+      if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
+        // If the condition passes, set the status flags to the result of
+        // comparing the operands.
+        unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
+        FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
+      } else {
+        // If the condition fails, set the status flags to the nzcv immediate.
+        nzcv().SetFlags(instr->Nzcv());
+      }
+      break;
+    }
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPConditionalSelect(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
+
+  double selected_val;
+  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
+    selected_val = fpreg(reg_size, instr->Rn());
+  } else {
+    selected_val = fpreg(reg_size, instr->Rm());
+  }
+
+  switch (instr->Mask(FPConditionalSelectMask)) {
+    case FCSEL_s:
+    case FCSEL_d: set_fpreg(reg_size, instr->Rd(), selected_val); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned fd = instr->Rd();
+  unsigned fn = instr->Rn();
+
+  switch (instr->Mask(FPDataProcessing1SourceMask)) {
+    case FMOV_s: set_sreg(fd, sreg(fn)); break;
+    case FMOV_d: set_dreg(fd, dreg(fn)); break;
+    case FABS_s: set_sreg(fd, fabs(sreg(fn))); break;
+    case FABS_d: set_dreg(fd, fabs(dreg(fn))); break;
+    case FNEG_s: set_sreg(fd, -sreg(fn)); break;
+    case FNEG_d: set_dreg(fd, -dreg(fn)); break;
+    case FSQRT_s: set_sreg(fd, sqrt(sreg(fn))); break;
+    case FSQRT_d: set_dreg(fd, sqrt(dreg(fn))); break;
+    case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
+    case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
+    case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
+    case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
+    case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
+    case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+// Assemble the specified IEEE-754 components into the target type and apply
+// appropriate rounding.
+//  sign:     0 = positive, 1 = negative
+//  exponent: Unbiased IEEE-754 exponent.
+//  mantissa: The mantissa of the input. The top bit (which is not encoded for
+//            normal IEEE-754 values) must not be omitted. This bit has the
+//            value 'pow(2, exponent)'.
+//
+// The input value is assumed to be a normalized value. That is, the input may
+// not be infinity or NaN. If the source value is subnormal, it must be
+// normalized before calling this function such that the highest set bit in the
+// mantissa has the value 'pow(2, exponent)'.
+//
+// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
+// calling a templated FPRound.
+template <class T, int ebits, int mbits>
+static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
+                 FPRounding round_mode) {
+  ASSERT((sign == 0) || (sign == 1));
+
+  // Only the FPTieEven rounding mode is implemented.
+  ASSERT(round_mode == FPTieEven);
+  USE(round_mode);
+
+  // Rounding can promote subnormals to normals, and normals to infinities. For
+  // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
+  // encodable as a float, but rounding based on the low-order mantissa bits
+  // could make it overflow. With ties-to-even rounding, this value would become
+  // an infinity.
+
+  // ---- Rounding Method ----
+  //
+  // The exponent is irrelevant in the rounding operation, so we treat the
+  // lowest-order bit that will fit into the result ('onebit') as having
+  // the value '1'. Similarly, the highest-order bit that won't fit into
+  // the result ('halfbit') has the value '0.5'. The 'point' sits between
+  // 'onebit' and 'halfbit':
+  //
+  //            These bits fit into the result.
+  //               |---------------------|
+  //  mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+  //                                     ||
+  //                                    / |
+  //                                   /  halfbit
+  //                               onebit
+  //
+  // For subnormal outputs, the range of representable bits is smaller and
+  // the position of onebit and halfbit depends on the exponent of the
+  // input, but the method is otherwise similar.
+  //
+  //   onebit(frac)
+  //     |
+  //     | halfbit(frac)          halfbit(adjusted)
+  //     | /                      /
+  //     | |                      |
+  //  0b00.0 (exact)      -> 0b00.0 (exact)                    -> 0b00
+  //  0b00.0...           -> 0b00.0...                         -> 0b00
+  //  0b00.1 (exact)      -> 0b00.0111..111                    -> 0b00
+  //  0b00.1...           -> 0b00.1...                         -> 0b01
+  //  0b01.0 (exact)      -> 0b01.0 (exact)                    -> 0b01
+  //  0b01.0...           -> 0b01.0...                         -> 0b01
+  //  0b01.1 (exact)      -> 0b01.1 (exact)                    -> 0b10
+  //  0b01.1...           -> 0b01.1...                         -> 0b10
+  //  0b10.0 (exact)      -> 0b10.0 (exact)                    -> 0b10
+  //  0b10.0...           -> 0b10.0...                         -> 0b10
+  //  0b10.1 (exact)      -> 0b10.0111..111                    -> 0b10
+  //  0b10.1...           -> 0b10.1...                         -> 0b11
+  //  0b11.0 (exact)      -> 0b11.0 (exact)                    -> 0b11
+  //  ...                   /             |                      /   |
+  //                       /              |                     /    |
+  //                                                           /     |
+  // adjusted = frac - (halfbit(mantissa) & ~onebit(frac));   /      |
+  //
+  //                   mantissa = (mantissa >> shift) + halfbit(adjusted);
+
+  static const int mantissa_offset = 0;
+  static const int exponent_offset = mantissa_offset + mbits;
+  static const int sign_offset = exponent_offset + ebits;
+  ASSERT(sign_offset == (sizeof(T) * 8 - 1));
+
+  // Bail out early for zero inputs.
+  if (mantissa == 0) {
+    return sign << sign_offset;
+  }
+
+  // If all bits in the exponent are set, the value is infinite or NaN.
+  // This is true for all binary IEEE-754 formats.
+  static const int infinite_exponent = (1 << ebits) - 1;
+  static const int max_normal_exponent = infinite_exponent - 1;
+
+  // Apply the exponent bias to encode it for the result. Doing this early makes
+  // it easy to detect values that will be infinite or subnormal.
+  exponent += max_normal_exponent >> 1;
+
+  if (exponent > max_normal_exponent) {
+    // Overflow: The input is too large for the result type to represent. The
+    // FPTieEven rounding mode handles overflows using infinities.
+    exponent = infinite_exponent;
+    mantissa = 0;
+    return (sign << sign_offset) |
+           (exponent << exponent_offset) |
+           (mantissa << mantissa_offset);
+  }
+
+  // Calculate the shift required to move the top mantissa bit to the proper
+  // place in the destination type.
+  const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
+  int shift = highest_significant_bit - mbits;
+
+  if (exponent <= 0) {
+    // The output will be subnormal (before rounding).
+
+    // For subnormal outputs, the shift must be adjusted by the exponent. The +1
+    // is necessary because the exponent of a subnormal value (encoded as 0) is
+    // the same as the exponent of the smallest normal value (encoded as 1).
+    shift += -exponent + 1;
+
+    // Handle inputs that would produce a zero output.
+    //
+    // Shifts higher than highest_significant_bit+1 will always produce a zero
+    // result. A shift of exactly highest_significant_bit+1 might produce a
+    // non-zero result after rounding.
+    if (shift > (highest_significant_bit + 1)) {
+      // The result will always be +/-0.0.
+      return sign << sign_offset;
+    }
+
+    // Properly encode the exponent for a subnormal output.
+    exponent = 0;
+  } else {
+    // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
+    // normal values.
+    mantissa &= ~(1UL << highest_significant_bit);
+  }
+
+  if (shift > 0) {
+    // We have to shift the mantissa to the right. Some precision is lost, so we
+    // need to apply rounding.
+    uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
+    uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
+    uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
+    T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
+
+    T result = (sign << sign_offset) |
+               (exponent << exponent_offset) |
+               ((mantissa >> shift) << mantissa_offset);
+
+    // A very large mantissa can overflow during rounding. If this happens, the
+    // exponent should be incremented and the mantissa set to 1.0 (encoded as
+    // 0). Applying halfbit_adjusted after assembling the float has the nice
+    // side-effect that this case is handled for free.
+    //
+    // This also handles cases where a very large finite value overflows to
+    // infinity, or where a very large subnormal value overflows to become
+    // normal.
+    return result + halfbit_adjusted;
+  } else {
+    // We have to shift the mantissa to the left (or not at all). The input
+    // mantissa is exactly representable in the output mantissa, so apply no
+    // rounding correction.
+    return (sign << sign_offset) |
+           (exponent << exponent_offset) |
+           ((mantissa << -shift) << mantissa_offset);
+  }
+}
+
+
+// See FPRound for a description of this function.
+static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
+                                     uint64_t mantissa, FPRounding round_mode) {
+  int64_t bits =
+      FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
+                                                                 exponent,
+                                                                 mantissa,
+                                                                 round_mode);
+  return rawbits_to_double(bits);
+}
+
+
+// See FPRound for a description of this function.
+static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
+                                   uint64_t mantissa, FPRounding round_mode) {
+  int32_t bits =
+      FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
+                                                               exponent,
+                                                               mantissa,
+                                                               round_mode);
+  return rawbits_to_float(bits);
+}
+
+
+double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
+  if (src >= 0) {
+    return UFixedToDouble(src, fbits, round);
+  } else {
+    // This works for all negative values, including INT64_MIN.
+    return -UFixedToDouble(-src, fbits, round);
+  }
+}
+
+
+double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
+  // An input of 0 is a special case because the result is effectively
+  // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
+  if (src == 0) {
+    return 0.0;
+  }
+
+  // Calculate the exponent. The highest significant bit will have the value
+  // 2^exponent.
+  const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
+  const int64_t exponent = highest_significant_bit - fbits;
+
+  return FPRoundToDouble(0, exponent, src, round);
+}
+
+
+float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
+  if (src >= 0) {
+    return UFixedToFloat(src, fbits, round);
+  } else {
+    // This works for all negative values, including INT64_MIN.
+    return -UFixedToFloat(-src, fbits, round);
+  }
+}
+
+
+float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
+  // An input of 0 is a special case because the result is effectively
+  // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
+  if (src == 0) {
+    return 0.0f;
+  }
+
+  // Calculate the exponent. The highest significant bit will have the value
+  // 2^exponent.
+  const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
+  const int32_t exponent = highest_significant_bit - fbits;
+
+  return FPRoundToFloat(0, exponent, src, round);
+}
+
+
+double Simulator::FPRoundInt(double value, FPRounding round_mode) {
+  if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
+      (value == kFP64NegativeInfinity) || isnan(value)) {
+    return value;
+  }
+
+  double int_result = floor(value);
+  double error = value - int_result;
+  switch (round_mode) {
+    case FPTieEven: {
+      // If the error is greater than 0.5, or is equal to 0.5 and the integer
+      // result is odd, round up.
+      if ((error > 0.5) ||
+          ((error == 0.5) && (fmod(int_result, 2) != 0))) {
+        int_result++;
+      }
+      break;
+    }
+    case FPZero: {
+      // If value>0 then we take floor(value)
+      // otherwise, ceil(value).
+      if (value < 0) {
+         int_result = ceil(value);
+      }
+      break;
+    }
+    case FPNegativeInfinity: {
+      // We always use floor(value).
+      break;
+    }
+    default: UNIMPLEMENTED();
+  }
+  return int_result;
+}
+
+
+double Simulator::FPToDouble(float value) {
+  switch (fpclassify(value)) {
+    case FP_NAN: {
+      // Convert NaNs as the processor would, assuming that FPCR.DN (default
+      // NaN) is not set:
+      //  - The sign is propagated.
+      //  - The payload (mantissa) is transferred entirely, except that the top
+      //    bit is forced to '1', making the result a quiet NaN. The unused
+      //    (low-order) payload bits are set to 0.
+      uint32_t raw = float_to_rawbits(value);
+
+      uint64_t sign = raw >> 31;
+      uint64_t exponent = (1 << 11) - 1;
+      uint64_t payload = unsigned_bitextract_64(21, 0, raw);
+      payload <<= (52 - 23);  // The unused low-order bits should be 0.
+      payload |= (1L << 51);  // Force a quiet NaN.
+
+      return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
+    }
+
+    case FP_ZERO:
+    case FP_NORMAL:
+    case FP_SUBNORMAL:
+    case FP_INFINITE: {
+      // All other inputs are preserved in a standard cast, because every value
+      // representable using an IEEE-754 float is also representable using an
+      // IEEE-754 double.
+      return static_cast<double>(value);
+    }
+  }
+
+  UNREACHABLE();
+  return static_cast<double>(value);
+}
+
+
+float Simulator::FPToFloat(double value, FPRounding round_mode) {
+  // Only the FPTieEven rounding mode is implemented.
+  ASSERT(round_mode == FPTieEven);
+  USE(round_mode);
+
+  switch (fpclassify(value)) {
+    case FP_NAN: {
+      // Convert NaNs as the processor would, assuming that FPCR.DN (default
+      // NaN) is not set:
+      //  - The sign is propagated.
+      //  - The payload (mantissa) is transferred as much as possible, except
+      //    that the top bit is forced to '1', making the result a quiet NaN.
+      uint64_t raw = double_to_rawbits(value);
+
+      uint32_t sign = raw >> 63;
+      uint32_t exponent = (1 << 8) - 1;
+      uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw);
+      payload |= (1 << 22);   // Force a quiet NaN.
+
+      return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
+    }
+
+    case FP_ZERO:
+    case FP_INFINITE: {
+      // In a C++ cast, any value representable in the target type will be
+      // unchanged. This is always the case for +/-0.0 and infinities.
+      return static_cast<float>(value);
+    }
+
+    case FP_NORMAL:
+    case FP_SUBNORMAL: {
+      // Convert double-to-float as the processor would, assuming that FPCR.FZ
+      // (flush-to-zero) is not set.
+      uint64_t raw = double_to_rawbits(value);
+      // Extract the IEEE-754 double components.
+      uint32_t sign = raw >> 63;
+      // Extract the exponent and remove the IEEE-754 encoding bias.
+      int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023;
+      // Extract the mantissa and add the implicit '1' bit.
+      uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
+      if (fpclassify(value) == FP_NORMAL) {
+        mantissa |= (1UL << 52);
+      }
+      return FPRoundToFloat(sign, exponent, mantissa, round_mode);
+    }
+  }
+
+  UNREACHABLE();
+  return value;
+}
+
+
+void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned fd = instr->Rd();
+  unsigned fn = instr->Rn();
+  unsigned fm = instr->Rm();
+
+  switch (instr->Mask(FPDataProcessing2SourceMask)) {
+    case FADD_s: set_sreg(fd, sreg(fn) + sreg(fm)); break;
+    case FADD_d: set_dreg(fd, dreg(fn) + dreg(fm)); break;
+    case FSUB_s: set_sreg(fd, sreg(fn) - sreg(fm)); break;
+    case FSUB_d: set_dreg(fd, dreg(fn) - dreg(fm)); break;
+    case FMUL_s: set_sreg(fd, sreg(fn) * sreg(fm)); break;
+    case FMUL_d: set_dreg(fd, dreg(fn) * dreg(fm)); break;
+    case FDIV_s: set_sreg(fd, sreg(fn) / sreg(fm)); break;
+    case FDIV_d: set_dreg(fd, dreg(fn) / dreg(fm)); break;
+    case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
+    case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
+    case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
+    case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned fd = instr->Rd();
+  unsigned fn = instr->Rn();
+  unsigned fm = instr->Rm();
+  unsigned fa = instr->Ra();
+
+  // Note: The FMSUB implementation here is not precisely the same as the
+  // instruction definition. In full implementation rounding of results would
+  // occur once at the end, here rounding will occur after the first multiply
+  // and then after the subsequent addition.  A full implementation here would
+  // be possible but would require an effort isn't immediately justified given
+  // the small differences we expect to see in most cases.
+
+  switch (instr->Mask(FPDataProcessing3SourceMask)) {
+    case FMSUB_s: set_sreg(fd, sreg(fa) + (-sreg(fn))*sreg(fm)); break;
+    case FMSUB_d: set_dreg(fd, dreg(fa) + (-dreg(fn))*dreg(fm)); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+double Simulator::FPMax(double a, double b) {
+  if (isnan(a)) {
+    return a;
+  } else if (isnan(b)) {
+    return b;
+  }
+
+  if ((a == 0.0) && (b == 0.0) &&
+      (copysign(1.0, a) != copysign(1.0, b))) {
+    // a and b are zero, and the sign differs: return +0.0.
+    return 0.0;
+  } else {
+    return (a > b) ? a : b;
+  }
+}
+
+
+double Simulator::FPMin(double a, double b) {
+  if (isnan(a)) {
+    return a;
+  } else if (isnan(b)) {
+    return b;
+  }
+
+  if ((a == 0.0) && (b == 0.0) &&
+      (copysign(1.0, a) != copysign(1.0, b))) {
+    // a and b are zero, and the sign differs: return -0.0.
+    return -0.0;
+  } else {
+    return (a < b) ? a : b;
+  }
+}
+
+
+void Simulator::VisitSystem(Instruction* instr) {
+  // Some system instructions hijack their Op and Cp fields to represent a
+  // range of immediates instead of indicating a different instruction. This
+  // makes the decoding tricky.
+  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
+    switch (instr->Mask(SystemSysRegMask)) {
+      case MRS: {
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
+          case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
+          default: UNIMPLEMENTED();
+        }
+        break;
+      }
+      case MSR: {
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break;
+          case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break;
+          default: UNIMPLEMENTED();
+        }
+        break;
+      }
+    }
+  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
+    ASSERT(instr->Mask(SystemHintMask) == HINT);
+    switch (instr->ImmHint()) {
+      case NOP: break;
+      default: UNIMPLEMENTED();
+    }
+  } else {
+    UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitException(Instruction* instr) {
+  switch (instr->Mask(ExceptionMask)) {
+    case BRK: HostBreakpoint(); break;
+    case HLT:
+      // The Printf pseudo instruction is so useful, we include it in the
+      // default simulator.
+      if (instr->ImmException() == kPrintfOpcode) {
+        DoPrintf(instr);
+      } else {
+        HostBreakpoint();
+      }
+      break;
+    default:
+      UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::DoPrintf(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kPrintfOpcode));
+
+  // Read the argument encoded inline in the instruction stream.
+  uint32_t type;
+  ASSERT(sizeof(*instr) == 1);
+  memcpy(&type, instr + kPrintfTypeOffset, sizeof(type));
+
+  const char * format = reinterpret_cast<const char *>(x0());
+  ASSERT(format != NULL);
+
+  // Pass all of the relevant PCS registers onto printf. It doesn't matter
+  // if we pass too many as the extra ones won't be read.
+  int result = 0;
+  if (type == CPURegister::kRegister) {
+    result = printf(format, x1(), x2(), x3(), x4(), x5(), x6(), x7());
+  } else if (type == CPURegister::kFPRegister) {
+    result = printf(format, d0(), d1(), d2(), d3(), d4(), d5(), d6(), d7());
+  } else {
+    ASSERT(type == CPURegister::kNoRegister);
+    result = printf("%s", format);
+  }
+  set_x0(result);
+
+  // TODO: Clobber all caller-saved registers here, to ensure no assumptions
+  // are made about preserved state.
+
+  // The printf parameters are inlined in the code, so skip them.
+  set_pc(instr->InstructionAtOffset(kPrintfLength));
+
+  // Set LR as if we'd just called a native printf function.
+  set_lr(reinterpret_cast<uint64_t>(pc()));
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/simulator-a64.h b/disas/libvixl/src/a64/simulator-a64.h
new file mode 100644
index 0000000..0c22f9e
--- /dev/null
+++ b/disas/libvixl/src/a64/simulator-a64.h
@@ -0,0 +1,576 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_SIMULATOR_A64_H_
+#define VIXL_A64_SIMULATOR_A64_H_
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/instructions-a64.h"
+#include "a64/assembler-a64.h"
+#include "a64/disasm-a64.h"
+#include "a64/instrument-a64.h"
+
+namespace vixl {
+
+enum ReverseByteMode {
+  Reverse16 = 0,
+  Reverse32 = 1,
+  Reverse64 = 2
+};
+
+// Printf. See debugger-a64.h for more informations on pseudo instructions.
+//  - type: CPURegister::RegisterType stored as a uint32_t.
+//
+// Simulate a call to printf.
+//
+// Floating-point and integer arguments are passed in separate sets of
+// registers in AAPCS64 (even for varargs functions), so it is not possible to
+// determine the type of location of each argument without some information
+// about the values that were passed in. This information could be retrieved
+// from the printf format string, but the format string is not trivial to
+// parse so we encode the relevant information with the HLT instruction under
+// the type argument. Therefore the interface is:
+//    x0: The format string
+// x1-x7: Optional arguments, if type == CPURegister::kRegister
+// d0-d7: Optional arguments, if type == CPURegister::kFPRegister
+const Instr kPrintfOpcode = 0xdeb1;
+const unsigned kPrintfTypeOffset = 1 * kInstructionSize;
+const unsigned kPrintfLength = 2 * kInstructionSize;
+
+
+// The proper way to initialize a simulated system register (such as NZCV) is as
+// follows:
+//  SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
+class SimSystemRegister {
+ public:
+  // The default constructor represents a register which has no writable bits.
+  // It is not possible to set its value to anything other than 0.
+  SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
+
+  inline uint32_t RawValue() const {
+    return value_;
+  }
+
+  inline void SetRawValue(uint32_t new_value) {
+    value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
+  }
+
+  inline uint32_t Bits(int msb, int lsb) const {
+    return unsigned_bitextract_32(msb, lsb, value_);
+  }
+
+  inline int32_t SignedBits(int msb, int lsb) const {
+    return signed_bitextract_32(msb, lsb, value_);
+  }
+
+  void SetBits(int msb, int lsb, uint32_t bits);
+
+  // Default system register values.
+  static SimSystemRegister DefaultValueFor(SystemRegister id);
+
+#define DEFINE_GETTER(Name, HighBit, LowBit, Func)                            \
+  inline uint32_t Name() const { return Func(HighBit, LowBit); }              \
+  inline void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
+#define DEFINE_WRITE_IGNORE_MASK(Name, Mask)                                  \
+  static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
+
+  SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
+
+#undef DEFINE_ZERO_BITS
+#undef DEFINE_GETTER
+
+ protected:
+  // Most system registers only implement a few of the bits in the word. Other
+  // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
+  // describes the bits which are not modifiable.
+  SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
+      : value_(value), write_ignore_mask_(write_ignore_mask) { }
+
+  uint32_t value_;
+  uint32_t write_ignore_mask_;
+};
+
+
+class Simulator : public DecoderVisitor {
+ public:
+  explicit Simulator(Decoder* decoder, FILE* stream = stdout);
+  ~Simulator();
+
+  void ResetState();
+
+  // TODO: We assume little endianness, and the way in which the members of this
+  // union overlay. Add tests to ensure this, or fix accessors to no longer
+  // require this assumption.
+  union SimRegister {
+    int64_t x;
+    int32_t w;
+  };
+
+  union SimFPRegister {
+    double d;
+    float s;
+  };
+
+  // Run the simulator.
+  virtual void Run();
+  void RunFrom(Instruction* first);
+
+  // Simulation helpers.
+  inline Instruction* pc() { return pc_; }
+  inline void set_pc(Instruction* new_pc) {
+    pc_ = new_pc;
+    pc_modified_ = true;
+  }
+
+  inline void increment_pc() {
+    if (!pc_modified_) {
+      pc_ = pc_->NextInstruction();
+    }
+
+    pc_modified_ = false;
+  }
+
+  inline void ExecuteInstruction() {
+    // The program counter should always be aligned.
+    ASSERT(IsWordAligned(pc_));
+    decoder_->Decode(pc_);
+    increment_pc();
+  }
+
+  // Declare all Visitor functions.
+  #define DECLARE(A)  void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+  // Register accessors.
+  inline int32_t wreg(unsigned code,
+                      Reg31Mode r31mode = Reg31IsZeroRegister) const {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
+      return 0;
+    }
+    return registers_[code].w;
+  }
+
+  inline int64_t xreg(unsigned code,
+                      Reg31Mode r31mode = Reg31IsZeroRegister) const {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
+      return 0;
+    }
+    return registers_[code].x;
+  }
+
+  inline int64_t reg(unsigned size,
+                     unsigned code,
+                     Reg31Mode r31mode = Reg31IsZeroRegister) const {
+    switch (size) {
+      case kWRegSize: return wreg(code, r31mode) & kWRegMask;
+      case kXRegSize: return xreg(code, r31mode);
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+  }
+
+  inline void set_wreg(unsigned code, int32_t value,
+                       Reg31Mode r31mode = Reg31IsZeroRegister) {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
+      return;
+    }
+    registers_[code].x = 0;  // First clear the register top bits.
+    registers_[code].w = value;
+  }
+
+  inline void set_xreg(unsigned code, int64_t value,
+                       Reg31Mode r31mode = Reg31IsZeroRegister) {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
+      return;
+    }
+    registers_[code].x = value;
+  }
+
+  inline void set_reg(unsigned size, unsigned code, int64_t value,
+                      Reg31Mode r31mode = Reg31IsZeroRegister) {
+    switch (size) {
+      case kWRegSize:
+        return set_wreg(code, static_cast<int32_t>(value & 0xffffffff),
+                        r31mode);
+      case kXRegSize:
+        return set_xreg(code, value, r31mode);
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+
+  #define REG_ACCESSORS(N)                                 \
+  inline int32_t w##N() { return wreg(N); }                \
+  inline int64_t x##N() { return xreg(N); }                \
+  inline void set_w##N(int32_t val) { set_wreg(N, val); }  \
+  inline void set_x##N(int64_t val) { set_xreg(N, val); }
+  REGISTER_CODE_LIST(REG_ACCESSORS)
+  #undef REG_ACCESSORS
+
+  // Aliases.
+  #define REG_ALIAS_ACCESSORS(N, wname, xname)                \
+  inline int32_t wname() { return wreg(N); }                  \
+  inline int64_t xname() { return xreg(N); }                  \
+  inline void set_##wname(int32_t val) { set_wreg(N, val); }  \
+  inline void set_##xname(int64_t val) { set_xreg(N, val); }
+  REG_ALIAS_ACCESSORS(30, wlr, lr);
+  #undef REG_ALIAS_ACCESSORS
+
+  // The stack is a special case in aarch64.
+  inline int32_t wsp() { return wreg(31, Reg31IsStackPointer); }
+  inline int64_t sp() { return xreg(31, Reg31IsStackPointer); }
+  inline void set_wsp(int32_t val) {
+    set_wreg(31, val, Reg31IsStackPointer);
+  }
+  inline void set_sp(int64_t val) {
+    set_xreg(31, val, Reg31IsStackPointer);
+  }
+
+  // FPRegister accessors.
+  inline float sreg(unsigned code) const {
+    ASSERT(code < kNumberOfFPRegisters);
+    return fpregisters_[code].s;
+  }
+
+  inline uint32_t sreg_bits(unsigned code) const {
+    return float_to_rawbits(sreg(code));
+  }
+
+  inline double dreg(unsigned code) const {
+    ASSERT(code < kNumberOfFPRegisters);
+    return fpregisters_[code].d;
+  }
+
+  inline uint64_t dreg_bits(unsigned code) const {
+    return double_to_rawbits(dreg(code));
+  }
+
+  inline double fpreg(unsigned size, unsigned code) const {
+    switch (size) {
+      case kSRegSize: return sreg(code);
+      case kDRegSize: return dreg(code);
+      default: {
+        UNREACHABLE();
+        return 0.0;
+      }
+    }
+  }
+
+  inline void set_sreg(unsigned code, float val) {
+    ASSERT(code < kNumberOfFPRegisters);
+    // Ensure that the upper word is set to 0.
+    set_dreg_bits(code, 0);
+
+    fpregisters_[code].s = val;
+  }
+
+  inline void set_sreg_bits(unsigned code, uint32_t rawbits) {
+    ASSERT(code < kNumberOfFPRegisters);
+    // Ensure that the upper word is set to 0.
+    set_dreg_bits(code, 0);
+
+    set_sreg(code, rawbits_to_float(rawbits));
+  }
+
+  inline void set_dreg(unsigned code, double val) {
+    ASSERT(code < kNumberOfFPRegisters);
+    fpregisters_[code].d = val;
+  }
+
+  inline void set_dreg_bits(unsigned code, uint64_t rawbits) {
+    ASSERT(code < kNumberOfFPRegisters);
+    set_dreg(code, rawbits_to_double(rawbits));
+  }
+
+  inline void set_fpreg(unsigned size, unsigned code, double value) {
+    switch (size) {
+      case kSRegSize:
+        return set_sreg(code, value);
+      case kDRegSize:
+        return set_dreg(code, value);
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+
+  #define FPREG_ACCESSORS(N)                             \
+  inline float s##N() { return sreg(N); }                \
+  inline double d##N() { return dreg(N); }               \
+  inline void set_s##N(float val) { set_sreg(N, val); }  \
+  inline void set_d##N(double val) { set_dreg(N, val); }
+  REGISTER_CODE_LIST(FPREG_ACCESSORS)
+  #undef FPREG_ACCESSORS
+
+  bool N() { return nzcv_.N() != 0; }
+  bool Z() { return nzcv_.Z() != 0; }
+  bool C() { return nzcv_.C() != 0; }
+  bool V() { return nzcv_.V() != 0; }
+  SimSystemRegister& nzcv() { return nzcv_; }
+
+  // TODO(jbramley): Find a way to make the fpcr_ members return the proper
+  // types, so this accessor is not necessary.
+  FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
+  SimSystemRegister& fpcr() { return fpcr_; }
+
+  // Debug helpers
+  void PrintSystemRegisters(bool print_all = false);
+  void PrintRegisters(bool print_all_regs = false);
+  void PrintFPRegisters(bool print_all_regs = false);
+  void PrintProcessorState();
+
+  static const char* WRegNameForCode(unsigned code,
+                                     Reg31Mode mode = Reg31IsZeroRegister);
+  static const char* XRegNameForCode(unsigned code,
+                                     Reg31Mode mode = Reg31IsZeroRegister);
+  static const char* SRegNameForCode(unsigned code);
+  static const char* DRegNameForCode(unsigned code);
+  static const char* VRegNameForCode(unsigned code);
+
+  inline bool coloured_trace() { return coloured_trace_; }
+  inline void set_coloured_trace(bool value) { coloured_trace_ = value; }
+
+  inline bool disasm_trace() { return disasm_trace_; }
+  inline void set_disasm_trace(bool value) {
+    if (value != disasm_trace_) {
+      if (value) {
+        decoder_->InsertVisitorBefore(print_disasm_, this);
+      } else {
+        decoder_->RemoveVisitor(print_disasm_);
+      }
+      disasm_trace_ = value;
+    }
+  }
+  inline void set_instruction_stats(bool value) {
+    if (value != instruction_stats_) {
+      if (value) {
+        decoder_->AppendVisitor(instrumentation_);
+      } else {
+        decoder_->RemoveVisitor(instrumentation_);
+      }
+      instruction_stats_ = value;
+    }
+  }
+
+ protected:
+  // Simulation helpers ------------------------------------
+  bool ConditionPassed(Condition cond) {
+    switch (cond) {
+      case eq:
+        return Z();
+      case ne:
+        return !Z();
+      case hs:
+        return C();
+      case lo:
+        return !C();
+      case mi:
+        return N();
+      case pl:
+        return !N();
+      case vs:
+        return V();
+      case vc:
+        return !V();
+      case hi:
+        return C() && !Z();
+      case ls:
+        return !(C() && !Z());
+      case ge:
+        return N() == V();
+      case lt:
+        return N() != V();
+      case gt:
+        return !Z() && (N() == V());
+      case le:
+        return !(!Z() && (N() == V()));
+      case nv:  // Fall through.
+      case al:
+        return true;
+      default:
+        UNREACHABLE();
+        return false;
+    }
+  }
+
+  bool ConditionFailed(Condition cond) {
+    return !ConditionPassed(cond);
+  }
+
+  void AddSubHelper(Instruction* instr, int64_t op2);
+  int64_t AddWithCarry(unsigned reg_size,
+                       bool set_flags,
+                       int64_t src1,
+                       int64_t src2,
+                       int64_t carry_in = 0);
+  void LogicalHelper(Instruction* instr, int64_t op2);
+  void ConditionalCompareHelper(Instruction* instr, int64_t op2);
+  void LoadStoreHelper(Instruction* instr,
+                       int64_t offset,
+                       AddrMode addrmode);
+  void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
+  uint8_t* AddressModeHelper(unsigned addr_reg,
+                             int64_t offset,
+                             AddrMode addrmode);
+
+  uint64_t MemoryRead(const uint8_t* address, unsigned num_bytes);
+  uint8_t MemoryRead8(uint8_t* address);
+  uint16_t MemoryRead16(uint8_t* address);
+  uint32_t MemoryRead32(uint8_t* address);
+  float MemoryReadFP32(uint8_t* address);
+  uint64_t MemoryRead64(uint8_t* address);
+  double MemoryReadFP64(uint8_t* address);
+
+  void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
+  void MemoryWrite32(uint8_t* address, uint32_t value);
+  void MemoryWriteFP32(uint8_t* address, float value);
+  void MemoryWrite64(uint8_t* address, uint64_t value);
+  void MemoryWriteFP64(uint8_t* address, double value);
+
+  int64_t ShiftOperand(unsigned reg_size,
+                       int64_t value,
+                       Shift shift_type,
+                       unsigned amount);
+  int64_t Rotate(unsigned reg_width,
+                 int64_t value,
+                 Shift shift_type,
+                 unsigned amount);
+  int64_t ExtendValue(unsigned reg_width,
+                      int64_t value,
+                      Extend extend_type,
+                      unsigned left_shift = 0);
+
+  uint64_t ReverseBits(uint64_t value, unsigned num_bits);
+  uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
+
+  void FPCompare(double val0, double val1);
+  double FPRoundInt(double value, FPRounding round_mode);
+  double FPToDouble(float value);
+  float FPToFloat(double value, FPRounding round_mode);
+  double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
+  double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
+  float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
+  float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
+  int32_t FPToInt32(double value, FPRounding rmode);
+  int64_t FPToInt64(double value, FPRounding rmode);
+  uint32_t FPToUInt32(double value, FPRounding rmode);
+  uint64_t FPToUInt64(double value, FPRounding rmode);
+  double FPMax(double a, double b);
+  double FPMin(double a, double b);
+
+  // Pseudo Printf instruction
+  void DoPrintf(Instruction* instr);
+
+  // Processor state ---------------------------------------
+
+  // Output stream.
+  FILE* stream_;
+  PrintDisassembler* print_disasm_;
+
+  // Instruction statistics instrumentation.
+  Instrument* instrumentation_;
+
+  // General purpose registers. Register 31 is the stack pointer.
+  SimRegister registers_[kNumberOfRegisters];
+
+  // Floating point registers
+  SimFPRegister fpregisters_[kNumberOfFPRegisters];
+
+  // Program Status Register.
+  // bits[31, 27]: Condition flags N, Z, C, and V.
+  //               (Negative, Zero, Carry, Overflow)
+  SimSystemRegister nzcv_;
+
+  // Floating-Point Control Register
+  SimSystemRegister fpcr_;
+
+  // Only a subset of FPCR features are supported by the simulator. This helper
+  // checks that the FPCR settings are supported.
+  //
+  // This is checked when floating-point instructions are executed, not when
+  // FPCR is set. This allows generated code to modify FPCR for external
+  // functions, or to save and restore it when entering and leaving generated
+  // code.
+  void AssertSupportedFPCR() {
+    ASSERT(fpcr().DN() == 0);             // No default-NaN support.
+    ASSERT(fpcr().FZ() == 0);             // No flush-to-zero support.
+    ASSERT(fpcr().RMode() == FPTieEven);  // Ties-to-even rounding only.
+
+    // The simulator does not support half-precision operations so fpcr().AHP()
+    // is irrelevant, and is not checked here.
+  }
+
+  static inline int CalcNFlag(uint64_t result, unsigned reg_size) {
+    return (result >> (reg_size - 1)) & 1;
+  }
+
+  static inline int CalcZFlag(uint64_t result) {
+    return result == 0;
+  }
+
+  static const uint32_t kConditionFlagsMask = 0xf0000000;
+
+  // Stack
+  byte* stack_;
+  static const int stack_protection_size_ = 256;
+  // 2 KB stack.
+  static const int stack_size_ = 2 * 1024 + 2 * stack_protection_size_;
+  byte* stack_limit_;
+
+  Decoder* decoder_;
+  // Indicates if the pc has been modified by the instruction and should not be
+  // automatically incremented.
+  bool pc_modified_;
+  Instruction* pc_;
+
+  static const char* xreg_names[];
+  static const char* wreg_names[];
+  static const char* sreg_names[];
+  static const char* dreg_names[];
+  static const char* vreg_names[];
+
+  static const Instruction* kEndOfSimAddress;
+
+ private:
+  bool coloured_trace_;
+
+  // Indicates whether the disassembly trace is active.
+  bool disasm_trace_;
+
+  // Indicates whether the instruction instrumentation is active.
+  bool instruction_stats_;
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_SIMULATOR_A64_H_
diff --git a/disas/libvixl/src/globals.h b/disas/libvixl/src/globals.h
new file mode 100644
index 0000000..859ea69
--- /dev/null
+++ b/disas/libvixl/src/globals.h
@@ -0,0 +1,66 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_GLOBALS_H
+#define VIXL_GLOBALS_H
+
+// Get the standard printf format macros for C99 stdint types.
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "platform.h"
+
+
+typedef uint8_t byte;
+
+const int KBytes = 1024;
+const int MBytes = 1024 * KBytes;
+const int GBytes = 1024 * MBytes;
+
+  #define ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort()
+#ifdef DEBUG
+  #define ASSERT(condition) assert(condition)
+  #define CHECK(condition) ASSERT(condition)
+  #define UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); ABORT()
+  #define UNREACHABLE() printf("UNREACHABLE\t"); ABORT()
+#else
+  #define ASSERT(condition) ((void) 0)
+  #define CHECK(condition) assert(condition)
+  #define UNIMPLEMENTED() ((void) 0)
+  #define UNREACHABLE() ((void) 0)
+#endif
+
+template <typename T> inline void USE(T) {}
+
+#define ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); ABORT()
+
+#endif  // VIXL_GLOBALS_H
diff --git a/disas/libvixl/src/platform.h b/disas/libvixl/src/platform.h
new file mode 100644
index 0000000..a2600f3
--- /dev/null
+++ b/disas/libvixl/src/platform.h
@@ -0,0 +1,43 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+// Define platform specific functionalities.
+
+namespace vixl {
+#ifdef USE_SIMULATOR
+// Currently we assume running the simulator implies running on x86 hardware.
+inline void HostBreakpoint() { asm("int3"); }
+#else
+inline void HostBreakpoint() {
+  // TODO: Implement HostBreakpoint on a64.
+}
+#endif
+}  // namespace vixl
+
+#endif
diff --git a/disas/libvixl/src/utils.cc b/disas/libvixl/src/utils.cc
new file mode 100644
index 0000000..6f85e61
--- /dev/null
+++ b/disas/libvixl/src/utils.cc
@@ -0,0 +1,120 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utils.h"
+#include <stdio.h>
+
+namespace vixl {
+
+uint32_t float_to_rawbits(float value) {
+  uint32_t bits = 0;
+  memcpy(&bits, &value, 4);
+  return bits;
+}
+
+
+uint64_t double_to_rawbits(double value) {
+  uint64_t bits = 0;
+  memcpy(&bits, &value, 8);
+  return bits;
+}
+
+
+float rawbits_to_float(uint32_t bits) {
+  float value = 0.0;
+  memcpy(&value, &bits, 4);
+  return value;
+}
+
+
+double rawbits_to_double(uint64_t bits) {
+  double value = 0.0;
+  memcpy(&value, &bits, 8);
+  return value;
+}
+
+
+int CountLeadingZeros(uint64_t value, int width) {
+  ASSERT((width == 32) || (width == 64));
+  int count = 0;
+  uint64_t bit_test = 1UL << (width - 1);
+  while ((count < width) && ((bit_test & value) == 0)) {
+    count++;
+    bit_test >>= 1;
+  }
+  return count;
+}
+
+
+int CountLeadingSignBits(int64_t value, int width) {
+  ASSERT((width == 32) || (width == 64));
+  if (value >= 0) {
+    return CountLeadingZeros(value, width) - 1;
+  } else {
+    return CountLeadingZeros(~value, width) - 1;
+  }
+}
+
+
+int CountTrailingZeros(uint64_t value, int width) {
+  ASSERT((width == 32) || (width == 64));
+  int count = 0;
+  while ((count < width) && (((value >> count) & 1) == 0)) {
+    count++;
+  }
+  return count;
+}
+
+
+int CountSetBits(uint64_t value, int width) {
+  // TODO: Other widths could be added here, as the implementation already
+  // supports them.
+  ASSERT((width == 32) || (width == 64));
+
+  // Mask out unused bits to ensure that they are not counted.
+  value &= (0xffffffffffffffffUL >> (64-width));
+
+  // Add up the set bits.
+  // The algorithm works by adding pairs of bit fields together iteratively,
+  // where the size of each bit field doubles each time.
+  // An example for an 8-bit value:
+  // Bits:  h  g  f  e  d  c  b  a
+  //         \ |   \ |   \ |   \ |
+  // value = h+g   f+e   d+c   b+a
+  //            \    |      \    |
+  // value =   h+g+f+e     d+c+b+a
+  //                  \          |
+  // value =       h+g+f+e+d+c+b+a
+  value = ((value >> 1) & 0x5555555555555555) + (value & 0x5555555555555555);
+  value = ((value >> 2) & 0x3333333333333333) + (value & 0x3333333333333333);
+  value = ((value >> 4) & 0x0f0f0f0f0f0f0f0f) + (value & 0x0f0f0f0f0f0f0f0f);
+  value = ((value >> 8) & 0x00ff00ff00ff00ff) + (value & 0x00ff00ff00ff00ff);
+  value = ((value >> 16) & 0x0000ffff0000ffff) + (value & 0x0000ffff0000ffff);
+  value = ((value >> 32) & 0x00000000ffffffff) + (value & 0x00000000ffffffff);
+
+  return value;
+}
+}  // namespace vixl
diff --git a/disas/libvixl/src/utils.h b/disas/libvixl/src/utils.h
new file mode 100644
index 0000000..4e0b367
--- /dev/null
+++ b/disas/libvixl/src/utils.h
@@ -0,0 +1,126 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_UTILS_H
+#define VIXL_UTILS_H
+
+
+#include <string.h>
+#include "globals.h"
+
+namespace vixl {
+
+// Check number width.
+inline bool is_intn(unsigned n, int64_t x) {
+  ASSERT((0 < n) && (n < 64));
+  int64_t limit = 1L << (n - 1);
+  return (-limit <= x) && (x < limit);
+}
+
+inline bool is_uintn(unsigned n, int64_t x) {
+  ASSERT((0 < n) && (n < 64));
+  return !(x >> n);
+}
+
+inline unsigned truncate_to_intn(unsigned n, int64_t x) {
+  ASSERT((0 < n) && (n < 64));
+  return (x & ((1L << n) - 1));
+}
+
+#define INT_1_TO_63_LIST(V)                                                    \
+V(1)  V(2)  V(3)  V(4)  V(5)  V(6)  V(7)  V(8)                                 \
+V(9)  V(10) V(11) V(12) V(13) V(14) V(15) V(16)                                \
+V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24)                                \
+V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32)                                \
+V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40)                                \
+V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48)                                \
+V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56)                                \
+V(57) V(58) V(59) V(60) V(61) V(62) V(63)
+
+#define DECLARE_IS_INT_N(N)                                                    \
+inline bool is_int##N(int64_t x) { return is_intn(N, x); }
+#define DECLARE_IS_UINT_N(N)                                                   \
+inline bool is_uint##N(int64_t x) { return is_uintn(N, x); }
+#define DECLARE_TRUNCATE_TO_INT_N(N)                                           \
+inline int truncate_to_int##N(int x) { return truncate_to_intn(N, x); }
+INT_1_TO_63_LIST(DECLARE_IS_INT_N)
+INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
+INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
+#undef DECLARE_IS_INT_N
+#undef DECLARE_IS_UINT_N
+#undef DECLARE_TRUNCATE_TO_INT_N
+
+// Bit field extraction.
+inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
+  return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
+}
+
+inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
+  return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
+}
+
+inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
+  return (x << (31 - msb)) >> (lsb + 31 - msb);
+}
+
+inline int64_t signed_bitextract_64(int msb, int lsb, int64_t x) {
+  return (x << (63 - msb)) >> (lsb + 63 - msb);
+}
+
+// floating point representation
+uint32_t float_to_rawbits(float value);
+uint64_t double_to_rawbits(double value);
+float rawbits_to_float(uint32_t bits);
+double rawbits_to_double(uint64_t bits);
+
+// Bits counting.
+int CountLeadingZeros(uint64_t value, int width);
+int CountLeadingSignBits(int64_t value, int width);
+int CountTrailingZeros(uint64_t value, int width);
+int CountSetBits(uint64_t value, int width);
+
+// Pointer alignment
+// TODO: rename/refactor to make it specific to instructions.
+template<typename T>
+bool IsWordAligned(T pointer) {
+  ASSERT(sizeof(pointer) == sizeof(intptr_t));   // NOLINT(runtime/sizeof)
+  return (reinterpret_cast<intptr_t>(pointer) & 3) == 0;
+}
+
+// Increment a pointer until it has the specified alignment.
+template<class T>
+T AlignUp(T pointer, size_t alignment) {
+  ASSERT(sizeof(pointer) == sizeof(uintptr_t));
+  uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
+  size_t align_step = (alignment - pointer_raw) % alignment;
+  ASSERT((pointer_raw + align_step) % alignment == 0);
+  return reinterpret_cast<T>(pointer_raw + align_step);
+}
+
+
+}  // namespace vixl
+
+#endif  // VIXL_UTILS_H
-- 
1.8.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 4/4] disas: implement host disassembly output for aarch64
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
                   ` (2 preceding siblings ...)
  2013-09-11 13:05 ` [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64 Claudio Fontana
@ 2013-09-11 13:08 ` Claudio Fontana
  2013-09-16  6:53   ` Andreas Färber
  2013-09-11 13:14 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Andreas Färber
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Claudio Fontana @ 2013-09-11 13:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell

use C++ libvixl to implement output, for now only enabled for the host output
disasm, since we don't have the aarch64 target yet.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
---
 configure                   |  6 +++++
 disas.c                     |  2 ++
 disas/Makefile.objs         |  7 ++++++
 disas/aarch64-cxx.cc        | 53 +++++++++++++++++++++++++++++++++++++++++++++
 disas/aarch64.c             | 45 ++++++++++++++++++++++++++++++++++++++
 disas/libvixl/Makefile.objs |  6 +++++
 include/disas/bfd.h         |  1 +
 7 files changed, 120 insertions(+)
 create mode 100644 disas/aarch64-cxx.cc
 create mode 100644 disas/aarch64.c
 create mode 100644 disas/libvixl/Makefile.objs

diff --git a/configure b/configure
index 6b73d99..1a2648a 100755
--- a/configure
+++ b/configure
@@ -4443,6 +4443,12 @@ ldflags=""
 
 for i in $ARCH $TARGET_BASE_ARCH ; do
   case "$i" in
+  aarch64)
+    if test "x${cxx}" != "x"; then
+      echo "CONFIG_AARCH64_DIS=y"  >> $config_target_mak
+      echo "CONFIG_AARCH64_DIS=y"  >> config-all-disas.mak
+    fi
+  ;;
   alpha)
     echo "CONFIG_ALPHA_DIS=y"  >> $config_target_mak
     echo "CONFIG_ALPHA_DIS=y"  >> config-all-disas.mak
diff --git a/disas.c b/disas.c
index 0203ef2..cc20c4a 100644
--- a/disas.c
+++ b/disas.c
@@ -356,6 +356,8 @@ void disas(FILE *out, void *code, unsigned long size)
 #elif defined(_ARCH_PPC)
     s.info.disassembler_options = (char *)"any";
     print_insn = print_insn_ppc;
+#elif defined(__aarch64__)
+    print_insn = print_insn_aarch64;
 #elif defined(__alpha__)
     print_insn = print_insn_alpha;
 #elif defined(__sparc__)
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 3b1e77a..f468c22 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -1,3 +1,10 @@
+ifeq ($(CONFIG_AARCH64_DIS),y)
+libvixldir = $(SRC_PATH)/disas/libvixl/src
+QEMU_CFLAGS += -I$(libvixldir) -Wno-undef
+common-obj-$(CONFIG_AARCH64_DIS) += libvixl/
+common-obj-$(CONFIG_AARCH64_DIS) += aarch64.o aarch64-cxx.o
+endif
+
 common-obj-$(CONFIG_ALPHA_DIS) += alpha.o
 common-obj-$(CONFIG_ARM_DIS) += arm.o
 common-obj-$(CONFIG_CRIS_DIS) += cris.o
diff --git a/disas/aarch64-cxx.cc b/disas/aarch64-cxx.cc
new file mode 100644
index 0000000..524f5ae
--- /dev/null
+++ b/disas/aarch64-cxx.cc
@@ -0,0 +1,53 @@
+/*
+ * Aarch64 disassembly output wrapper to libvixl - C++ part
+ * Copyright (c) 2013 Linaro Limited
+ * Written by Claudio Fontana
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "a64/simulator-a64.h"
+#include "a64/macro-assembler-a64.h"
+
+extern "C" {
+    int vixl_is_initialized(int);
+    int vixl_init(FILE *f);
+    int vixl_decode_insn(uint8_t *bytes);
+}
+
+using namespace vixl;
+
+static Decoder *vixl_decoder = NULL;
+static Disassembler *vixl_disasm = NULL;
+
+int vixl_is_initialized(int unused)
+{
+    return vixl_decoder != NULL;
+}
+
+/* Disassemble Aarch64 bytecode - wrappers */
+int vixl_init(FILE *f) {
+    vixl_decoder = new Decoder();
+    vixl_disasm = new PrintDisassembler(f);
+    vixl_decoder->AppendVisitor(vixl_disasm);
+    return 1;
+}
+
+int vixl_decode_insn(uint8_t *bytes)
+{
+    Instr instr;
+    instr = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24;
+    vixl_decoder->Decode(reinterpret_cast<Instruction*>(&instr));
+    return 1;
+}
diff --git a/disas/aarch64.c b/disas/aarch64.c
new file mode 100644
index 0000000..7e44837
--- /dev/null
+++ b/disas/aarch64.c
@@ -0,0 +1,45 @@
+/*
+ * Aarch64 disassembly output wrapper to libvixl - C part
+ * Copyright (c) 2013 Linaro Limited
+ * Written by Claudio Fontana
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "disas/bfd.h"
+#define INSN_SIZE 4
+
+extern int vixl_is_initialized(int);
+extern int vixl_init(FILE *);
+extern int vixl_decode_insn(uint8_t *);
+
+/* Disassemble Aarch64 bytecode. */
+int print_insn_aarch64(uint64_t addr, disassemble_info *info)
+{
+    uint8_t bytes[INSN_SIZE];
+    int status;
+
+    if (!vixl_is_initialized(0)) {
+        vixl_init(info->stream);
+    }
+
+    status = info->read_memory_func(addr, bytes, INSN_SIZE, info);
+    if (status != 0) {
+        info->memory_error_func(status, addr, info);
+        return -1;
+    }
+
+    vixl_decode_insn(bytes);
+    return INSN_SIZE;
+}
diff --git a/disas/libvixl/Makefile.objs b/disas/libvixl/Makefile.objs
new file mode 100644
index 0000000..43ba29c
--- /dev/null
+++ b/disas/libvixl/Makefile.objs
@@ -0,0 +1,6 @@
+libvixl_OBJS = src/utils.o \
+               src/a64/instructions-a64.o \
+               src/a64/decoder-a64.o \
+               src/a64/disasm-a64.o
+
+common-obj-$(CONFIG_AARCH64_DIS) += $(libvixl_OBJS)
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index 803b6ef..73017da 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -379,6 +379,7 @@ int print_insn_h8300            (bfd_vma, disassemble_info*);
 int print_insn_h8300h           (bfd_vma, disassemble_info*);
 int print_insn_h8300s           (bfd_vma, disassemble_info*);
 int print_insn_h8500            (bfd_vma, disassemble_info*);
+int print_insn_aarch64          (bfd_vma, disassemble_info*);
 int print_insn_alpha            (bfd_vma, disassemble_info*);
 disassembler_ftype arc_get_disassembler (int, int);
 int print_insn_arm              (bfd_vma, disassemble_info*);
-- 
1.8.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
                   ` (3 preceding siblings ...)
  2013-09-11 13:08 ` [Qemu-devel] [RFC 4/4] disas: implement host disassembly output " Claudio Fontana
@ 2013-09-11 13:14 ` Andreas Färber
  2013-09-11 13:29   ` Peter Maydell
  2013-09-11 13:37 ` Peter Maydell
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Andreas Färber @ 2013-09-11 13:14 UTC (permalink / raw)
  To: Claudio Fontana; +Cc: Peter Maydell, qemu-devel

Hi Claudio,

Am 11.09.2013 14:54, schrieb Claudio Fontana:
> 
> This is the aarch64 libvixl support patchset in the current state.
> It provides (limited) support for disassembly output on aarch64.
> Only host disassembly is enabled, since target for aarch64 is not in yet.
> 
> An external objdump solution as exemplified before by R.H. seems preferable
> to me, even if it means giving up the monitor support.
[snip]

That has been committed August 24th, hasn't it?

Regards,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
  2013-09-11 13:14 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Andreas Färber
@ 2013-09-11 13:29   ` Peter Maydell
  0 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-09-11 13:29 UTC (permalink / raw)
  To: Andreas Färber; +Cc: Claudio Fontana, qemu-devel

On 11 September 2013 14:14, Andreas Färber <afaerber@suse.de> wrote:
> Am 11.09.2013 14:54, schrieb Claudio Fontana:
>> This is the aarch64 libvixl support patchset in the current state.
>> It provides (limited) support for disassembly output on aarch64.
>> Only host disassembly is enabled, since target for aarch64 is not in yet.
>>
>> An external objdump solution as exemplified before by R.H. seems preferable
>> to me, even if it means giving up the monitor support.
> [snip]
>
> That has been committed August 24th, hasn't it?

Yes, but at the moment it's only for targets without a
builtin disassembler. If we're going to have it be the
standard setup we use for every target that's one thing.
But otherwise I'd rather aarch64 not be a second class
citizen in this regard.

-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
                   ` (4 preceding siblings ...)
  2013-09-11 13:14 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Andreas Färber
@ 2013-09-11 13:37 ` Peter Maydell
  2013-09-11 14:35 ` [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64 Claudio Fontana
  2013-09-15 16:41 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Rob Landley
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-09-11 13:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Richard Henderson, Claudio Fontana, Andreas Färber, Alexander Graf

On 11 September 2013 13:54, Claudio Fontana <claudio.fontana@huawei.com> wrote:
> This is the aarch64 libvixl support patchset in the current state.
> It provides (limited) support for disassembly output on aarch64.
> Only host disassembly is enabled, since target for aarch64 is not in yet.

Incidentally, people interested in aarch64 might like to know that
the first public beta release of the ARMv8-A ARM ARM is now
available on infocenter:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a/index.html
(needs an account on infocenter, which is a 'just fill in a webform'
sort of process).

-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
                   ` (5 preceding siblings ...)
  2013-09-11 13:37 ` Peter Maydell
@ 2013-09-11 14:35 ` Claudio Fontana
  2013-09-15 16:41 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Rob Landley
  7 siblings, 0 replies; 14+ messages in thread
From: Claudio Fontana @ 2013-09-11 14:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell


this just adds the libvixl source code verbatim from ARM,
including the source code itself (src/), license and readmes.
Examples, the scons build system etc, are excluded.
Not yet bound to QEMU's build system.

Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
---
 disas/libvixl/LICENCE                        |   30 +
 disas/libvixl/README.md                      |  128 ++
 disas/libvixl/doc/changelog.md               |   12 +
 disas/libvixl/doc/supported-instructions.md  | 1133 ++++++++++++++
 disas/libvixl/src/a64/assembler-a64.cc       | 2172 ++++++++++++++++++++++++++
 disas/libvixl/src/a64/assembler-a64.h        | 1784 +++++++++++++++++++++
 disas/libvixl/src/a64/constants-a64.h        | 1104 +++++++++++++
 disas/libvixl/src/a64/cpu-a64.cc             |  148 ++
 disas/libvixl/src/a64/cpu-a64.h              |   56 +
 disas/libvixl/src/a64/debugger-a64.cc        | 1511 ++++++++++++++++++
 disas/libvixl/src/a64/debugger-a64.h         |  188 +++
 disas/libvixl/src/a64/decoder-a64.cc         |  712 +++++++++
 disas/libvixl/src/a64/decoder-a64.h          |  198 +++
 disas/libvixl/src/a64/disasm-a64.cc          | 1678 ++++++++++++++++++++
 disas/libvixl/src/a64/disasm-a64.h           |  109 ++
 disas/libvixl/src/a64/instructions-a64.cc    |  238 +++
 disas/libvixl/src/a64/instructions-a64.h     |  344 ++++
 disas/libvixl/src/a64/instrument-a64.cc      |  638 ++++++++
 disas/libvixl/src/a64/instrument-a64.h       |  108 ++
 disas/libvixl/src/a64/macro-assembler-a64.cc | 1108 +++++++++++++
 disas/libvixl/src/a64/macro-assembler-a64.h  | 1175 ++++++++++++++
 disas/libvixl/src/a64/simulator-a64.cc       | 2077 ++++++++++++++++++++++++
 disas/libvixl/src/a64/simulator-a64.h        |  576 +++++++
 disas/libvixl/src/globals.h                  |   66 +
 disas/libvixl/src/platform.h                 |   43 +
 disas/libvixl/src/utils.cc                   |  120 ++
 disas/libvixl/src/utils.h                    |  126 ++
 27 files changed, 17582 insertions(+)
 create mode 100644 disas/libvixl/LICENCE
 create mode 100644 disas/libvixl/README.md
 create mode 100644 disas/libvixl/doc/changelog.md
 create mode 100644 disas/libvixl/doc/supported-instructions.md
 create mode 100644 disas/libvixl/src/a64/assembler-a64.cc
 create mode 100644 disas/libvixl/src/a64/assembler-a64.h
 create mode 100644 disas/libvixl/src/a64/constants-a64.h
 create mode 100644 disas/libvixl/src/a64/cpu-a64.cc
 create mode 100644 disas/libvixl/src/a64/cpu-a64.h
 create mode 100644 disas/libvixl/src/a64/debugger-a64.cc
 create mode 100644 disas/libvixl/src/a64/debugger-a64.h
 create mode 100644 disas/libvixl/src/a64/decoder-a64.cc
 create mode 100644 disas/libvixl/src/a64/decoder-a64.h
 create mode 100644 disas/libvixl/src/a64/disasm-a64.cc
 create mode 100644 disas/libvixl/src/a64/disasm-a64.h
 create mode 100644 disas/libvixl/src/a64/instructions-a64.cc
 create mode 100644 disas/libvixl/src/a64/instructions-a64.h
 create mode 100644 disas/libvixl/src/a64/instrument-a64.cc
 create mode 100644 disas/libvixl/src/a64/instrument-a64.h
 create mode 100644 disas/libvixl/src/a64/macro-assembler-a64.cc
 create mode 100644 disas/libvixl/src/a64/macro-assembler-a64.h
 create mode 100644 disas/libvixl/src/a64/simulator-a64.cc
 create mode 100644 disas/libvixl/src/a64/simulator-a64.h
 create mode 100644 disas/libvixl/src/globals.h
 create mode 100644 disas/libvixl/src/platform.h
 create mode 100644 disas/libvixl/src/utils.cc
 create mode 100644 disas/libvixl/src/utils.h

diff --git a/disas/libvixl/LICENCE b/disas/libvixl/LICENCE
new file mode 100644
index 0000000..b7e160a
--- /dev/null
+++ b/disas/libvixl/LICENCE
@@ -0,0 +1,30 @@
+LICENCE
+=======
+
+The software in this repository is covered by the following licence.
+
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/disas/libvixl/README.md b/disas/libvixl/README.md
new file mode 100644
index 0000000..e3c3a0a
--- /dev/null
+++ b/disas/libvixl/README.md
@@ -0,0 +1,128 @@
+VIXL: AArch64 Runtime Code Generation Library Version 1.1
+=========================================================
+
+Contents:
+
+ * Requirements
+ * Overview
+ * Known limitations
+ * Usage
+
+
+Requirements
+============
+
+To build VIXL the following software is required:
+
+ 1. Python 2.7
+ 2. SCons 2.0
+ 3. GCC 4.4
+
+A 64-bit host machine is required, implementing an LP64 data model. VIXL has
+only been tested using GCC on Ubuntu systems.
+
+To run the linter stage of the tests, the following software is also required:
+
+ 1. Git
+ 2. [Google's `cpplint.py`][cpplint]
+
+Refer to the 'Usage' section for details.
+
+
+Overview
+========
+
+VIXL is made of three components.
+
+ 1. A programmatic assembler to generate A64 code at runtime. The assembler
+    abstracts some of the constraints of the A64 ISA, for example most
+    instructions support any immediate.
+ 2. A disassembler which can print any instruction emitted by the assembler.
+ 3. A simulator which can simulate any instruction emitted by the assembler.
+    The simulator allows generated code to be run on another architecture
+    without the need for a full ISA model.
+
+The VIXL git repository can be found [on GitHub][vixl]. Changes from previous
+versions of VIXL can be found in the [Changelog](doc/changelog.md).
+
+
+Known Limitations
+=================
+
+VIXL was developed to target JavaScript engines so a number of features from A64
+were deemed unnecessary:
+
+ * No Advanced SIMD support.
+ * Limited rounding mode support for floating point.
+ * No support for synchronisation instructions.
+ * Limited support for system instructions.
+ * A few miscellaneous integer and floating point instructions are missing.
+
+The VIXL simulator supports only those instructions that the VIXL assembler can
+generate. The `doc` directory contains a
+[list of supported instructions](doc/supported-instructions.md).
+
+
+Usage
+=====
+
+
+Running all Tests
+-----------------
+
+The helper script `tools/presubmit.py` will build and run every test that is
+provided with VIXL, in both release and debug mode. It is a useful script for
+verifying that all of VIXL's dependencies are in place and that VIXL is working
+as it should.
+
+By default, the `tools/presubmit.py` script runs a linter to check that the
+source code conforms with the code style guide, and to detect several common
+errors that the compiler may not warn about. This is most useful for VIXL
+developers. The linter has the following dependencies:
+
+ 1. Git must be installed, and the VIXL project must be in a valid Git
+    repository, such as one produced using `git clone`.
+ 2. `cpplint.py`, [as provided by Google][cpplint], must be available (and
+    executable) on the `PATH`. Only revision 104 has been tested with VIXL.
+
+It is possible to tell `tools/presubmit.py` to skip the linter stage by passing
+`--nolint`. This removes the dependency on `cpplint.py` and Git. The `--nolint`
+option is implied if the VIXL project is a snapshot (with no `.git` directory).
+
+
+Building and Running Specific Tests
+-----------------------------------
+
+The helper script `tools/test.py` will build and run all the tests for the
+assembler and disassembler in release mode. Add `--mode=debug` to build and run
+in debug mode. The tests can be built separately using SCons: `scons
+target=cctest`.
+
+
+Building and Running the Benchmarks
+-----------------------------------
+
+There are two very basic benchmarks provided with VIXL:
+
+ 1. bench\_dataop, emitting adds
+ 2. bench\_branch, emitting branches
+
+To build one benchmark: `scons target=bench_xxx`, then run it as
+`./bench_xxx_sim <number of iterations>`. The benchmarks do not report a
+figure; they should be timed using the `time` command.
+
+
+Getting Started
+---------------
+
+A short introduction to using VIXL can be found [here](doc/getting-started.md).
+Example source code is provided in the `examples` directory. Build this using
+`scons target=examples` from the root directory.
+
+
+
+[cpplint]: https://google-styleguide.googlecode.com/svn-history/r104/trunk/cpplint/cpplint.py
+           "Google's cpplint.py script."
+
+[vixl]: https://github.com/armvixl/vixl
+        "The VIXL repository on GitHub."
diff --git a/disas/libvixl/doc/changelog.md b/disas/libvixl/doc/changelog.md
new file mode 100644
index 0000000..8bab932
--- /dev/null
+++ b/disas/libvixl/doc/changelog.md
@@ -0,0 +1,12 @@
+VIXL Change Log
+===============
+
+* 1.1
+    + Improved robustness of instruction decoder and disassembler.
+    + Added support for double-to-float conversions using `fcvt`.
+    + Added support for more fixed-point to floating-point conversions (`ucvtf`
+      and `scvtf`).
+    + Added instruction statistics collection class `instrument-a64.cc`.
+
+* 1.0
+    + Initial release.
diff --git a/disas/libvixl/doc/supported-instructions.md b/disas/libvixl/doc/supported-instructions.md
new file mode 100644
index 0000000..90d63ec
--- /dev/null
+++ b/disas/libvixl/doc/supported-instructions.md
@@ -0,0 +1,1133 @@
+VIXL Supported Instruction List
+===============================
+
+This is a list of the AArch64 instructions supported by the VIXL assembler,
+disassembler and simulator. The simulator may not support all floating point
+operations to the precision required by AArch64 - please check the simulator
+source code for details.
+
+AArch64 integer instructions
+----------------------------
+
+### adc ###
+
+Add with carry bit.
+
+    void adc(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### add ###
+
+Add.
+
+    void add(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### adr ###
+
+Calculate the address of a PC offset.
+
+    void adr(const Register& rd, int imm21)
+
+
+### adr ###
+
+Calculate the address of a label.
+
+    void adr(const Register& rd, Label* label)
+
+
+### asr ###
+
+Arithmetic shift right.
+
+    inline void asr(const Register& rd, const Register& rn, unsigned shift)
+
+
+### asrv ###
+
+Arithmetic shift right by variable.
+
+    void asrv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### b ###
+
+Branch to PC offset.
+
+    void b(int imm26, Condition cond = al)
+
+
+### b ###
+
+Branch to label.
+
+    void b(Label* label, Condition cond = al)
+
+
+### bfi ###
+
+Bitfield insert.
+
+    inline void bfi(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width)
+
+
+### bfm ###
+
+Bitfield move.
+
+    void bfm(const Register& rd,
+             const Register& rn,
+             unsigned immr,
+             unsigned imms)
+
+
+### bfxil ###
+
+Bitfield extract and insert low.
+
+    inline void bfxil(const Register& rd,
+                      const Register& rn,
+                      unsigned lsb,
+                      unsigned width)
+
+
+### bic ###
+
+Bit clear (A & ~B).
+
+    void bic(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### bl ###
+
+Branch with link to PC offset.
+
+    void bl(int imm26)
+
+
+### bl ###
+
+Branch with link to label.
+
+    void bl(Label* label)
+
+
+### blr ###
+
+Branch with link to register.
+
+    void blr(const Register& xn)
+
+
+### br ###
+
+Branch to register.
+
+    void br(const Register& xn)
+
+
+### brk ###
+
+Monitor debug-mode breakpoint.
+
+    void brk(int code)
+
+
+### cbnz ###
+
+Compare and branch to PC offset if not zero.
+
+    void cbnz(const Register& rt, int imm19)
+
+
+### cbnz ###
+
+Compare and branch to label if not zero.
+
+    void cbnz(const Register& rt, Label* label)
+
+
+### cbz ###
+
+Compare and branch to PC offset if zero.
+
+    void cbz(const Register& rt, int imm19)
+
+
+### cbz ###
+
+Compare and branch to label if zero.
+
+    void cbz(const Register& rt, Label* label)
+
+
+### ccmn ###
+
+Conditional compare negative.
+
+    void ccmn(const Register& rn,
+              const Operand& operand,
+              StatusFlags nzcv,
+              Condition cond)
+
+
+### ccmp ###
+
+Conditional compare.
+
+    void ccmp(const Register& rn,
+              const Operand& operand,
+              StatusFlags nzcv,
+              Condition cond)
+
+
+### cinc ###
+
+Conditional increment: rd = cond ? rn + 1 : rn.
+
+    void cinc(const Register& rd, const Register& rn, Condition cond)
+
+
+### cinv ###
+
+Conditional invert: rd = cond ? ~rn : rn.
+
+    void cinv(const Register& rd, const Register& rn, Condition cond)
+
+
+### cls ###
+
+Count leading sign bits.
+
+    void cls(const Register& rd, const Register& rn)
+
+
+### clz ###
+
+Count leading zeroes.
+
+    void clz(const Register& rd, const Register& rn)
+
+
+### cmn ###
+
+Compare negative.
+
+    void cmn(const Register& rn, const Operand& operand)
+
+
+### cmp ###
+
+Compare.
+
+    void cmp(const Register& rn, const Operand& operand)
+
+
+### cneg ###
+
+Conditional negate: rd = cond ? -rn : rn.
+
+    void cneg(const Register& rd, const Register& rn, Condition cond)
+
+
+### csel ###
+
+Conditional select: rd = cond ? rn : rm.
+
+    void csel(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              Condition cond)
+
+
+### cset ###
+
+Conditional set: rd = cond ? 1 : 0.
+
+    void cset(const Register& rd, Condition cond)
+
+
+### csetm ###
+
+Conditional set mask: rd = cond ? -1 : 0.
+
+    void csetm(const Register& rd, Condition cond)
+
+
+### csinc ###
+
+Conditional select increment: rd = cond ? rn : rm + 1.
+
+    void csinc(const Register& rd,
+               const Register& rn,
+               const Register& rm,
+               Condition cond)
+
+
+### csinv ###
+
+Conditional select inversion: rd = cond ? rn : ~rm.
+
+    void csinv(const Register& rd,
+               const Register& rn,
+               const Register& rm,
+               Condition cond)
+
+
+### csneg ###
+
+Conditional select negation: rd = cond ? rn : -rm.
+
+    void csneg(const Register& rd,
+               const Register& rn,
+               const Register& rm,
+               Condition cond)
+
+
+### eon ###
+
+Bitwise enor/xnor (A ^ ~B).
+
+    void eon(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### eor ###
+
+Bitwise eor/xor (A ^ B).
+
+    void eor(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### extr ###
+
+Extract.
+
+    void extr(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              unsigned lsb)
+
+
+### hint ###
+
+System hint.
+
+    void hint(SystemHint code)
+
+
+### hlt ###
+
+Halting debug-mode breakpoint.
+
+    void hlt(int code)
+
+
+### ldnp ###
+
+Load integer or FP register pair, non-temporal.
+
+    void ldnp(const CPURegister& rt, const CPURegister& rt2,
+              const MemOperand& src)
+
+
+### ldp ###
+
+Load integer or FP register pair.
+
+    void ldp(const CPURegister& rt, const CPURegister& rt2,
+             const MemOperand& src)
+
+
+### ldpsw ###
+
+Load word pair with sign extension.
+
+    void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src)
+
+
+### ldr ###
+
+Load integer or FP register.
+
+    void ldr(const CPURegister& rt, const MemOperand& src)
+
+
+### ldr ###
+
+Load literal to FP register.
+
+    void ldr(const FPRegister& ft, double imm)
+
+
+### ldr ###
+
+Load literal to register.
+
+    void ldr(const Register& rt, uint64_t imm)
+
+
+### ldrb ###
+
+Load byte.
+
+    void ldrb(const Register& rt, const MemOperand& src)
+
+
+### ldrh ###
+
+Load half-word.
+
+    void ldrh(const Register& rt, const MemOperand& src)
+
+
+### ldrsb ###
+
+Load byte with sign extension.
+
+    void ldrsb(const Register& rt, const MemOperand& src)
+
+
+### ldrsh ###
+
+Load half-word with sign extension.
+
+    void ldrsh(const Register& rt, const MemOperand& src)
+
+
+### ldrsw ###
+
+Load word with sign extension.
+
+    void ldrsw(const Register& rt, const MemOperand& src)
+
+
+### lsl ###
+
+Logical shift left.
+
+    inline void lsl(const Register& rd, const Register& rn, unsigned shift)
+
+
+### lslv ###
+
+Logical shift left by variable.
+
+    void lslv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### lsr ###
+
+Logical shift right.
+
+    inline void lsr(const Register& rd, const Register& rn, unsigned shift)
+
+
+### lsrv ###
+
+Logical shift right by variable.
+
+    void lsrv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### madd ###
+
+Multiply and accumulate.
+
+    void madd(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra)
+
+
+### mneg ###
+
+Negated multiply.
+
+    void mneg(const Register& rd, const Register& rn, const Register& rm)
+
+
+### mov ###
+
+Move register to register.
+
+    void mov(const Register& rd, const Register& rn)
+
+
+### movk ###
+
+Move immediate and keep.
+
+    void movk(const Register& rd, uint64_t imm, int shift = -1)
+
+
+### movn ###
+
+Move inverted immediate.
+
+    void movn(const Register& rd, uint64_t imm, int shift = -1)
+
+
+### movz ###
+
+Move immediate.
+
+    void movz(const Register& rd, uint64_t imm, int shift = -1)
+
+
+### mrs ###
+
+Move to register from system register.
+
+    void mrs(const Register& rt, SystemRegister sysreg)
+
+
+### msr ###
+
+Move from register to system register.
+
+    void msr(SystemRegister sysreg, const Register& rt)
+
+
+### msub ###
+
+Multiply and subtract.
+
+    void msub(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra)
+
+
+### mul ###
+
+Multiply.
+
+    void mul(const Register& rd, const Register& rn, const Register& rm)
+
+
+### mvn ###
+
+Move inverted operand to register.
+
+    void mvn(const Register& rd, const Operand& operand)
+
+
+### neg ###
+
+Negate.
+
+    void neg(const Register& rd,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### ngc ###
+
+Negate with carry bit.
+
+    void ngc(const Register& rd,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### nop ###
+
+No-op.
+
+    void nop()
+
+
+### orn ###
+
+Bitwise nor (A | ~B).
+
+    void orn(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### orr ###
+
+Bitwise or (A | B).
+
+    void orr(const Register& rd, const Register& rn, const Operand& operand)
+
+
+### rbit ###
+
+Bit reverse.
+
+    void rbit(const Register& rd, const Register& rn)
+
+
+### ret ###
+
+Branch to register with return hint.
+
+    void ret(const Register& xn = lr)
+
+
+### rev ###
+
+Reverse bytes.
+
+    void rev(const Register& rd, const Register& rn)
+
+
+### rev16 ###
+
+Reverse bytes in 16-bit half words.
+
+    void rev16(const Register& rd, const Register& rn)
+
+
+### rev32 ###
+
+Reverse bytes in 32-bit words.
+
+    void rev32(const Register& rd, const Register& rn)
+
+
+### ror ###
+
+Rotate right.
+
+    inline void ror(const Register& rd, const Register& rs, unsigned shift)
+
+
+### rorv ###
+
+Rotate right by variable.
+
+    void rorv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### sbc ###
+
+Subtract with carry bit.
+
+    void sbc(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### sbfiz ###
+
+Signed bitfield insert with zero at right.
+
+    inline void sbfiz(const Register& rd,
+                      const Register& rn,
+                      unsigned lsb,
+                      unsigned width)
+
+
+### sbfm ###
+
+Signed bitfield move.
+
+    void sbfm(const Register& rd,
+              const Register& rn,
+              unsigned immr,
+              unsigned imms)
+
+
+### sbfx ###
+
+Signed bitfield extract.
+
+    inline void sbfx(const Register& rd,
+                     const Register& rn,
+                     unsigned lsb,
+                     unsigned width)
+
+
+### scvtf ###
+
+Convert signed integer or fixed point to FP.
+
+    void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0)
+
+
+### sdiv ###
+
+Signed integer divide.
+
+    void sdiv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### smaddl ###
+
+Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+
+    void smaddl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### smsubl ###
+
+Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+
+    void smsubl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### smulh ###
+
+Signed multiply high: 64 x 64 -> 64-bit <127:64>.
+
+    void smulh(const Register& xd, const Register& xn, const Register& xm)
+
+
+### smull ###
+
+Signed long multiply: 32 x 32 -> 64-bit.
+
+    void smull(const Register& rd, const Register& rn, const Register& rm)
+
+
+### stnp ###
+
+Store integer or FP register pair, non-temporal.
+
+    void stnp(const CPURegister& rt, const CPURegister& rt2,
+              const MemOperand& dst)
+
+
+### stp ###
+
+Store integer or FP register pair.
+
+    void stp(const CPURegister& rt, const CPURegister& rt2,
+             const MemOperand& dst)
+
+
+### str ###
+
+Store integer or FP register.
+
+    void str(const CPURegister& rt, const MemOperand& dst)
+
+
+### strb ###
+
+Store byte.
+
+    void strb(const Register& rt, const MemOperand& dst)
+
+
+### strh ###
+
+Store half-word.
+
+    void strh(const Register& rt, const MemOperand& dst)
+
+
+### sub ###
+
+Subtract.
+
+    void sub(const Register& rd,
+             const Register& rn,
+             const Operand& operand,
+             FlagsUpdate S = LeaveFlags)
+
+
+### sxtb ###
+
+Signed extend byte.
+
+    inline void sxtb(const Register& rd, const Register& rn)
+
+
+### sxth ###
+
+Signed extend halfword.
+
+    inline void sxth(const Register& rd, const Register& rn)
+
+
+### sxtw ###
+
+Signed extend word.
+
+    inline void sxtw(const Register& rd, const Register& rn)
+
+
+### tbnz ###
+
+Test bit and branch to PC offset if not zero.
+
+    void tbnz(const Register& rt, unsigned bit_pos, int imm14)
+
+
+### tbnz ###
+
+Test bit and branch to label if not zero.
+
+    void tbnz(const Register& rt, unsigned bit_pos, Label* label)
+
+
+### tbz ###
+
+Test bit and branch to PC offset if zero.
+
+    void tbz(const Register& rt, unsigned bit_pos, int imm14)
+
+
+### tbz ###
+
+Test bit and branch to label if zero.
+
+    void tbz(const Register& rt, unsigned bit_pos, Label* label)
+
+
+### tst ###
+
+Bit test and set flags.
+
+    void tst(const Register& rn, const Operand& operand)
+
+
+### ubfiz ###
+
+Unsigned bitfield insert with zero at right.
+
+    inline void ubfiz(const Register& rd,
+                      const Register& rn,
+                      unsigned lsb,
+                      unsigned width)
+
+
+### ubfm ###
+
+Unsigned bitfield move.
+
+    void ubfm(const Register& rd,
+              const Register& rn,
+              unsigned immr,
+              unsigned imms)
+
+
+### ubfx ###
+
+Unsigned bitfield extract.
+
+    inline void ubfx(const Register& rd,
+                     const Register& rn,
+                     unsigned lsb,
+                     unsigned width)
+
+
+### ucvtf ###
+
+Convert unsigned integer or fixed point to FP.
+
+    void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0)
+
+
+### udiv ###
+
+Unsigned integer divide.
+
+    void udiv(const Register& rd, const Register& rn, const Register& rm)
+
+
+### umaddl ###
+
+Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+
+    void umaddl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### umsubl ###
+
+Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+
+    void umsubl(const Register& rd,
+                const Register& rn,
+                const Register& rm,
+                const Register& ra)
+
+
+### uxtb ###
+
+Unsigned extend byte.
+
+    inline void uxtb(const Register& rd, const Register& rn)
+
+
+### uxth ###
+
+Unsigned extend halfword.
+
+    inline void uxth(const Register& rd, const Register& rn)
+
+
+### uxtw ###
+
+Unsigned extend word.
+
+    inline void uxtw(const Register& rd, const Register& rn)
+
+
+
+AArch64 floating point instructions
+-----------------------------------
+
+### fabs ###
+
+FP absolute.
+
+    void fabs(const FPRegister& fd, const FPRegister& fn)
+
+
+### fadd ###
+
+FP add.
+
+    void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fccmp ###
+
+FP conditional compare.
+
+    void fccmp(const FPRegister& fn,
+               const FPRegister& fm,
+               StatusFlags nzcv,
+               Condition cond)
+
+
+### fcmp ###
+
+FP compare immediate.
+
+    void fcmp(const FPRegister& fn, double value)
+
+
+### fcmp ###
+
+FP compare registers.
+
+    void fcmp(const FPRegister& fn, const FPRegister& fm)
+
+
+### fcsel ###
+
+FP conditional select.
+
+    void fcsel(const FPRegister& fd,
+               const FPRegister& fn,
+               const FPRegister& fm,
+               Condition cond)
+
+
+### fcvt ###
+
+FP convert single to double precision.
+
+    void fcvt(const FPRegister& fd, const FPRegister& fn)
+
+
+### fcvtms ###
+
+Convert FP to signed integer (round towards -infinity).
+
+    void fcvtms(const Register& rd, const FPRegister& fn)
+
+
+### fcvtmu ###
+
+Convert FP to unsigned integer (round towards -infinity).
+
+    void fcvtmu(const Register& rd, const FPRegister& fn)
+
+
+### fcvtns ###
+
+Convert FP to signed integer (nearest with ties to even).
+
+    void fcvtns(const Register& rd, const FPRegister& fn)
+
+
+### fcvtnu ###
+
+Convert FP to unsigned integer (nearest with ties to even).
+
+    void fcvtnu(const Register& rd, const FPRegister& fn)
+
+
+### fcvtzs ###
+
+Convert FP to signed integer (round towards zero).
+
+    void fcvtzs(const Register& rd, const FPRegister& fn)
+
+
+### fcvtzu ###
+
+Convert FP to unsigned integer (round towards zero).
+
+    void fcvtzu(const Register& rd, const FPRegister& fn)
+
+
+### fdiv ###
+
+FP divide.
+
+    void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fmax ###
+
+FP maximum.
+
+    void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fmin ###
+
+FP minimum.
+
+    void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fmov ###
+
+Move FP register to FP register.
+
+    void fmov(FPRegister fd, FPRegister fn)
+
+
+### fmov ###
+
+Move FP register to register.
+
+    void fmov(Register rd, FPRegister fn)
+
+
+### fmov ###
+
+Move immediate to FP register.
+
+    void fmov(FPRegister fd, double imm)
+
+
+### fmov ###
+
+Move register to FP register.
+
+    void fmov(FPRegister fd, Register rn)
+
+
+### fmsub ###
+
+FP multiply and subtract.
+
+    void fmsub(const FPRegister& fd,
+               const FPRegister& fn,
+               const FPRegister& fm,
+               const FPRegister& fa)
+
+
+### fmul ###
+
+FP multiply.
+
+    void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+### fneg ###
+
+FP negate.
+
+    void fneg(const FPRegister& fd, const FPRegister& fn)
+
+
+### frintn ###
+
+FP round to integer (nearest with ties to even).
+
+    void frintn(const FPRegister& fd, const FPRegister& fn)
+
+
+### frintz ###
+
+FP round to integer (towards zero).
+
+    void frintz(const FPRegister& fd, const FPRegister& fn)
+
+
+### fsqrt ###
+
+FP square root.
+
+    void fsqrt(const FPRegister& fd, const FPRegister& fn)
+
+
+### fsub ###
+
+FP subtract.
+
+    void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm)
+
+
+
+Additional or pseudo instructions
+---------------------------------
+
+### bind ###
+
+Bind a label to the current PC.
+
+    void bind(Label* label)
+
+
+### dc32 ###
+
+Emit 32 bits of data into the instruction stream.
+
+    inline void dc32(uint32_t data)
+
+
+### dc64 ###
+
+Emit 64 bits of data into the instruction stream.
+
+    inline void dc64(uint64_t data)
+
+
+### dci ###
+
+Emit raw instructions into the instruction stream.
+
+    inline void dci(Instr raw_inst)
+
+
+### debug ###
+
+Debug control pseudo instruction, only supported by the debugger.
+
+    void debug(const char* message, uint32_t code, Instr params = BREAK)
+
+
+
diff --git a/disas/libvixl/src/a64/assembler-a64.cc b/disas/libvixl/src/a64/assembler-a64.cc
new file mode 100644
index 0000000..89f7406
--- /dev/null
+++ b/disas/libvixl/src/a64/assembler-a64.cc
@@ -0,0 +1,2172 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#include <cmath>
+#include "a64/assembler-a64.h"
+
+namespace vixl {
+
+// CPURegList utilities.
+CPURegister CPURegList::PopLowestIndex() {
+  if (IsEmpty()) {
+    return NoCPUReg;
+  }
+  int index = CountTrailingZeros(list_, kRegListSizeInBits);
+  ASSERT((1 << index) & list_);
+  Remove(index);
+  return CPURegister(index, size_, type_);
+}
+
+
+CPURegister CPURegList::PopHighestIndex() {
+  ASSERT(IsValid());
+  if (IsEmpty()) {
+    return NoCPUReg;
+  }
+  int index = CountLeadingZeros(list_, kRegListSizeInBits);
+  index = kRegListSizeInBits - 1 - index;
+  ASSERT((1 << index) & list_);
+  Remove(index);
+  return CPURegister(index, size_, type_);
+}
+
+
+bool CPURegList::IsValid() const {
+  if ((type_ == CPURegister::kRegister) ||
+      (type_ == CPURegister::kFPRegister)) {
+    bool is_valid = true;
+    // Try to create a CPURegister for each element in the list.
+    for (int i = 0; i < kRegListSizeInBits; i++) {
+      if (((list_ >> i) & 1) != 0) {
+        is_valid &= CPURegister(i, size_, type_).IsValid();
+      }
+    }
+    return is_valid;
+  } else if (type_ == CPURegister::kNoRegister) {
+    // We can't use IsEmpty here because that asserts IsValid().
+    return list_ == 0;
+  } else {
+    return false;
+  }
+}
+
+
+void CPURegList::RemoveCalleeSaved() {
+  if (type() == CPURegister::kRegister) {
+    Remove(GetCalleeSaved(RegisterSizeInBits()));
+  } else if (type() == CPURegister::kFPRegister) {
+    Remove(GetCalleeSavedFP(RegisterSizeInBits()));
+  } else {
+    ASSERT(type() == CPURegister::kNoRegister);
+    ASSERT(IsEmpty());
+    // The list must already be empty, so do nothing.
+  }
+}
+
+
+CPURegList CPURegList::GetCalleeSaved(unsigned size) {
+  return CPURegList(CPURegister::kRegister, size, 19, 29);
+}
+
+
+CPURegList CPURegList::GetCalleeSavedFP(unsigned size) {
+  return CPURegList(CPURegister::kFPRegister, size, 8, 15);
+}
+
+
+CPURegList CPURegList::GetCallerSaved(unsigned size) {
+  // Registers x0-x18 and lr (x30) are caller-saved.
+  CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18);
+  list.Combine(lr);
+  return list;
+}
+
+
+CPURegList CPURegList::GetCallerSavedFP(unsigned size) {
+  // Registers d0-d7 and d16-d31 are caller-saved.
+  CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7);
+  list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31));
+  return list;
+}
+
+
+const CPURegList kCalleeSaved = CPURegList::GetCalleeSaved();
+const CPURegList kCalleeSavedFP = CPURegList::GetCalleeSavedFP();
+const CPURegList kCallerSaved = CPURegList::GetCallerSaved();
+const CPURegList kCallerSavedFP = CPURegList::GetCallerSavedFP();
+
+
+// Registers.
+#define WREG(n) w##n,
+const Register Register::wregisters[] = {
+REGISTER_CODE_LIST(WREG)
+};
+#undef WREG
+
+#define XREG(n) x##n,
+const Register Register::xregisters[] = {
+REGISTER_CODE_LIST(XREG)
+};
+#undef XREG
+
+#define SREG(n) s##n,
+const FPRegister FPRegister::sregisters[] = {
+REGISTER_CODE_LIST(SREG)
+};
+#undef SREG
+
+#define DREG(n) d##n,
+const FPRegister FPRegister::dregisters[] = {
+REGISTER_CODE_LIST(DREG)
+};
+#undef DREG
+
+
+const Register& Register::WRegFromCode(unsigned code) {
+  // This function returns the zero register when code = 31. The stack pointer
+  // can not be returned.
+  ASSERT(code < kNumberOfRegisters);
+  return wregisters[code];
+}
+
+
+const Register& Register::XRegFromCode(unsigned code) {
+  // This function returns the zero register when code = 31. The stack pointer
+  // can not be returned.
+  ASSERT(code < kNumberOfRegisters);
+  return xregisters[code];
+}
+
+
+const FPRegister& FPRegister::SRegFromCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return sregisters[code];
+}
+
+
+const FPRegister& FPRegister::DRegFromCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return dregisters[code];
+}
+
+
+const Register& CPURegister::W() const {
+  ASSERT(IsValidRegister());
+  ASSERT(Is64Bits());
+  return Register::WRegFromCode(code_);
+}
+
+
+const Register& CPURegister::X() const {
+  ASSERT(IsValidRegister());
+  ASSERT(Is32Bits());
+  return Register::XRegFromCode(code_);
+}
+
+
+const FPRegister& CPURegister::S() const {
+  ASSERT(IsValidFPRegister());
+  ASSERT(Is64Bits());
+  return FPRegister::SRegFromCode(code_);
+}
+
+
+const FPRegister& CPURegister::D() const {
+  ASSERT(IsValidFPRegister());
+  ASSERT(Is32Bits());
+  return FPRegister::DRegFromCode(code_);
+}
+
+
+// Operand.
+Operand::Operand(int64_t immediate)
+    : immediate_(immediate),
+      reg_(NoReg),
+      shift_(NO_SHIFT),
+      extend_(NO_EXTEND),
+      shift_amount_(0) {}
+
+
+Operand::Operand(Register reg, Shift shift, unsigned shift_amount)
+    : reg_(reg),
+      shift_(shift),
+      extend_(NO_EXTEND),
+      shift_amount_(shift_amount) {
+  ASSERT(reg.Is64Bits() || (shift_amount < kWRegSize));
+  ASSERT(reg.Is32Bits() || (shift_amount < kXRegSize));
+  ASSERT(!reg.IsSP());
+}
+
+
+Operand::Operand(Register reg, Extend extend, unsigned shift_amount)
+    : reg_(reg),
+      shift_(NO_SHIFT),
+      extend_(extend),
+      shift_amount_(shift_amount) {
+  ASSERT(reg.IsValid());
+  ASSERT(shift_amount <= 4);
+  ASSERT(!reg.IsSP());
+}
+
+
+bool Operand::IsImmediate() const {
+  return reg_.Is(NoReg);
+}
+
+
+bool Operand::IsShiftedRegister() const {
+  return reg_.IsValid() && (shift_ != NO_SHIFT);
+}
+
+
+bool Operand::IsExtendedRegister() const {
+  return reg_.IsValid() && (extend_ != NO_EXTEND);
+}
+
+
+Operand Operand::ToExtendedRegister() const {
+  ASSERT(IsShiftedRegister());
+  ASSERT((shift_ == LSL) && (shift_amount_ <= 4));
+  return Operand(reg_, reg_.Is64Bits() ? UXTX : UXTW, shift_amount_);
+}
+
+
+// MemOperand
+MemOperand::MemOperand(Register base, ptrdiff_t offset, AddrMode addrmode)
+  : base_(base), regoffset_(NoReg), offset_(offset), addrmode_(addrmode) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+}
+
+
+MemOperand::MemOperand(Register base,
+                       Register regoffset,
+                       Extend extend,
+                       unsigned shift_amount)
+  : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset),
+    shift_(NO_SHIFT), extend_(extend), shift_amount_(shift_amount) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+  ASSERT(!regoffset.IsSP());
+  ASSERT((extend == UXTW) || (extend == SXTW) || (extend == SXTX));
+}
+
+
+MemOperand::MemOperand(Register base,
+                       Register regoffset,
+                       Shift shift,
+                       unsigned shift_amount)
+  : base_(base), regoffset_(regoffset), offset_(0), addrmode_(Offset),
+    shift_(shift), extend_(NO_EXTEND), shift_amount_(shift_amount) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+  ASSERT(!regoffset.IsSP());
+  ASSERT(shift == LSL);
+}
+
+
+MemOperand::MemOperand(Register base, const Operand& offset, AddrMode addrmode)
+  : base_(base), regoffset_(NoReg), addrmode_(addrmode) {
+  ASSERT(base.Is64Bits() && !base.IsZero());
+
+  if (offset.IsImmediate()) {
+    offset_ = offset.immediate();
+  } else if (offset.IsShiftedRegister()) {
+    ASSERT(addrmode == Offset);
+
+    regoffset_ = offset.reg();
+    shift_= offset.shift();
+    shift_amount_ = offset.shift_amount();
+
+    extend_ = NO_EXTEND;
+    offset_ = 0;
+
+    // These assertions match those in the shifted-register constructor.
+    ASSERT(!regoffset_.IsSP());
+    ASSERT(shift_ == LSL);
+  } else {
+    ASSERT(offset.IsExtendedRegister());
+    ASSERT(addrmode == Offset);
+
+    regoffset_ = offset.reg();
+    extend_ = offset.extend();
+    shift_amount_ = offset.shift_amount();
+
+    shift_= NO_SHIFT;
+    offset_ = 0;
+
+    // These assertions match those in the extended-register constructor.
+    ASSERT(!regoffset_.IsSP());
+    ASSERT((extend_ == UXTW) || (extend_ == SXTW) || (extend_ == SXTX));
+  }
+}
+
+
+bool MemOperand::IsImmediateOffset() const {
+  return (addrmode_ == Offset) && regoffset_.Is(NoReg);
+}
+
+
+bool MemOperand::IsRegisterOffset() const {
+  return (addrmode_ == Offset) && !regoffset_.Is(NoReg);
+}
+
+
+bool MemOperand::IsPreIndex() const {
+  return addrmode_ == PreIndex;
+}
+
+
+bool MemOperand::IsPostIndex() const {
+  return addrmode_ == PostIndex;
+}
+
+
+// Assembler
+Assembler::Assembler(byte* buffer, unsigned buffer_size)
+    : buffer_size_(buffer_size), literal_pool_monitor_(0) {
+  // Assert that this is an LP64 system.
+  ASSERT(sizeof(int) == sizeof(int32_t));     // NOLINT(runtime/sizeof)
+  ASSERT(sizeof(long) == sizeof(int64_t));    // NOLINT(runtime/int)
+  ASSERT(sizeof(void *) == sizeof(int64_t));  // NOLINT(runtime/sizeof)
+  ASSERT(sizeof(1) == sizeof(int32_t));       // NOLINT(runtime/sizeof)
+  ASSERT(sizeof(1L) == sizeof(int64_t));      // NOLINT(runtime/sizeof)
+
+  buffer_ = reinterpret_cast<Instruction*>(buffer);
+  pc_ = buffer_;
+  Reset();
+}
+
+
+Assembler::~Assembler() {
+  ASSERT(finalized_ || (pc_ == buffer_));
+  ASSERT(literals_.empty());
+}
+
+
+void Assembler::Reset() {
+#ifdef DEBUG
+  ASSERT((pc_ >= buffer_) && (pc_ < buffer_ + buffer_size_));
+  ASSERT(literal_pool_monitor_ == 0);
+  memset(buffer_, 0, pc_ - buffer_);
+  finalized_ = false;
+#endif
+  pc_ = buffer_;
+  literals_.clear();
+  next_literal_pool_check_ = pc_ + kLiteralPoolCheckInterval;
+}
+
+
+void Assembler::FinalizeCode() {
+  EmitLiteralPool();
+#ifdef DEBUG
+  finalized_ = true;
+#endif
+}
+
+
+void Assembler::bind(Label* label) {
+  label->is_bound_ = true;
+  label->target_ = pc_;
+  while (label->IsLinked()) {
+    // Get the address of the following instruction in the chain.
+    Instruction* next_link = label->link_->ImmPCOffsetTarget();
+    // Update the instruction target.
+    label->link_->SetImmPCOffsetTarget(label->target_);
+    // Update the label's link.
+    // If the offset of the branch we just updated was 0 (kEndOfChain) we are
+    // done.
+    label->link_ = (label->link_ != next_link) ? next_link : NULL;
+  }
+}
+
+
+int Assembler::UpdateAndGetByteOffsetTo(Label* label) {
+  int offset;
+  ASSERT(sizeof(*pc_) == 1);
+  if (label->IsBound()) {
+    offset = label->target() - pc_;
+  } else if (label->IsLinked()) {
+    offset = label->link() - pc_;
+  } else {
+    offset = Label::kEndOfChain;
+  }
+  label->set_link(pc_);
+  return offset;
+}
+
+
+// Code generation.
+void Assembler::br(const Register& xn) {
+  ASSERT(xn.Is64Bits());
+  Emit(BR | Rn(xn));
+}
+
+
+void Assembler::blr(const Register& xn) {
+  ASSERT(xn.Is64Bits());
+  Emit(BLR | Rn(xn));
+}
+
+
+void Assembler::ret(const Register& xn) {
+  ASSERT(xn.Is64Bits());
+  Emit(RET | Rn(xn));
+}
+
+
+void Assembler::b(int imm26) {
+  Emit(B | ImmUncondBranch(imm26));
+}
+
+
+void Assembler::b(int imm19, Condition cond) {
+  Emit(B_cond | ImmCondBranch(imm19) | cond);
+}
+
+
+void Assembler::b(Label* label) {
+  b(UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::b(Label* label, Condition cond) {
+  b(UpdateAndGetInstructionOffsetTo(label), cond);
+}
+
+
+void Assembler::bl(int imm26) {
+  Emit(BL | ImmUncondBranch(imm26));
+}
+
+
+void Assembler::bl(Label* label) {
+  bl(UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::cbz(const Register& rt,
+                    int imm19) {
+  Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
+}
+
+
+void Assembler::cbz(const Register& rt,
+                    Label* label) {
+  cbz(rt, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::cbnz(const Register& rt,
+                     int imm19) {
+  Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
+}
+
+
+void Assembler::cbnz(const Register& rt,
+                     Label* label) {
+  cbnz(rt, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::tbz(const Register& rt,
+                    unsigned bit_pos,
+                    int imm14) {
+  ASSERT(rt.Is64Bits());
+  Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
+}
+
+
+void Assembler::tbz(const Register& rt,
+                    unsigned bit_pos,
+                    Label* label) {
+  tbz(rt, bit_pos, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::tbnz(const Register& rt,
+                     unsigned bit_pos,
+                     int imm14) {
+  ASSERT(rt.Is64Bits());
+  Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
+}
+
+
+void Assembler::tbnz(const Register& rt,
+                     unsigned bit_pos,
+                     Label* label) {
+  tbnz(rt, bit_pos, UpdateAndGetInstructionOffsetTo(label));
+}
+
+
+void Assembler::adr(const Register& rd, int imm21) {
+  ASSERT(rd.Is64Bits());
+  Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd));
+}
+
+
+void Assembler::adr(const Register& rd, Label* label) {
+  adr(rd, UpdateAndGetByteOffsetTo(label));
+}
+
+
+void Assembler::add(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSub(rd, rn, operand, S, ADD);
+}
+
+
+void Assembler::cmn(const Register& rn,
+                    const Operand& operand) {
+  Register zr = AppropriateZeroRegFor(rn);
+  add(zr, rn, operand, SetFlags);
+}
+
+
+void Assembler::sub(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSub(rd, rn, operand, S, SUB);
+}
+
+
+void Assembler::cmp(const Register& rn, const Operand& operand) {
+  Register zr = AppropriateZeroRegFor(rn);
+  sub(zr, rn, operand, SetFlags);
+}
+
+
+void Assembler::neg(const Register& rd, const Operand& operand, FlagsUpdate S) {
+  Register zr = AppropriateZeroRegFor(rd);
+  sub(rd, zr, operand, S);
+}
+
+
+void Assembler::adc(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSubWithCarry(rd, rn, operand, S, ADC);
+}
+
+
+void Assembler::sbc(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  AddSubWithCarry(rd, rn, operand, S, SBC);
+}
+
+
+void Assembler::ngc(const Register& rd, const Operand& operand, FlagsUpdate S) {
+  Register zr = AppropriateZeroRegFor(rd);
+  sbc(rd, zr, operand, S);
+}
+
+
+// Logical instructions.
+void Assembler::and_(const Register& rd,
+                     const Register& rn,
+                     const Operand& operand,
+                     FlagsUpdate S) {
+  Logical(rd, rn, operand, (S == SetFlags) ? ANDS : AND);
+}
+
+
+void Assembler::tst(const Register& rn,
+                    const Operand& operand) {
+  and_(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void Assembler::bic(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    FlagsUpdate S) {
+  Logical(rd, rn, operand, (S == SetFlags) ? BICS : BIC);
+}
+
+
+void Assembler::orr(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, ORR);
+}
+
+
+void Assembler::orn(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, ORN);
+}
+
+
+void Assembler::eor(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, EOR);
+}
+
+
+void Assembler::eon(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand) {
+  Logical(rd, rn, operand, EON);
+}
+
+
+void Assembler::lslv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::lsrv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::asrv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::rorv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+// Bitfield operations.
+void Assembler::bfm(const Register& rd,
+                     const Register& rn,
+                     unsigned immr,
+                     unsigned imms) {
+  ASSERT(rd.size() == rn.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | BFM | N |
+       ImmR(immr, rd.size()) | ImmS(imms, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::sbfm(const Register& rd,
+                     const Register& rn,
+                     unsigned immr,
+                     unsigned imms) {
+  ASSERT(rd.size() == rn.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | SBFM | N |
+       ImmR(immr, rd.size()) | ImmS(imms, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::ubfm(const Register& rd,
+                     const Register& rn,
+                     unsigned immr,
+                     unsigned imms) {
+  ASSERT(rd.size() == rn.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | UBFM | N |
+       ImmR(immr, rd.size()) | ImmS(imms, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::extr(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     unsigned lsb) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset);
+  Emit(SF(rd) | EXTR | N | Rm(rm) | ImmS(lsb, rd.size()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::csel(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSEL);
+}
+
+
+void Assembler::csinc(const Register& rd,
+                      const Register& rn,
+                      const Register& rm,
+                      Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSINC);
+}
+
+
+void Assembler::csinv(const Register& rd,
+                      const Register& rn,
+                      const Register& rm,
+                      Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSINV);
+}
+
+
+void Assembler::csneg(const Register& rd,
+                      const Register& rn,
+                      const Register& rm,
+                      Condition cond) {
+  ConditionalSelect(rd, rn, rm, cond, CSNEG);
+}
+
+
+void Assembler::cset(const Register &rd, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  Register zr = AppropriateZeroRegFor(rd);
+  csinc(rd, zr, zr, InvertCondition(cond));
+}
+
+
+void Assembler::csetm(const Register &rd, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  Register zr = AppropriateZeroRegFor(rd);
+  csinv(rd, zr, zr, InvertCondition(cond));
+}
+
+
+void Assembler::cinc(const Register &rd, const Register &rn, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  csinc(rd, rn, rn, InvertCondition(cond));
+}
+
+
+void Assembler::cinv(const Register &rd, const Register &rn, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  csinv(rd, rn, rn, InvertCondition(cond));
+}
+
+
+void Assembler::cneg(const Register &rd, const Register &rn, Condition cond) {
+  ASSERT((cond != al) && (cond != nv));
+  csneg(rd, rn, rn, InvertCondition(cond));
+}
+
+
+void Assembler::ConditionalSelect(const Register& rd,
+                                  const Register& rn,
+                                  const Register& rm,
+                                  Condition cond,
+                                  ConditionalSelectOp op) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::ccmn(const Register& rn,
+                     const Operand& operand,
+                     StatusFlags nzcv,
+                     Condition cond) {
+  ConditionalCompare(rn, operand, nzcv, cond, CCMN);
+}
+
+
+void Assembler::ccmp(const Register& rn,
+                     const Operand& operand,
+                     StatusFlags nzcv,
+                     Condition cond) {
+  ConditionalCompare(rn, operand, nzcv, cond, CCMP);
+}
+
+
+void Assembler::DataProcessing3Source(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     const Register& ra,
+                     DataProcessing3SourceOp op) {
+  Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::mul(const Register& rd,
+                    const Register& rn,
+                    const Register& rm) {
+  ASSERT(AreSameSizeAndType(rd, rn, rm));
+  DataProcessing3Source(rd, rn, rm, AppropriateZeroRegFor(rd), MADD);
+}
+
+
+void Assembler::madd(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     const Register& ra) {
+  DataProcessing3Source(rd, rn, rm, ra, MADD);
+}
+
+
+void Assembler::mneg(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(AreSameSizeAndType(rd, rn, rm));
+  DataProcessing3Source(rd, rn, rm, AppropriateZeroRegFor(rd), MSUB);
+}
+
+
+void Assembler::msub(const Register& rd,
+                     const Register& rn,
+                     const Register& rm,
+                     const Register& ra) {
+  DataProcessing3Source(rd, rn, rm, ra, MSUB);
+}
+
+
+void Assembler::umaddl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, UMADDL_x);
+}
+
+
+void Assembler::smaddl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, SMADDL_x);
+}
+
+
+void Assembler::umsubl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x);
+}
+
+
+void Assembler::smsubl(const Register& rd,
+                       const Register& rn,
+                       const Register& rm,
+                       const Register& ra) {
+  ASSERT(rd.Is64Bits() && ra.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x);
+}
+
+
+void Assembler::smull(const Register& rd,
+                      const Register& rn,
+                      const Register& rm) {
+  ASSERT(rd.Is64Bits());
+  ASSERT(rn.Is32Bits() && rm.Is32Bits());
+  DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x);
+}
+
+
+void Assembler::sdiv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::smulh(const Register& xd,
+                      const Register& xn,
+                      const Register& xm) {
+  ASSERT(xd.Is64Bits() && xn.Is64Bits() && xm.Is64Bits());
+  DataProcessing3Source(xd, xn, xm, xzr, SMULH_x);
+}
+
+void Assembler::udiv(const Register& rd,
+                     const Register& rn,
+                     const Register& rm) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == rm.size());
+  Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::rbit(const Register& rd,
+                     const Register& rn) {
+  DataProcessing1Source(rd, rn, RBIT);
+}
+
+
+void Assembler::rev16(const Register& rd,
+                      const Register& rn) {
+  DataProcessing1Source(rd, rn, REV16);
+}
+
+
+void Assembler::rev32(const Register& rd,
+                      const Register& rn) {
+  ASSERT(rd.Is64Bits());
+  DataProcessing1Source(rd, rn, REV);
+}
+
+
+void Assembler::rev(const Register& rd,
+                    const Register& rn) {
+  DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w);
+}
+
+
+void Assembler::clz(const Register& rd,
+                    const Register& rn) {
+  DataProcessing1Source(rd, rn, CLZ);
+}
+
+
+void Assembler::cls(const Register& rd,
+                    const Register& rn) {
+  DataProcessing1Source(rd, rn, CLS);
+}
+
+
+void Assembler::ldp(const CPURegister& rt,
+                    const CPURegister& rt2,
+                    const MemOperand& src) {
+  LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2));
+}
+
+
+void Assembler::stp(const CPURegister& rt,
+                    const CPURegister& rt2,
+                    const MemOperand& dst) {
+  LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2));
+}
+
+
+void Assembler::ldpsw(const Register& rt,
+                      const Register& rt2,
+                      const MemOperand& src) {
+  ASSERT(rt.Is64Bits());
+  LoadStorePair(rt, rt2, src, LDPSW_x);
+}
+
+
+void Assembler::LoadStorePair(const CPURegister& rt,
+                              const CPURegister& rt2,
+                              const MemOperand& addr,
+                              LoadStorePairOp op) {
+  // 'rt' and 'rt2' can only be aliased for stores.
+  ASSERT(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2));
+  ASSERT(AreSameSizeAndType(rt, rt2));
+
+  Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
+                ImmLSPair(addr.offset(), CalcLSPairDataSize(op));
+
+  Instr addrmodeop;
+  if (addr.IsImmediateOffset()) {
+    addrmodeop = LoadStorePairOffsetFixed;
+  } else {
+    ASSERT(addr.offset() != 0);
+    if (addr.IsPreIndex()) {
+      addrmodeop = LoadStorePairPreIndexFixed;
+    } else {
+      ASSERT(addr.IsPostIndex());
+      addrmodeop = LoadStorePairPostIndexFixed;
+    }
+  }
+  Emit(addrmodeop | memop);
+}
+
+
+void Assembler::ldnp(const CPURegister& rt,
+                     const CPURegister& rt2,
+                     const MemOperand& src) {
+  LoadStorePairNonTemporal(rt, rt2, src,
+                           LoadPairNonTemporalOpFor(rt, rt2));
+}
+
+
+void Assembler::stnp(const CPURegister& rt,
+                     const CPURegister& rt2,
+                     const MemOperand& dst) {
+  LoadStorePairNonTemporal(rt, rt2, dst,
+                           StorePairNonTemporalOpFor(rt, rt2));
+}
+
+
+void Assembler::LoadStorePairNonTemporal(const CPURegister& rt,
+                                         const CPURegister& rt2,
+                                         const MemOperand& addr,
+                                         LoadStorePairNonTemporalOp op) {
+  ASSERT(!rt.Is(rt2));
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  ASSERT(addr.IsImmediateOffset());
+
+  LSDataSize size = CalcLSPairDataSize(
+    static_cast<LoadStorePairOp>(op & LoadStorePairMask));
+  Emit(op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) |
+       ImmLSPair(addr.offset(), size));
+}
+
+
+// Memory instructions.
+void Assembler::ldrb(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, LDRB_w);
+}
+
+
+void Assembler::strb(const Register& rt, const MemOperand& dst) {
+  LoadStore(rt, dst, STRB_w);
+}
+
+
+void Assembler::ldrsb(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w);
+}
+
+
+void Assembler::ldrh(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, LDRH_w);
+}
+
+
+void Assembler::strh(const Register& rt, const MemOperand& dst) {
+  LoadStore(rt, dst, STRH_w);
+}
+
+
+void Assembler::ldrsh(const Register& rt, const MemOperand& src) {
+  LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w);
+}
+
+
+void Assembler::ldr(const CPURegister& rt, const MemOperand& src) {
+  LoadStore(rt, src, LoadOpFor(rt));
+}
+
+
+void Assembler::str(const CPURegister& rt, const MemOperand& src) {
+  LoadStore(rt, src, StoreOpFor(rt));
+}
+
+
+void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
+  ASSERT(rt.Is64Bits());
+  LoadStore(rt, src, LDRSW_x);
+}
+
+
+void Assembler::ldr(const Register& rt, uint64_t imm) {
+  LoadLiteral(rt, imm, rt.Is64Bits() ? LDR_x_lit : LDR_w_lit);
+}
+
+
+void Assembler::ldr(const FPRegister& ft, double imm) {
+  uint64_t rawbits = 0;
+  LoadLiteralOp op;
+
+  if (ft.Is64Bits()) {
+    rawbits = double_to_rawbits(imm);
+    op = LDR_d_lit;
+  } else {
+    ASSERT(ft.Is32Bits());
+    float float_imm = static_cast<float>(imm);
+    rawbits = float_to_rawbits(float_imm);
+    op = LDR_s_lit;
+  }
+
+  LoadLiteral(ft, rawbits, op);
+}
+
+
+void Assembler::mov(const Register& rd, const Register& rm) {
+  // Moves involving the stack pointer are encoded as add immediate with
+  // second operand of zero. Otherwise, orr with first operand zr is
+  // used.
+  if (rd.IsSP() || rm.IsSP()) {
+    add(rd, rm, 0);
+  } else {
+    orr(rd, AppropriateZeroRegFor(rd), rm);
+  }
+}
+
+
+void Assembler::mvn(const Register& rd, const Operand& operand) {
+  orn(rd, AppropriateZeroRegFor(rd), operand);
+}
+
+
+void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
+  ASSERT(rt.Is64Bits());
+  Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
+}
+
+
+void Assembler::msr(SystemRegister sysreg, const Register& rt) {
+  ASSERT(rt.Is64Bits());
+  Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
+}
+
+
+void Assembler::hint(SystemHint code) {
+  Emit(HINT | ImmHint(code) | Rt(xzr));
+}
+
+
+void Assembler::fmov(FPRegister fd, double imm) {
+  if (fd.Is64Bits() && IsImmFP64(imm)) {
+    Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm));
+  } else if (fd.Is32Bits() && IsImmFP32(imm)) {
+    Emit(FMOV_s_imm | Rd(fd) | ImmFP32(static_cast<float>(imm)));
+  } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
+    Register zr = AppropriateZeroRegFor(fd);
+    fmov(fd, zr);
+  } else {
+    ldr(fd, imm);
+  }
+}
+
+
+void Assembler::fmov(Register rd, FPRegister fn) {
+  ASSERT(rd.size() == fn.size());
+  FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd;
+  Emit(op | Rd(rd) | Rn(fn));
+}
+
+
+void Assembler::fmov(FPRegister fd, Register rn) {
+  ASSERT(fd.size() == rn.size());
+  FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx;
+  Emit(op | Rd(fd) | Rn(rn));
+}
+
+
+void Assembler::fmov(FPRegister fd, FPRegister fn) {
+  ASSERT(fd.size() == fn.size());
+  Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn));
+}
+
+
+void Assembler::fadd(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FADD);
+}
+
+
+void Assembler::fsub(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FSUB);
+}
+
+
+void Assembler::fmul(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FMUL);
+}
+
+
+void Assembler::fmsub(const FPRegister& fd,
+                      const FPRegister& fn,
+                      const FPRegister& fm,
+                      const FPRegister& fa) {
+  FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d);
+}
+
+
+void Assembler::fdiv(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FDIV);
+}
+
+
+void Assembler::fmax(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FMAX);
+}
+
+
+void Assembler::fmin(const FPRegister& fd,
+                     const FPRegister& fn,
+                     const FPRegister& fm) {
+  FPDataProcessing2Source(fd, fn, fm, FMIN);
+}
+
+
+void Assembler::fabs(const FPRegister& fd,
+                     const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FABS);
+}
+
+
+void Assembler::fneg(const FPRegister& fd,
+                     const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FNEG);
+}
+
+
+void Assembler::fsqrt(const FPRegister& fd,
+                      const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FSQRT);
+}
+
+
+void Assembler::frintn(const FPRegister& fd,
+                       const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FRINTN);
+}
+
+
+void Assembler::frintz(const FPRegister& fd,
+                       const FPRegister& fn) {
+  ASSERT(fd.SizeInBits() == fn.SizeInBits());
+  FPDataProcessing1Source(fd, fn, FRINTZ);
+}
+
+
+void Assembler::fcmp(const FPRegister& fn,
+                     const FPRegister& fm) {
+  ASSERT(fn.size() == fm.size());
+  Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
+}
+
+
+void Assembler::fcmp(const FPRegister& fn,
+                     double value) {
+  USE(value);
+  // Although the fcmp instruction can strictly only take an immediate value of
+  // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
+  // affect the result of the comparison.
+  ASSERT(value == 0.0);
+  Emit(FPType(fn) | FCMP_zero | Rn(fn));
+}
+
+
+void Assembler::fccmp(const FPRegister& fn,
+                      const FPRegister& fm,
+                      StatusFlags nzcv,
+                      Condition cond) {
+  ASSERT(fn.size() == fm.size());
+  Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
+}
+
+
+void Assembler::fcsel(const FPRegister& fd,
+                      const FPRegister& fn,
+                      const FPRegister& fm,
+                      Condition cond) {
+  ASSERT(fd.size() == fn.size());
+  ASSERT(fd.size() == fm.size());
+  Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
+}
+
+
+void Assembler::FPConvertToInt(const Register& rd,
+                               const FPRegister& fn,
+                               FPIntegerConvertOp op) {
+  Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd));
+}
+
+
+void Assembler::fcvt(const FPRegister& fd,
+                     const FPRegister& fn) {
+  if (fd.Is64Bits()) {
+    // Convert float to double.
+    ASSERT(fn.Is32Bits());
+    FPDataProcessing1Source(fd, fn, FCVT_ds);
+  } else {
+    // Convert double to float.
+    ASSERT(fn.Is64Bits());
+    FPDataProcessing1Source(fd, fn, FCVT_sd);
+  }
+}
+
+
+void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTMU);
+}
+
+
+void Assembler::fcvtms(const Register& rd, const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTMS);
+}
+
+
+void Assembler::fcvtnu(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTNU);
+}
+
+
+void Assembler::fcvtns(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTNS);
+}
+
+
+void Assembler::fcvtzu(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTZU);
+}
+
+
+void Assembler::fcvtzs(const Register& rd,
+                       const FPRegister& fn) {
+  FPConvertToInt(rd, fn, FCVTZS);
+}
+
+
+void Assembler::scvtf(const FPRegister& fd,
+                      const Register& rn,
+                      unsigned fbits) {
+  if (fbits == 0) {
+    Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd));
+  } else {
+    Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
+         Rd(fd));
+  }
+}
+
+
+void Assembler::ucvtf(const FPRegister& fd,
+                      const Register& rn,
+                      unsigned fbits) {
+  if (fbits == 0) {
+    Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
+  } else {
+    Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
+         Rd(fd));
+  }
+}
+
+
+// Note:
+// Below, a difference in case for the same letter indicates a
+// negated bit.
+// If b is 1, then B is 0.
+Instr Assembler::ImmFP32(float imm) {
+  ASSERT(IsImmFP32(imm));
+  // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
+  uint32_t bits = float_to_rawbits(imm);
+  // bit7: a000.0000
+  uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
+  // bit6: 0b00.0000
+  uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
+  // bit5_to_0: 00cd.efgh
+  uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
+
+  return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
+}
+
+
+Instr Assembler::ImmFP64(double imm) {
+  ASSERT(IsImmFP64(imm));
+  // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
+  //       0000.0000.0000.0000.0000.0000.0000.0000
+  uint64_t bits = double_to_rawbits(imm);
+  // bit7: a000.0000
+  uint32_t bit7 = ((bits >> 63) & 0x1) << 7;
+  // bit6: 0b00.0000
+  uint32_t bit6 = ((bits >> 61) & 0x1) << 6;
+  // bit5_to_0: 00cd.efgh
+  uint32_t bit5_to_0 = (bits >> 48) & 0x3f;
+
+  return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
+}
+
+
+// Code generation helpers.
+void Assembler::MoveWide(const Register& rd,
+                         uint64_t imm,
+                         int shift,
+                         MoveWideImmediateOp mov_op) {
+  if (shift >= 0) {
+    // Explicit shift specified.
+    ASSERT((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48));
+    ASSERT(rd.Is64Bits() || (shift == 0) || (shift == 16));
+    shift /= 16;
+  } else {
+    // Calculate a new immediate and shift combination to encode the immediate
+    // argument.
+    shift = 0;
+    if ((imm & ~0xffffUL) == 0) {
+      // Nothing to do.
+    } else if ((imm & ~(0xffffUL << 16)) == 0) {
+      imm >>= 16;
+      shift = 1;
+    } else if ((imm & ~(0xffffUL << 32)) == 0) {
+      ASSERT(rd.Is64Bits());
+      imm >>= 32;
+      shift = 2;
+    } else if ((imm & ~(0xffffUL << 48)) == 0) {
+      ASSERT(rd.Is64Bits());
+      imm >>= 48;
+      shift = 3;
+    }
+  }
+
+  ASSERT(is_uint16(imm));
+
+  Emit(SF(rd) | MoveWideImmediateFixed | mov_op |
+       Rd(rd) | ImmMoveWide(imm) | ShiftMoveWide(shift));
+}
+
+
+void Assembler::AddSub(const Register& rd,
+                       const Register& rn,
+                       const Operand& operand,
+                       FlagsUpdate S,
+                       AddSubOp op) {
+  ASSERT(rd.size() == rn.size());
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    ASSERT(IsImmAddSub(immediate));
+    Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
+    Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
+         ImmAddSub(immediate) | dest_reg | RnSP(rn));
+  } else if (operand.IsShiftedRegister()) {
+    ASSERT(operand.reg().size() == rd.size());
+    ASSERT(operand.shift() != ROR);
+
+    // For instructions of the form:
+    //   add/sub   wsp, <Wn>, <Wm> [, LSL #0-3 ]
+    //   add/sub   <Wd>, wsp, <Wm> [, LSL #0-3 ]
+    //   add/sub   wsp, wsp, <Wm> [, LSL #0-3 ]
+    //   adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
+    // or their 64-bit register equivalents, convert the operand from shifted to
+    // extended register mode, and emit an add/sub extended instruction.
+    if (rn.IsSP() || rd.IsSP()) {
+      ASSERT(!(rd.IsSP() && (S == SetFlags)));
+      DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
+                               AddSubExtendedFixed | op);
+    } else {
+      DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
+    }
+  } else {
+    ASSERT(operand.IsExtendedRegister());
+    DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
+  }
+}
+
+
+void Assembler::AddSubWithCarry(const Register& rd,
+                                const Register& rn,
+                                const Operand& operand,
+                                FlagsUpdate S,
+                                AddSubWithCarryOp op) {
+  ASSERT(rd.size() == rn.size());
+  ASSERT(rd.size() == operand.reg().size());
+  ASSERT(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
+  Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::hlt(int code) {
+  ASSERT(is_uint16(code));
+  Emit(HLT | ImmException(code));
+}
+
+
+void Assembler::brk(int code) {
+  ASSERT(is_uint16(code));
+  Emit(BRK | ImmException(code));
+}
+
+
+void Assembler::Logical(const Register& rd,
+                        const Register& rn,
+                        const Operand& operand,
+                        LogicalOp op) {
+  ASSERT(rd.size() == rn.size());
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    unsigned reg_size = rd.size();
+
+    ASSERT(immediate != 0);
+    ASSERT(immediate != -1);
+    ASSERT(rd.Is64Bits() || is_uint32(immediate));
+
+    // If the operation is NOT, invert the operation and immediate.
+    if ((op & NOT) == NOT) {
+      op = static_cast<LogicalOp>(op & ~NOT);
+      immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
+    }
+
+    unsigned n, imm_s, imm_r;
+    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
+      // Immediate can be encoded in the instruction.
+      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
+    } else {
+      // This case is handled in the macro assembler.
+      UNREACHABLE();
+    }
+  } else {
+    ASSERT(operand.IsShiftedRegister());
+    ASSERT(operand.reg().size() == rd.size());
+    Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
+    DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
+  }
+}
+
+
+void Assembler::LogicalImmediate(const Register& rd,
+                                 const Register& rn,
+                                 unsigned n,
+                                 unsigned imm_s,
+                                 unsigned imm_r,
+                                 LogicalOp op) {
+  unsigned reg_size = rd.size();
+  Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
+  Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
+       ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg |
+       Rn(rn));
+}
+
+
+void Assembler::ConditionalCompare(const Register& rn,
+                                   const Operand& operand,
+                                   StatusFlags nzcv,
+                                   Condition cond,
+                                   ConditionalCompareOp op) {
+  Instr ccmpop;
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    ASSERT(IsImmConditionalCompare(immediate));
+    ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate);
+  } else {
+    ASSERT(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
+    ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg());
+  }
+  Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv));
+}
+
+
+void Assembler::DataProcessing1Source(const Register& rd,
+                                      const Register& rn,
+                                      DataProcessing1SourceOp op) {
+  ASSERT(rd.size() == rn.size());
+  Emit(SF(rn) | op | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::FPDataProcessing1Source(const FPRegister& fd,
+                                        const FPRegister& fn,
+                                        FPDataProcessing1SourceOp op) {
+  Emit(FPType(fn) | op | Rn(fn) | Rd(fd));
+}
+
+
+void Assembler::FPDataProcessing2Source(const FPRegister& fd,
+                                        const FPRegister& fn,
+                                        const FPRegister& fm,
+                                        FPDataProcessing2SourceOp op) {
+  ASSERT(fd.size() == fn.size());
+  ASSERT(fd.size() == fm.size());
+  Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
+}
+
+
+void Assembler::FPDataProcessing3Source(const FPRegister& fd,
+                                        const FPRegister& fn,
+                                        const FPRegister& fm,
+                                        const FPRegister& fa,
+                                        FPDataProcessing3SourceOp op) {
+  ASSERT(AreSameSizeAndType(fd, fn, fm, fa));
+  Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
+}
+
+
+void Assembler::EmitShift(const Register& rd,
+                          const Register& rn,
+                          Shift shift,
+                          unsigned shift_amount) {
+  switch (shift) {
+    case LSL:
+      lsl(rd, rn, shift_amount);
+      break;
+    case LSR:
+      lsr(rd, rn, shift_amount);
+      break;
+    case ASR:
+      asr(rd, rn, shift_amount);
+      break;
+    case ROR:
+      ror(rd, rn, shift_amount);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void Assembler::EmitExtendShift(const Register& rd,
+                                const Register& rn,
+                                Extend extend,
+                                unsigned left_shift) {
+  ASSERT(rd.size() >= rn.size());
+  unsigned reg_size = rd.size();
+  // Use the correct size of register.
+  Register rn_ = Register(rn.code(), rd.size());
+  // Bits extracted are high_bit:0.
+  unsigned high_bit = (8 << (extend & 0x3)) - 1;
+  // Number of bits left in the result that are not introduced by the shift.
+  unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1);
+
+  if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) {
+    switch (extend) {
+      case UXTB:
+      case UXTH:
+      case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break;
+      case SXTB:
+      case SXTH:
+      case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break;
+      case UXTX:
+      case SXTX: {
+        ASSERT(rn.size() == kXRegSize);
+        // Nothing to extend. Just shift.
+        lsl(rd, rn_, left_shift);
+        break;
+      }
+      default: UNREACHABLE();
+    }
+  } else {
+    // No need to extend as the extended bits would be shifted away.
+    lsl(rd, rn_, left_shift);
+  }
+}
+
+
+void Assembler::DataProcShiftedRegister(const Register& rd,
+                                        const Register& rn,
+                                        const Operand& operand,
+                                        FlagsUpdate S,
+                                        Instr op) {
+  ASSERT(operand.IsShiftedRegister());
+  ASSERT(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
+  Emit(SF(rd) | op | Flags(S) |
+       ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) |
+       Rm(operand.reg()) | Rn(rn) | Rd(rd));
+}
+
+
+void Assembler::DataProcExtendedRegister(const Register& rd,
+                                         const Register& rn,
+                                         const Operand& operand,
+                                         FlagsUpdate S,
+                                         Instr op) {
+  Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
+  Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) |
+       ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) |
+       dest_reg | RnSP(rn));
+}
+
+
+bool Assembler::IsImmAddSub(int64_t immediate) {
+  return is_uint12(immediate) ||
+         (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0));
+}
+
+void Assembler::LoadStore(const CPURegister& rt,
+                          const MemOperand& addr,
+                          LoadStoreOp op) {
+  Instr memop = op | Rt(rt) | RnSP(addr.base());
+  ptrdiff_t offset = addr.offset();
+
+  if (addr.IsImmediateOffset()) {
+    LSDataSize size = CalcLSDataSize(op);
+    if (IsImmLSScaled(offset, size)) {
+      // Use the scaled addressing mode.
+      Emit(LoadStoreUnsignedOffsetFixed | memop |
+           ImmLSUnsigned(offset >> size));
+    } else if (IsImmLSUnscaled(offset)) {
+      // Use the unscaled addressing mode.
+      Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
+    } else {
+      // This case is handled in the macro assembler.
+      UNREACHABLE();
+    }
+  } else if (addr.IsRegisterOffset()) {
+    Extend ext = addr.extend();
+    Shift shift = addr.shift();
+    unsigned shift_amount = addr.shift_amount();
+
+    // LSL is encoded in the option field as UXTX.
+    if (shift == LSL) {
+      ext = UXTX;
+    }
+
+    // Shifts are encoded in one bit, indicating a left shift by the memory
+    // access size.
+    ASSERT((shift_amount == 0) ||
+           (shift_amount == static_cast<unsigned>(CalcLSDataSize(op))));
+    Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) |
+         ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0));
+  } else {
+    if (IsImmLSUnscaled(offset)) {
+      if (addr.IsPreIndex()) {
+        Emit(LoadStorePreIndexFixed | memop | ImmLS(offset));
+      } else {
+        ASSERT(addr.IsPostIndex());
+        Emit(LoadStorePostIndexFixed | memop | ImmLS(offset));
+      }
+    } else {
+      // This case is handled in the macro assembler.
+      UNREACHABLE();
+    }
+  }
+}
+
+
+bool Assembler::IsImmLSUnscaled(ptrdiff_t offset) {
+  return is_int9(offset);
+}
+
+
+bool Assembler::IsImmLSScaled(ptrdiff_t offset, LSDataSize size) {
+  bool offset_is_size_multiple = (((offset >> size) << size) == offset);
+  return offset_is_size_multiple && is_uint12(offset >> size);
+}
+
+
+void Assembler::LoadLiteral(const CPURegister& rt,
+                            uint64_t imm,
+                            LoadLiteralOp op) {
+  ASSERT(is_int32(imm) || is_uint32(imm) || (rt.Is64Bits()));
+
+  BlockLiteralPoolScope scope(this);
+  RecordLiteral(imm, rt.SizeInBytes());
+  Emit(op | ImmLLiteral(0) | Rt(rt));
+}
+
+
+// Test if a given value can be encoded in the immediate field of a logical
+// instruction.
+// If it can be encoded, the function returns true, and values pointed to by n,
+// imm_s and imm_r are updated with immediates encoded in the format required
+// by the corresponding fields in the logical instruction.
+// If it can not be encoded, the function returns false, and the values pointed
+// to by n, imm_s and imm_r are undefined.
+bool Assembler::IsImmLogical(uint64_t value,
+                             unsigned width,
+                             unsigned* n,
+                             unsigned* imm_s,
+                             unsigned* imm_r) {
+  ASSERT((n != NULL) && (imm_s != NULL) && (imm_r != NULL));
+  ASSERT((width == kWRegSize) || (width == kXRegSize));
+
+  // Logical immediates are encoded using parameters n, imm_s and imm_r using
+  // the following table:
+  //
+  //  N   imms    immr    size        S             R
+  //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
+  //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
+  //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
+  //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
+  //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
+  //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
+  // (s bits must not be all set)
+  //
+  // A pattern is constructed of size bits, where the least significant S+1
+  // bits are set. The pattern is rotated right by R, and repeated across a
+  // 32 or 64-bit value, depending on destination register width.
+  //
+  // To test if an arbitrary immediate can be encoded using this scheme, an
+  // iterative algorithm is used.
+  //
+  // TODO: This code does not consider using X/W register overlap to support
+  // 64-bit immediates where the top 32-bits are zero, and the bottom 32-bits
+  // are an encodable logical immediate.
+
+  // 1. If the value has all set or all clear bits, it can't be encoded.
+  if ((value == 0) || (value == 0xffffffffffffffffUL) ||
+      ((width == kWRegSize) && (value == 0xffffffff))) {
+    return false;
+  }
+
+  unsigned lead_zero = CountLeadingZeros(value, width);
+  unsigned lead_one = CountLeadingZeros(~value, width);
+  unsigned trail_zero = CountTrailingZeros(value, width);
+  unsigned trail_one = CountTrailingZeros(~value, width);
+  unsigned set_bits = CountSetBits(value, width);
+
+  // The fixed bits in the immediate s field.
+  // If width == 64 (X reg), start at 0xFFFFFF80.
+  // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit
+  // widths won't be executed.
+  int imm_s_fixed = (width == kXRegSize) ? -128 : -64;
+  int imm_s_mask = 0x3F;
+
+  for (;;) {
+    // 2. If the value is two bits wide, it can be encoded.
+    if (width == 2) {
+      *n = 0;
+      *imm_s = 0x3C;
+      *imm_r = (value & 3) - 1;
+      return true;
+    }
+
+    *n = (width == 64) ? 1 : 0;
+    *imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask);
+    if ((lead_zero + set_bits) == width) {
+      *imm_r = 0;
+    } else {
+      *imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one;
+    }
+
+    // 3. If the sum of leading zeros, trailing zeros and set bits is equal to
+    //    the bit width of the value, it can be encoded.
+    if (lead_zero + trail_zero + set_bits == width) {
+      return true;
+    }
+
+    // 4. If the sum of leading ones, trailing ones and unset bits in the
+    //    value is equal to the bit width of the value, it can be encoded.
+    if (lead_one + trail_one + (width - set_bits) == width) {
+      return true;
+    }
+
+    // 5. If the most-significant half of the bitwise value is equal to the
+    //    least-significant half, return to step 2 using the least-significant
+    //    half of the value.
+    uint64_t mask = (1UL << (width >> 1)) - 1;
+    if ((value & mask) == ((value >> (width >> 1)) & mask)) {
+      width >>= 1;
+      set_bits >>= 1;
+      imm_s_fixed >>= 1;
+      continue;
+    }
+
+    // 6. Otherwise, the value can't be encoded.
+    return false;
+  }
+}
+
+bool Assembler::IsImmConditionalCompare(int64_t immediate) {
+  return is_uint5(immediate);
+}
+
+
+bool Assembler::IsImmFP32(float imm) {
+  // Valid values will have the form:
+  // aBbb.bbbc.defg.h000.0000.0000.0000.0000
+  uint32_t bits = float_to_rawbits(imm);
+  // bits[19..0] are cleared.
+  if ((bits & 0x7ffff) != 0) {
+    return false;
+  }
+
+  // bits[29..25] are all set or all cleared.
+  uint32_t b_pattern = (bits >> 16) & 0x3e00;
+  if (b_pattern != 0 && b_pattern != 0x3e00) {
+    return false;
+  }
+
+  // bit[30] and bit[29] are opposite.
+  if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
+    return false;
+  }
+
+  return true;
+}
+
+
+bool Assembler::IsImmFP64(double imm) {
+  // Valid values will have the form:
+  // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
+  // 0000.0000.0000.0000.0000.0000.0000.0000
+  uint64_t bits = double_to_rawbits(imm);
+  // bits[47..0] are cleared.
+  if ((bits & 0xffffffffffffL) != 0) {
+    return false;
+  }
+
+  // bits[61..54] are all set or all cleared.
+  uint32_t b_pattern = (bits >> 48) & 0x3fc0;
+  if (b_pattern != 0 && b_pattern != 0x3fc0) {
+    return false;
+  }
+
+  // bit[62] and bit[61] are opposite.
+  if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) {
+    return false;
+  }
+
+  return true;
+}
+
+
+LoadStoreOp Assembler::LoadOpFor(const CPURegister& rt) {
+  ASSERT(rt.IsValid());
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDR_x : LDR_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDR_d : LDR_s;
+  }
+}
+
+
+LoadStorePairOp Assembler::LoadPairOpFor(const CPURegister& rt,
+    const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDP_x : LDP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDP_d : LDP_s;
+  }
+}
+
+
+LoadStoreOp Assembler::StoreOpFor(const CPURegister& rt) {
+  ASSERT(rt.IsValid());
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? STR_x : STR_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? STR_d : STR_s;
+  }
+}
+
+
+LoadStorePairOp Assembler::StorePairOpFor(const CPURegister& rt,
+    const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? STP_x : STP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? STP_d : STP_s;
+  }
+}
+
+
+LoadStorePairNonTemporalOp Assembler::LoadPairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDNP_x : LDNP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDNP_d : LDNP_s;
+  }
+}
+
+
+LoadStorePairNonTemporalOp Assembler::StorePairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2) {
+  ASSERT(AreSameSizeAndType(rt, rt2));
+  USE(rt2);
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? STNP_x : STNP_w;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? STNP_d : STNP_s;
+  }
+}
+
+
+void Assembler::RecordLiteral(int64_t imm, unsigned size) {
+  literals_.push_front(new Literal(pc_, imm, size));
+}
+
+
+// Check if a literal pool should be emitted. Currently a literal is emitted
+// when:
+//  * the distance to the first literal load handled by this pool is greater
+//    than the recommended distance and the literal pool can be emitted without
+//    generating a jump over it.
+//  * the distance to the first literal load handled by this pool is greater
+//    than twice the recommended distance.
+// TODO: refine this heuristic using real world data.
+void Assembler::CheckLiteralPool(LiteralPoolEmitOption option) {
+  if (IsLiteralPoolBlocked()) {
+    // Literal pool emission is forbidden, no point in doing further checks.
+    return;
+  }
+
+  if (literals_.empty()) {
+    // No literal pool to emit.
+    next_literal_pool_check_ += kLiteralPoolCheckInterval;
+    return;
+  }
+
+  intptr_t distance = pc_ - literals_.back()->pc_;
+  if ((distance < kRecommendedLiteralPoolRange) ||
+      ((option == JumpRequired) &&
+       (distance < (2 * kRecommendedLiteralPoolRange)))) {
+    // We prefer not to have to jump over the literal pool.
+    next_literal_pool_check_ += kLiteralPoolCheckInterval;
+    return;
+  }
+
+  EmitLiteralPool(option);
+}
+
+
+void Assembler::EmitLiteralPool(LiteralPoolEmitOption option) {
+  // Prevent recursive calls while emitting the literal pool.
+  BlockLiteralPoolScope scope(this);
+
+  Label marker;
+  Label start_of_pool;
+  Label end_of_pool;
+
+  if (option == JumpRequired) {
+    b(&end_of_pool);
+  }
+
+  // Leave space for a literal pool marker. This is populated later, once the
+  // size of the pool is known.
+  bind(&marker);
+  nop();
+
+  // Now populate the literal pool.
+  bind(&start_of_pool);
+  std::list<Literal*>::iterator it;
+  for (it = literals_.begin(); it != literals_.end(); it++) {
+    // Update the load-literal instruction to point to this pool entry.
+    Instruction* load_literal = (*it)->pc_;
+    load_literal->SetImmLLiteral(pc_);
+    // Copy the data into the pool.
+    uint64_t value= (*it)->value_;
+    unsigned size = (*it)->size_;
+    ASSERT((size == kXRegSizeInBytes) || (size == kWRegSizeInBytes));
+    ASSERT((pc_ + size) <= (buffer_ + buffer_size_));
+    memcpy(pc_, &value, size);
+    pc_ += size;
+    delete *it;
+  }
+  literals_.clear();
+  bind(&end_of_pool);
+
+  // The pool size should always be a multiple of four bytes because that is the
+  // scaling applied by the LDR(literal) instruction, even for X-register loads.
+  ASSERT((SizeOfCodeGeneratedSince(&start_of_pool) % 4) == 0);
+  uint64_t pool_size = SizeOfCodeGeneratedSince(&start_of_pool) / 4;
+
+  // Literal pool marker indicating the size in words of the literal pool.
+  // We use a literal load to the zero register, the offset indicating the
+  // size in words. This instruction can encode a large enough offset to span
+  // the entire pool at its maximum size.
+  Instr marker_instruction = LDR_x_lit | ImmLLiteral(pool_size) | Rt(xzr);
+  memcpy(marker.target(), &marker_instruction, kInstructionSize);
+
+  next_literal_pool_check_ = pc_ + kLiteralPoolCheckInterval;
+}
+
+
+// Return the size in bytes, required by the literal pool entries. This does
+// not include any marker or branch over the literal pool itself.
+size_t Assembler::LiteralPoolSize() {
+  size_t size = 0;
+
+  std::list<Literal*>::iterator it;
+  for (it = literals_.begin(); it != literals_.end(); it++) {
+    size += (*it)->size_;
+  }
+
+  return size;
+}
+
+
+bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
+                const CPURegister& reg3, const CPURegister& reg4,
+                const CPURegister& reg5, const CPURegister& reg6,
+                const CPURegister& reg7, const CPURegister& reg8) {
+  int number_of_valid_regs = 0;
+  int number_of_valid_fpregs = 0;
+
+  RegList unique_regs = 0;
+  RegList unique_fpregs = 0;
+
+  const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
+
+  for (unsigned i = 0; i < sizeof(regs) / sizeof(regs[0]); i++) {
+    if (regs[i].IsRegister()) {
+      number_of_valid_regs++;
+      unique_regs |= regs[i].Bit();
+    } else if (regs[i].IsFPRegister()) {
+      number_of_valid_fpregs++;
+      unique_fpregs |= regs[i].Bit();
+    } else {
+      ASSERT(!regs[i].IsValid());
+    }
+  }
+
+  int number_of_unique_regs =
+    CountSetBits(unique_regs, sizeof(unique_regs) * 8);
+  int number_of_unique_fpregs =
+    CountSetBits(unique_fpregs, sizeof(unique_fpregs) * 8);
+
+  ASSERT(number_of_valid_regs >= number_of_unique_regs);
+  ASSERT(number_of_valid_fpregs >= number_of_unique_fpregs);
+
+  return (number_of_valid_regs != number_of_unique_regs) ||
+         (number_of_valid_fpregs != number_of_unique_fpregs);
+}
+
+
+bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2,
+                        const CPURegister& reg3, const CPURegister& reg4,
+                        const CPURegister& reg5, const CPURegister& reg6,
+                        const CPURegister& reg7, const CPURegister& reg8) {
+  ASSERT(reg1.IsValid());
+  bool match = true;
+  match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1);
+  match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1);
+  match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1);
+  match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1);
+  match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1);
+  match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1);
+  match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1);
+  return match;
+}
+
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/assembler-a64.h b/disas/libvixl/src/a64/assembler-a64.h
new file mode 100644
index 0000000..93b3011
--- /dev/null
+++ b/disas/libvixl/src/a64/assembler-a64.h
@@ -0,0 +1,1784 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_ASSEMBLER_A64_H_
+#define VIXL_A64_ASSEMBLER_A64_H_
+
+#include <list>
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/instructions-a64.h"
+
+namespace vixl {
+
+typedef uint64_t RegList;
+static const int kRegListSizeInBits = sizeof(RegList) * 8;
+
+// Registers.
+
+// Some CPURegister methods can return Register and FPRegister types, so we
+// need to declare them in advance.
+class Register;
+class FPRegister;
+
+
+class CPURegister {
+ public:
+  enum RegisterType {
+    // The kInvalid value is used to detect uninitialized static instances,
+    // which are always zero-initialized before any constructors are called.
+    kInvalid = 0,
+    kRegister,
+    kFPRegister,
+    kNoRegister
+  };
+
+  CPURegister() : code_(0), size_(0), type_(kNoRegister) {
+    ASSERT(!IsValid());
+    ASSERT(IsNone());
+  }
+
+  CPURegister(unsigned code, unsigned size, RegisterType type)
+      : code_(code), size_(size), type_(type) {
+    ASSERT(IsValidOrNone());
+  }
+
+  unsigned code() const {
+    ASSERT(IsValid());
+    return code_;
+  }
+
+  RegisterType type() const {
+    ASSERT(IsValidOrNone());
+    return type_;
+  }
+
+  RegList Bit() const {
+    ASSERT(code_ < (sizeof(RegList) * 8));
+    return IsValid() ? (static_cast<RegList>(1) << code_) : 0;
+  }
+
+  unsigned size() const {
+    ASSERT(IsValid());
+    return size_;
+  }
+
+  int SizeInBytes() const {
+    ASSERT(IsValid());
+    ASSERT(size() % 8 == 0);
+    return size_ / 8;
+  }
+
+  int SizeInBits() const {
+    ASSERT(IsValid());
+    return size_;
+  }
+
+  bool Is32Bits() const {
+    ASSERT(IsValid());
+    return size_ == 32;
+  }
+
+  bool Is64Bits() const {
+    ASSERT(IsValid());
+    return size_ == 64;
+  }
+
+  bool IsValid() const {
+    if (IsValidRegister() || IsValidFPRegister()) {
+      ASSERT(!IsNone());
+      return true;
+    } else {
+      ASSERT(IsNone());
+      return false;
+    }
+  }
+
+  bool IsValidRegister() const {
+    return IsRegister() &&
+           ((size_ == kWRegSize) || (size_ == kXRegSize)) &&
+           ((code_ < kNumberOfRegisters) || (code_ == kSPRegInternalCode));
+  }
+
+  bool IsValidFPRegister() const {
+    return IsFPRegister() &&
+           ((size_ == kSRegSize) || (size_ == kDRegSize)) &&
+           (code_ < kNumberOfFPRegisters);
+  }
+
+  bool IsNone() const {
+    // kNoRegister types should always have size 0 and code 0.
+    ASSERT((type_ != kNoRegister) || (code_ == 0));
+    ASSERT((type_ != kNoRegister) || (size_ == 0));
+
+    return type_ == kNoRegister;
+  }
+
+  bool Is(const CPURegister& other) const {
+    ASSERT(IsValidOrNone() && other.IsValidOrNone());
+    return (code_ == other.code_) && (size_ == other.size_) &&
+           (type_ == other.type_);
+  }
+
+  inline bool IsZero() const {
+    ASSERT(IsValid());
+    return IsRegister() && (code_ == kZeroRegCode);
+  }
+
+  inline bool IsSP() const {
+    ASSERT(IsValid());
+    return IsRegister() && (code_ == kSPRegInternalCode);
+  }
+
+  inline bool IsRegister() const {
+    return type_ == kRegister;
+  }
+
+  inline bool IsFPRegister() const {
+    return type_ == kFPRegister;
+  }
+
+  const Register& W() const;
+  const Register& X() const;
+  const FPRegister& S() const;
+  const FPRegister& D() const;
+
+  inline bool IsSameSizeAndType(const CPURegister& other) const {
+    return (size_ == other.size_) && (type_ == other.type_);
+  }
+
+ protected:
+  unsigned code_;
+  unsigned size_;
+  RegisterType type_;
+
+ private:
+  bool IsValidOrNone() const {
+    return IsValid() || IsNone();
+  }
+};
+
+
+class Register : public CPURegister {
+ public:
+  explicit Register() : CPURegister() {}
+  inline explicit Register(const CPURegister& other)
+      : CPURegister(other.code(), other.size(), other.type()) {
+    ASSERT(IsValidRegister());
+  }
+  explicit Register(unsigned code, unsigned size)
+      : CPURegister(code, size, kRegister) {}
+
+  bool IsValid() const {
+    ASSERT(IsRegister() || IsNone());
+    return IsValidRegister();
+  }
+
+  static const Register& WRegFromCode(unsigned code);
+  static const Register& XRegFromCode(unsigned code);
+
+  // V8 compatibility.
+  static const int kNumRegisters = kNumberOfRegisters;
+  static const int kNumAllocatableRegisters = kNumberOfRegisters - 1;
+
+ private:
+  static const Register wregisters[];
+  static const Register xregisters[];
+};
+
+
+class FPRegister : public CPURegister {
+ public:
+  inline FPRegister() : CPURegister() {}
+  inline explicit FPRegister(const CPURegister& other)
+      : CPURegister(other.code(), other.size(), other.type()) {
+    ASSERT(IsValidFPRegister());
+  }
+  inline FPRegister(unsigned code, unsigned size)
+      : CPURegister(code, size, kFPRegister) {}
+
+  bool IsValid() const {
+    ASSERT(IsFPRegister() || IsNone());
+    return IsValidFPRegister();
+  }
+
+  static const FPRegister& SRegFromCode(unsigned code);
+  static const FPRegister& DRegFromCode(unsigned code);
+
+  // V8 compatibility.
+  static const int kNumRegisters = kNumberOfFPRegisters;
+  static const int kNumAllocatableRegisters = kNumberOfFPRegisters - 1;
+
+ private:
+  static const FPRegister sregisters[];
+  static const FPRegister dregisters[];
+};
+
+
+// No*Reg is used to indicate an unused argument, or an error case. Note that
+// these all compare equal (using the Is() method). The Register and FPRegister
+// variants are provided for convenience.
+const Register NoReg;
+const FPRegister NoFPReg;
+const CPURegister NoCPUReg;
+
+
+#define DEFINE_REGISTERS(N)  \
+const Register w##N(N, kWRegSize);  \
+const Register x##N(N, kXRegSize);
+REGISTER_CODE_LIST(DEFINE_REGISTERS)
+#undef DEFINE_REGISTERS
+const Register wsp(kSPRegInternalCode, kWRegSize);
+const Register sp(kSPRegInternalCode, kXRegSize);
+
+
+#define DEFINE_FPREGISTERS(N)  \
+const FPRegister s##N(N, kSRegSize);  \
+const FPRegister d##N(N, kDRegSize);
+REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
+#undef DEFINE_FPREGISTERS
+
+
+// Registers aliases.
+const Register ip0 = x16;
+const Register ip1 = x17;
+const Register lr = x30;
+const Register xzr = x31;
+const Register wzr = w31;
+
+
+// AreAliased returns true if any of the named registers overlap. Arguments
+// set to NoReg are ignored. The system stack pointer may be specified.
+bool AreAliased(const CPURegister& reg1,
+                const CPURegister& reg2,
+                const CPURegister& reg3 = NoReg,
+                const CPURegister& reg4 = NoReg,
+                const CPURegister& reg5 = NoReg,
+                const CPURegister& reg6 = NoReg,
+                const CPURegister& reg7 = NoReg,
+                const CPURegister& reg8 = NoReg);
+
+
+// AreSameSizeAndType returns true if all of the specified registers have the
+// same size, and are of the same type. The system stack pointer may be
+// specified. Arguments set to NoReg are ignored, as are any subsequent
+// arguments. At least one argument (reg1) must be valid (not NoCPUReg).
+bool AreSameSizeAndType(const CPURegister& reg1,
+                        const CPURegister& reg2,
+                        const CPURegister& reg3 = NoCPUReg,
+                        const CPURegister& reg4 = NoCPUReg,
+                        const CPURegister& reg5 = NoCPUReg,
+                        const CPURegister& reg6 = NoCPUReg,
+                        const CPURegister& reg7 = NoCPUReg,
+                        const CPURegister& reg8 = NoCPUReg);
+
+
+// Lists of registers.
+class CPURegList {
+ public:
+  inline explicit CPURegList(CPURegister reg1,
+                             CPURegister reg2 = NoCPUReg,
+                             CPURegister reg3 = NoCPUReg,
+                             CPURegister reg4 = NoCPUReg)
+      : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()),
+        size_(reg1.size()), type_(reg1.type()) {
+    ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4));
+    ASSERT(IsValid());
+  }
+
+  inline CPURegList(CPURegister::RegisterType type, unsigned size, RegList list)
+      : list_(list), size_(size), type_(type) {
+    ASSERT(IsValid());
+  }
+
+  inline CPURegList(CPURegister::RegisterType type, unsigned size,
+                    unsigned first_reg, unsigned last_reg)
+      : size_(size), type_(type) {
+    ASSERT(((type == CPURegister::kRegister) &&
+            (last_reg < kNumberOfRegisters)) ||
+           ((type == CPURegister::kFPRegister) &&
+            (last_reg < kNumberOfFPRegisters)));
+    ASSERT(last_reg >= first_reg);
+    list_ = (1UL << (last_reg + 1)) - 1;
+    list_ &= ~((1UL << first_reg) - 1);
+    ASSERT(IsValid());
+  }
+
+  inline CPURegister::RegisterType type() const {
+    ASSERT(IsValid());
+    return type_;
+  }
+
+  // Combine another CPURegList into this one. Registers that already exist in
+  // this list are left unchanged. The type and size of the registers in the
+  // 'other' list must match those in this list.
+  void Combine(const CPURegList& other) {
+    ASSERT(IsValid());
+    ASSERT(other.type() == type_);
+    ASSERT(other.RegisterSizeInBits() == size_);
+    list_ |= other.list();
+  }
+
+  // Remove every register in the other CPURegList from this one. Registers that
+  // do not exist in this list are ignored. The type and size of the registers
+  // in the 'other' list must match those in this list.
+  void Remove(const CPURegList& other) {
+    ASSERT(IsValid());
+    ASSERT(other.type() == type_);
+    ASSERT(other.RegisterSizeInBits() == size_);
+    list_ &= ~other.list();
+  }
+
+  // Variants of Combine and Remove which take a single register.
+  inline void Combine(const CPURegister& other) {
+    ASSERT(other.type() == type_);
+    ASSERT(other.size() == size_);
+    Combine(other.code());
+  }
+
+  inline void Remove(const CPURegister& other) {
+    ASSERT(other.type() == type_);
+    ASSERT(other.size() == size_);
+    Remove(other.code());
+  }
+
+  // Variants of Combine and Remove which take a single register by its code;
+  // the type and size of the register is inferred from this list.
+  inline void Combine(int code) {
+    ASSERT(IsValid());
+    ASSERT(CPURegister(code, size_, type_).IsValid());
+    list_ |= (1UL << code);
+  }
+
+  inline void Remove(int code) {
+    ASSERT(IsValid());
+    ASSERT(CPURegister(code, size_, type_).IsValid());
+    list_ &= ~(1UL << code);
+  }
+
+  inline RegList list() const {
+    ASSERT(IsValid());
+    return list_;
+  }
+
+  // Remove all callee-saved registers from the list. This can be useful when
+  // preparing registers for an AAPCS64 function call, for example.
+  void RemoveCalleeSaved();
+
+  CPURegister PopLowestIndex();
+  CPURegister PopHighestIndex();
+
+  // AAPCS64 callee-saved registers.
+  static CPURegList GetCalleeSaved(unsigned size = kXRegSize);
+  static CPURegList GetCalleeSavedFP(unsigned size = kDRegSize);
+
+  // AAPCS64 caller-saved registers. Note that this includes lr.
+  static CPURegList GetCallerSaved(unsigned size = kXRegSize);
+  static CPURegList GetCallerSavedFP(unsigned size = kDRegSize);
+
+  inline bool IsEmpty() const {
+    ASSERT(IsValid());
+    return list_ == 0;
+  }
+
+  inline bool IncludesAliasOf(const CPURegister& other) const {
+    ASSERT(IsValid());
+    return (type_ == other.type()) && (other.Bit() & list_);
+  }
+
+  inline int Count() const {
+    ASSERT(IsValid());
+    return CountSetBits(list_, kRegListSizeInBits);
+  }
+
+  inline unsigned RegisterSizeInBits() const {
+    ASSERT(IsValid());
+    return size_;
+  }
+
+  inline unsigned RegisterSizeInBytes() const {
+    int size_in_bits = RegisterSizeInBits();
+    ASSERT((size_in_bits % 8) == 0);
+    return size_in_bits / 8;
+  }
+
+ private:
+  RegList list_;
+  unsigned size_;
+  CPURegister::RegisterType type_;
+
+  bool IsValid() const;
+};
+
+
+// AAPCS64 callee-saved registers.
+extern const CPURegList kCalleeSaved;
+extern const CPURegList kCalleeSavedFP;
+
+
+// AAPCS64 caller-saved registers. Note that this includes lr.
+extern const CPURegList kCallerSaved;
+extern const CPURegList kCallerSavedFP;
+
+
+// Operand.
+class Operand {
+ public:
+  // #<immediate>
+  // where <immediate> is int64_t.
+  // This is allowed to be an implicit constructor because Operand is
+  // a wrapper class that doesn't normally perform any type conversion.
+  Operand(int64_t immediate);           // NOLINT(runtime/explicit)
+
+  // rm, {<shift> #<shift_amount>}
+  // where <shift> is one of {LSL, LSR, ASR, ROR}.
+  //       <shift_amount> is uint6_t.
+  // This is allowed to be an implicit constructor because Operand is
+  // a wrapper class that doesn't normally perform any type conversion.
+  Operand(Register reg,
+          Shift shift = LSL,
+          unsigned shift_amount = 0);   // NOLINT(runtime/explicit)
+
+  // rm, {<extend> {#<shift_amount>}}
+  // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}.
+  //       <shift_amount> is uint2_t.
+  explicit Operand(Register reg, Extend extend, unsigned shift_amount = 0);
+
+  bool IsImmediate() const;
+  bool IsShiftedRegister() const;
+  bool IsExtendedRegister() const;
+
+  // This returns an LSL shift (<= 4) operand as an equivalent extend operand,
+  // which helps in the encoding of instructions that use the stack pointer.
+  Operand ToExtendedRegister() const;
+
+  int64_t immediate() const {
+    ASSERT(IsImmediate());
+    return immediate_;
+  }
+
+  Register reg() const {
+    ASSERT(IsShiftedRegister() || IsExtendedRegister());
+    return reg_;
+  }
+
+  Shift shift() const {
+    ASSERT(IsShiftedRegister());
+    return shift_;
+  }
+
+  Extend extend() const {
+    ASSERT(IsExtendedRegister());
+    return extend_;
+  }
+
+  unsigned shift_amount() const {
+    ASSERT(IsShiftedRegister() || IsExtendedRegister());
+    return shift_amount_;
+  }
+
+ private:
+  int64_t immediate_;
+  Register reg_;
+  Shift shift_;
+  Extend extend_;
+  unsigned shift_amount_;
+};
+
+
+// MemOperand represents the addressing mode of a load or store instruction.
+class MemOperand {
+ public:
+  explicit MemOperand(Register base,
+                      ptrdiff_t offset = 0,
+                      AddrMode addrmode = Offset);
+  explicit MemOperand(Register base,
+                      Register regoffset,
+                      Shift shift = LSL,
+                      unsigned shift_amount = 0);
+  explicit MemOperand(Register base,
+                      Register regoffset,
+                      Extend extend,
+                      unsigned shift_amount = 0);
+  explicit MemOperand(Register base,
+                      const Operand& offset,
+                      AddrMode addrmode = Offset);
+
+  const Register& base() const { return base_; }
+  const Register& regoffset() const { return regoffset_; }
+  ptrdiff_t offset() const { return offset_; }
+  AddrMode addrmode() const { return addrmode_; }
+  Shift shift() const { return shift_; }
+  Extend extend() const { return extend_; }
+  unsigned shift_amount() const { return shift_amount_; }
+  bool IsImmediateOffset() const;
+  bool IsRegisterOffset() const;
+  bool IsPreIndex() const;
+  bool IsPostIndex() const;
+
+ private:
+  Register base_;
+  Register regoffset_;
+  ptrdiff_t offset_;
+  AddrMode addrmode_;
+  Shift shift_;
+  Extend extend_;
+  unsigned shift_amount_;
+};
+
+
+class Label {
+ public:
+  Label() : is_bound_(false), link_(NULL), target_(NULL) {}
+  ~Label() {
+    // If the label has been linked to, it needs to be bound to a target.
+    ASSERT(!IsLinked() || IsBound());
+  }
+
+  inline Instruction* link() const { return link_; }
+  inline Instruction* target() const { return target_; }
+
+  inline bool IsBound() const { return is_bound_; }
+  inline bool IsLinked() const { return link_ != NULL; }
+
+  inline void set_link(Instruction* new_link) { link_ = new_link; }
+
+  static const int kEndOfChain = 0;
+
+ private:
+  // Indicates if the label has been bound, ie its location is fixed.
+  bool is_bound_;
+  // Branches instructions branching to this label form a chained list, with
+  // their offset indicating where the next instruction is located.
+  // link_ points to the latest branch instruction generated branching to this
+  // branch.
+  // If link_ is not NULL, the label has been linked to.
+  Instruction* link_;
+  // The label location.
+  Instruction* target_;
+
+  friend class Assembler;
+};
+
+
+// TODO: Obtain better values for these, based on real-world data.
+const int kLiteralPoolCheckInterval = 4 * KBytes;
+const int kRecommendedLiteralPoolRange = 2 * kLiteralPoolCheckInterval;
+
+
+// Control whether a branch over the literal pool should also be emitted. This
+// is needed if the literal pool has to be emitted in the middle of the JITted
+// code.
+enum LiteralPoolEmitOption {
+  JumpRequired,
+  NoJumpRequired
+};
+
+
+// Literal pool entry.
+class Literal {
+ public:
+  Literal(Instruction* pc, uint64_t imm, unsigned size)
+      : pc_(pc), value_(imm), size_(size) {}
+
+ private:
+  Instruction* pc_;
+  int64_t value_;
+  unsigned size_;
+
+  friend class Assembler;
+};
+
+
+// Assembler.
+class Assembler {
+ public:
+  Assembler(byte* buffer, unsigned buffer_size);
+
+  // The destructor asserts that one of the following is true:
+  //  * The Assembler object has not been used.
+  //  * Nothing has been emitted since the last Reset() call.
+  //  * Nothing has been emitted since the last FinalizeCode() call.
+  ~Assembler();
+
+  // System functions.
+
+  // Start generating code from the beginning of the buffer, discarding any code
+  // and data that has already been emitted into the buffer.
+  //
+  // In order to avoid any accidental transfer of state, Reset ASSERTs that the
+  // constant pool is not blocked.
+  void Reset();
+
+  // Finalize a code buffer of generated instructions. This function must be
+  // called before executing or copying code from the buffer.
+  void FinalizeCode();
+
+  // Label.
+  // Bind a label to the current PC.
+  void bind(Label* label);
+  int UpdateAndGetByteOffsetTo(Label* label);
+  inline int UpdateAndGetInstructionOffsetTo(Label* label) {
+    ASSERT(Label::kEndOfChain == 0);
+    return UpdateAndGetByteOffsetTo(label) >> kInstructionSizeLog2;
+  }
+
+
+  // Instruction set functions.
+
+  // Branch / Jump instructions.
+  // Branch to register.
+  void br(const Register& xn);
+
+  // Branch with link to register.
+  void blr(const Register& xn);
+
+  // Branch to register with return hint.
+  void ret(const Register& xn = lr);
+
+  // Unconditional branch to label.
+  void b(Label* label);
+
+  // Conditional branch to label.
+  void b(Label* label, Condition cond);
+
+  // Unconditional branch to PC offset.
+  void b(int imm26);
+
+  // Conditional branch to PC offset.
+  void b(int imm19, Condition cond);
+
+  // Branch with link to label.
+  void bl(Label* label);
+
+  // Branch with link to PC offset.
+  void bl(int imm26);
+
+  // Compare and branch to label if zero.
+  void cbz(const Register& rt, Label* label);
+
+  // Compare and branch to PC offset if zero.
+  void cbz(const Register& rt, int imm19);
+
+  // Compare and branch to label if not zero.
+  void cbnz(const Register& rt, Label* label);
+
+  // Compare and branch to PC offset if not zero.
+  void cbnz(const Register& rt, int imm19);
+
+  // Test bit and branch to label if zero.
+  void tbz(const Register& rt, unsigned bit_pos, Label* label);
+
+  // Test bit and branch to PC offset if zero.
+  void tbz(const Register& rt, unsigned bit_pos, int imm14);
+
+  // Test bit and branch to label if not zero.
+  void tbnz(const Register& rt, unsigned bit_pos, Label* label);
+
+  // Test bit and branch to PC offset if not zero.
+  void tbnz(const Register& rt, unsigned bit_pos, int imm14);
+
+  // Address calculation instructions.
+  // Calculate a PC-relative address. Unlike for branches the offset in adr is
+  // unscaled (i.e. the result can be unaligned).
+
+  // Calculate the address of a label.
+  void adr(const Register& rd, Label* label);
+
+  // Calculate the address of a PC offset.
+  void adr(const Register& rd, int imm21);
+
+  // Data Processing instructions.
+  // Add.
+  void add(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Compare negative.
+  void cmn(const Register& rn, const Operand& operand);
+
+  // Subtract.
+  void sub(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Compare.
+  void cmp(const Register& rn, const Operand& operand);
+
+  // Negate.
+  void neg(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Add with carry bit.
+  void adc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Subtract with carry bit.
+  void sbc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Negate with carry bit.
+  void ngc(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Logical instructions.
+  // Bitwise and (A & B).
+  void and_(const Register& rd,
+            const Register& rn,
+            const Operand& operand,
+            FlagsUpdate S = LeaveFlags);
+
+  // Bit test and set flags.
+  void tst(const Register& rn, const Operand& operand);
+
+  // Bit clear (A & ~B).
+  void bic(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+
+  // Bitwise or (A | B).
+  void orr(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Bitwise nor (A | ~B).
+  void orn(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Bitwise eor/xor (A ^ B).
+  void eor(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Bitwise enor/xnor (A ^ ~B).
+  void eon(const Register& rd, const Register& rn, const Operand& operand);
+
+  // Logical shift left by variable.
+  void lslv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Logical shift right by variable.
+  void lsrv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Arithmetic shift right by variable.
+  void asrv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Rotate right by variable.
+  void rorv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Bitfield instructions.
+  // Bitfield move.
+  void bfm(const Register& rd,
+           const Register& rn,
+           unsigned immr,
+           unsigned imms);
+
+  // Signed bitfield move.
+  void sbfm(const Register& rd,
+            const Register& rn,
+            unsigned immr,
+            unsigned imms);
+
+  // Unsigned bitfield move.
+  void ubfm(const Register& rd,
+            const Register& rn,
+            unsigned immr,
+            unsigned imms);
+
+  // Bfm aliases.
+  // Bitfield insert.
+  inline void bfi(const Register& rd,
+                  const Register& rn,
+                  unsigned lsb,
+                  unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    bfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1);
+  }
+
+  // Bitfield extract and insert low.
+  inline void bfxil(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    bfm(rd, rn, lsb, lsb + width - 1);
+  }
+
+  // Sbfm aliases.
+  // Arithmetic shift right.
+  inline void asr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(shift < rd.size());
+    sbfm(rd, rn, shift, rd.size() - 1);
+  }
+
+  // Signed bitfield insert with zero at right.
+  inline void sbfiz(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    sbfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1);
+  }
+
+  // Signed bitfield extract.
+  inline void sbfx(const Register& rd,
+                   const Register& rn,
+                   unsigned lsb,
+                   unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    sbfm(rd, rn, lsb, lsb + width - 1);
+  }
+
+  // Signed extend byte.
+  inline void sxtb(const Register& rd, const Register& rn) {
+    sbfm(rd, rn, 0, 7);
+  }
+
+  // Signed extend halfword.
+  inline void sxth(const Register& rd, const Register& rn) {
+    sbfm(rd, rn, 0, 15);
+  }
+
+  // Signed extend word.
+  inline void sxtw(const Register& rd, const Register& rn) {
+    sbfm(rd, rn, 0, 31);
+  }
+
+  // Ubfm aliases.
+  // Logical shift left.
+  inline void lsl(const Register& rd, const Register& rn, unsigned shift) {
+    unsigned reg_size = rd.size();
+    ASSERT(shift < reg_size);
+    ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1);
+  }
+
+  // Logical shift right.
+  inline void lsr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(shift < rd.size());
+    ubfm(rd, rn, shift, rd.size() - 1);
+  }
+
+  // Unsigned bitfield insert with zero at right.
+  inline void ubfiz(const Register& rd,
+                    const Register& rn,
+                    unsigned lsb,
+                    unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    ubfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1);
+  }
+
+  // Unsigned bitfield extract.
+  inline void ubfx(const Register& rd,
+                   const Register& rn,
+                   unsigned lsb,
+                   unsigned width) {
+    ASSERT(width >= 1);
+    ASSERT(lsb + width <= rn.size());
+    ubfm(rd, rn, lsb, lsb + width - 1);
+  }
+
+  // Unsigned extend byte.
+  inline void uxtb(const Register& rd, const Register& rn) {
+    ubfm(rd, rn, 0, 7);
+  }
+
+  // Unsigned extend halfword.
+  inline void uxth(const Register& rd, const Register& rn) {
+    ubfm(rd, rn, 0, 15);
+  }
+
+  // Unsigned extend word.
+  inline void uxtw(const Register& rd, const Register& rn) {
+    ubfm(rd, rn, 0, 31);
+  }
+
+  // Extract.
+  void extr(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            unsigned lsb);
+
+  // Conditional select: rd = cond ? rn : rm.
+  void csel(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            Condition cond);
+
+  // Conditional select increment: rd = cond ? rn : rm + 1.
+  void csinc(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond);
+
+  // Conditional select inversion: rd = cond ? rn : ~rm.
+  void csinv(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond);
+
+  // Conditional select negation: rd = cond ? rn : -rm.
+  void csneg(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond);
+
+  // Conditional set: rd = cond ? 1 : 0.
+  void cset(const Register& rd, Condition cond);
+
+  // Conditional set mask: rd = cond ? -1 : 0.
+  void csetm(const Register& rd, Condition cond);
+
+  // Conditional increment: rd = cond ? rn + 1 : rn.
+  void cinc(const Register& rd, const Register& rn, Condition cond);
+
+  // Conditional invert: rd = cond ? ~rn : rn.
+  void cinv(const Register& rd, const Register& rn, Condition cond);
+
+  // Conditional negate: rd = cond ? -rn : rn.
+  void cneg(const Register& rd, const Register& rn, Condition cond);
+
+  // Rotate right.
+  inline void ror(const Register& rd, const Register& rs, unsigned shift) {
+    extr(rd, rs, rs, shift);
+  }
+
+  // Conditional comparison.
+  // Conditional compare negative.
+  void ccmn(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+
+  // Conditional compare.
+  void ccmp(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+
+  // Multiply.
+  void mul(const Register& rd, const Register& rn, const Register& rm);
+
+  // Negated multiply.
+  void mneg(const Register& rd, const Register& rn, const Register& rm);
+
+  // Signed long multiply: 32 x 32 -> 64-bit.
+  void smull(const Register& rd, const Register& rn, const Register& rm);
+
+  // Signed multiply high: 64 x 64 -> 64-bit <127:64>.
+  void smulh(const Register& xd, const Register& xn, const Register& xm);
+
+  // Multiply and accumulate.
+  void madd(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra);
+
+  // Multiply and subtract.
+  void msub(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra);
+
+  // Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+  void smaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit.
+  void umaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+  void smsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit.
+  void umsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra);
+
+  // Signed integer divide.
+  void sdiv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Unsigned integer divide.
+  void udiv(const Register& rd, const Register& rn, const Register& rm);
+
+  // Bit reverse.
+  void rbit(const Register& rd, const Register& rn);
+
+  // Reverse bytes in 16-bit half words.
+  void rev16(const Register& rd, const Register& rn);
+
+  // Reverse bytes in 32-bit words.
+  void rev32(const Register& rd, const Register& rn);
+
+  // Reverse bytes.
+  void rev(const Register& rd, const Register& rn);
+
+  // Count leading zeroes.
+  void clz(const Register& rd, const Register& rn);
+
+  // Count leading sign bits.
+  void cls(const Register& rd, const Register& rn);
+
+  // Memory instructions.
+  // Load integer or FP register.
+  void ldr(const CPURegister& rt, const MemOperand& src);
+
+  // Store integer or FP register.
+  void str(const CPURegister& rt, const MemOperand& dst);
+
+  // Load word with sign extension.
+  void ldrsw(const Register& rt, const MemOperand& src);
+
+  // Load byte.
+  void ldrb(const Register& rt, const MemOperand& src);
+
+  // Store byte.
+  void strb(const Register& rt, const MemOperand& dst);
+
+  // Load byte with sign extension.
+  void ldrsb(const Register& rt, const MemOperand& src);
+
+  // Load half-word.
+  void ldrh(const Register& rt, const MemOperand& src);
+
+  // Store half-word.
+  void strh(const Register& rt, const MemOperand& dst);
+
+  // Load half-word with sign extension.
+  void ldrsh(const Register& rt, const MemOperand& src);
+
+  // Load integer or FP register pair.
+  void ldp(const CPURegister& rt, const CPURegister& rt2,
+           const MemOperand& src);
+
+  // Store integer or FP register pair.
+  void stp(const CPURegister& rt, const CPURegister& rt2,
+           const MemOperand& dst);
+
+  // Load word pair with sign extension.
+  void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src);
+
+  // Load integer or FP register pair, non-temporal.
+  void ldnp(const CPURegister& rt, const CPURegister& rt2,
+            const MemOperand& src);
+
+  // Store integer or FP register pair, non-temporal.
+  void stnp(const CPURegister& rt, const CPURegister& rt2,
+            const MemOperand& dst);
+
+  // Load literal to register.
+  void ldr(const Register& rt, uint64_t imm);
+
+  // Load literal to FP register.
+  void ldr(const FPRegister& ft, double imm);
+
+  // Move instructions. The default shift of -1 indicates that the move
+  // instruction will calculate an appropriate 16-bit immediate and left shift
+  // that is equal to the 64-bit immediate argument. If an explicit left shift
+  // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value.
+  //
+  // For movk, an explicit shift can be used to indicate which half word should
+  // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant
+  // half word with zero, whereas movk(x0, 0, 48) will overwrite the
+  // most-significant.
+
+  // Move immediate and keep.
+  void movk(const Register& rd, uint64_t imm, int shift = -1) {
+    MoveWide(rd, imm, shift, MOVK);
+  }
+
+  // Move inverted immediate.
+  void movn(const Register& rd, uint64_t imm, int shift = -1) {
+    MoveWide(rd, imm, shift, MOVN);
+  }
+
+  // Move immediate.
+  void movz(const Register& rd, uint64_t imm, int shift = -1) {
+    MoveWide(rd, imm, shift, MOVZ);
+  }
+
+  // Misc instructions.
+  // Monitor debug-mode breakpoint.
+  void brk(int code);
+
+  // Halting debug-mode breakpoint.
+  void hlt(int code);
+
+  // Move register to register.
+  void mov(const Register& rd, const Register& rn);
+
+  // Move inverted operand to register.
+  void mvn(const Register& rd, const Operand& operand);
+
+  // System instructions.
+  // Move to register from system register.
+  void mrs(const Register& rt, SystemRegister sysreg);
+
+  // Move from register to system register.
+  void msr(SystemRegister sysreg, const Register& rt);
+
+  // System hint.
+  void hint(SystemHint code);
+
+  // Alias for system instructions.
+  // No-op.
+  void nop() {
+    hint(NOP);
+  }
+
+  // FP instructions.
+  // Move immediate to FP register.
+  void fmov(FPRegister fd, double imm);
+
+  // Move FP register to register.
+  void fmov(Register rd, FPRegister fn);
+
+  // Move register to FP register.
+  void fmov(FPRegister fd, Register rn);
+
+  // Move FP register to FP register.
+  void fmov(FPRegister fd, FPRegister fn);
+
+  // FP add.
+  void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP subtract.
+  void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP multiply.
+  void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP multiply and subtract.
+  void fmsub(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             const FPRegister& fa);
+
+  // FP divide.
+  void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP maximum.
+  void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP minimum.
+  void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
+
+  // FP absolute.
+  void fabs(const FPRegister& fd, const FPRegister& fn);
+
+  // FP negate.
+  void fneg(const FPRegister& fd, const FPRegister& fn);
+
+  // FP square root.
+  void fsqrt(const FPRegister& fd, const FPRegister& fn);
+
+  // FP round to integer (nearest with ties to even).
+  void frintn(const FPRegister& fd, const FPRegister& fn);
+
+  // FP round to integer (towards zero).
+  void frintz(const FPRegister& fd, const FPRegister& fn);
+
+  // FP compare registers.
+  void fcmp(const FPRegister& fn, const FPRegister& fm);
+
+  // FP compare immediate.
+  void fcmp(const FPRegister& fn, double value);
+
+  // FP conditional compare.
+  void fccmp(const FPRegister& fn,
+             const FPRegister& fm,
+             StatusFlags nzcv,
+             Condition cond);
+
+  // FP conditional select.
+  void fcsel(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             Condition cond);
+
+  // Common FP Convert function.
+  void FPConvertToInt(const Register& rd,
+                      const FPRegister& fn,
+                      FPIntegerConvertOp op);
+
+  // FP convert between single and double precision.
+  void fcvt(const FPRegister& fd, const FPRegister& fn);
+
+  // Convert FP to unsigned integer (round towards -infinity).
+  void fcvtmu(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to signed integer (round towards -infinity).
+  void fcvtms(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to unsigned integer (nearest with ties to even).
+  void fcvtnu(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to signed integer (nearest with ties to even).
+  void fcvtns(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to unsigned integer (round towards zero).
+  void fcvtzu(const Register& rd, const FPRegister& fn);
+
+  // Convert FP to signed integer (round towards zero).
+  void fcvtzs(const Register& rd, const FPRegister& fn);
+
+  // Convert signed integer or fixed point to FP.
+  void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
+
+  // Convert unsigned integer or fixed point to FP.
+  void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
+
+  // Emit generic instructions.
+  // Emit raw instructions into the instruction stream.
+  inline void dci(Instr raw_inst) { Emit(raw_inst); }
+
+  // Emit 32 bits of data into the instruction stream.
+  inline void dc32(uint32_t data) { EmitData(&data, sizeof(data)); }
+
+  // Emit 64 bits of data into the instruction stream.
+  inline void dc64(uint64_t data) { EmitData(&data, sizeof(data)); }
+
+  // Copy a string into the instruction stream, including the terminating NULL
+  // character. The instruction pointer (pc_) is then aligned correctly for
+  // subsequent instructions.
+  void EmitStringData(const char * string) {
+    ASSERT(string != NULL);
+
+    size_t len = strlen(string) + 1;
+    EmitData(string, len);
+
+    // Pad with NULL characters until pc_ is aligned.
+    const char pad[] = {'\0', '\0', '\0', '\0'};
+    ASSERT(sizeof(pad) == kInstructionSize);
+    Instruction* next_pc = AlignUp(pc_, kInstructionSize);
+    EmitData(&pad, next_pc - pc_);
+  }
+
+  // Code generation helpers.
+
+  // Register encoding.
+  static Instr Rd(CPURegister rd) {
+    ASSERT(rd.code() != kSPRegInternalCode);
+    return rd.code() << Rd_offset;
+  }
+
+  static Instr Rn(CPURegister rn) {
+    ASSERT(rn.code() != kSPRegInternalCode);
+    return rn.code() << Rn_offset;
+  }
+
+  static Instr Rm(CPURegister rm) {
+    ASSERT(rm.code() != kSPRegInternalCode);
+    return rm.code() << Rm_offset;
+  }
+
+  static Instr Ra(CPURegister ra) {
+    ASSERT(ra.code() != kSPRegInternalCode);
+    return ra.code() << Ra_offset;
+  }
+
+  static Instr Rt(CPURegister rt) {
+    ASSERT(rt.code() != kSPRegInternalCode);
+    return rt.code() << Rt_offset;
+  }
+
+  static Instr Rt2(CPURegister rt2) {
+    ASSERT(rt2.code() != kSPRegInternalCode);
+    return rt2.code() << Rt2_offset;
+  }
+
+  // These encoding functions allow the stack pointer to be encoded, and
+  // disallow the zero register.
+  static Instr RdSP(Register rd) {
+    ASSERT(!rd.IsZero());
+    return (rd.code() & kRegCodeMask) << Rd_offset;
+  }
+
+  static Instr RnSP(Register rn) {
+    ASSERT(!rn.IsZero());
+    return (rn.code() & kRegCodeMask) << Rn_offset;
+  }
+
+  // Flags encoding.
+  static Instr Flags(FlagsUpdate S) {
+    if (S == SetFlags) {
+      return 1 << FlagsUpdate_offset;
+    } else if (S == LeaveFlags) {
+      return 0 << FlagsUpdate_offset;
+    }
+    UNREACHABLE();
+    return 0;
+  }
+
+  static Instr Cond(Condition cond) {
+    return cond << Condition_offset;
+  }
+
+  // PC-relative address encoding.
+  static Instr ImmPCRelAddress(int imm21) {
+    ASSERT(is_int21(imm21));
+    Instr imm = static_cast<Instr>(truncate_to_int21(imm21));
+    Instr immhi = (imm >> ImmPCRelLo_width) << ImmPCRelHi_offset;
+    Instr immlo = imm << ImmPCRelLo_offset;
+    return (immhi & ImmPCRelHi_mask) | (immlo & ImmPCRelLo_mask);
+  }
+
+  // Branch encoding.
+  static Instr ImmUncondBranch(int imm26) {
+    ASSERT(is_int26(imm26));
+    return truncate_to_int26(imm26) << ImmUncondBranch_offset;
+  }
+
+  static Instr ImmCondBranch(int imm19) {
+    ASSERT(is_int19(imm19));
+    return truncate_to_int19(imm19) << ImmCondBranch_offset;
+  }
+
+  static Instr ImmCmpBranch(int imm19) {
+    ASSERT(is_int19(imm19));
+    return truncate_to_int19(imm19) << ImmCmpBranch_offset;
+  }
+
+  static Instr ImmTestBranch(int imm14) {
+    ASSERT(is_int14(imm14));
+    return truncate_to_int14(imm14) << ImmTestBranch_offset;
+  }
+
+  static Instr ImmTestBranchBit(unsigned bit_pos) {
+    ASSERT(is_uint6(bit_pos));
+    // Subtract five from the shift offset, as we need bit 5 from bit_pos.
+    unsigned b5 = bit_pos << (ImmTestBranchBit5_offset - 5);
+    unsigned b40 = bit_pos << ImmTestBranchBit40_offset;
+    b5 &= ImmTestBranchBit5_mask;
+    b40 &= ImmTestBranchBit40_mask;
+    return b5 | b40;
+  }
+
+  // Data Processing encoding.
+  static Instr SF(Register rd) {
+      return rd.Is64Bits() ? SixtyFourBits : ThirtyTwoBits;
+  }
+
+  static Instr ImmAddSub(int64_t imm) {
+    ASSERT(IsImmAddSub(imm));
+    if (is_uint12(imm)) {  // No shift required.
+      return imm << ImmAddSub_offset;
+    } else {
+      return ((imm >> 12) << ImmAddSub_offset) | (1 << ShiftAddSub_offset);
+    }
+  }
+
+  static inline Instr ImmS(unsigned imms, unsigned reg_size) {
+    ASSERT(((reg_size == kXRegSize) && is_uint6(imms)) ||
+           ((reg_size == kWRegSize) && is_uint5(imms)));
+    USE(reg_size);
+    return imms << ImmS_offset;
+  }
+
+  static inline Instr ImmR(unsigned immr, unsigned reg_size) {
+    ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) ||
+           ((reg_size == kWRegSize) && is_uint5(immr)));
+    USE(reg_size);
+    ASSERT(is_uint6(immr));
+    return immr << ImmR_offset;
+  }
+
+  static inline Instr ImmSetBits(unsigned imms, unsigned reg_size) {
+    ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+    ASSERT(is_uint6(imms));
+    ASSERT((reg_size == kXRegSize) || is_uint6(imms + 3));
+    USE(reg_size);
+    return imms << ImmSetBits_offset;
+  }
+
+  static inline Instr ImmRotate(unsigned immr, unsigned reg_size) {
+    ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+    ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) ||
+           ((reg_size == kWRegSize) && is_uint5(immr)));
+    USE(reg_size);
+    return immr << ImmRotate_offset;
+  }
+
+  static inline Instr ImmLLiteral(int imm19) {
+    ASSERT(is_int19(imm19));
+    return truncate_to_int19(imm19) << ImmLLiteral_offset;
+  }
+
+  static inline Instr BitN(unsigned bitn, unsigned reg_size) {
+    ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+    ASSERT((reg_size == kXRegSize) || (bitn == 0));
+    USE(reg_size);
+    return bitn << BitN_offset;
+  }
+
+  static Instr ShiftDP(Shift shift) {
+    ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR);
+    return shift << ShiftDP_offset;
+  }
+
+  static Instr ImmDPShift(unsigned amount) {
+    ASSERT(is_uint6(amount));
+    return amount << ImmDPShift_offset;
+  }
+
+  static Instr ExtendMode(Extend extend) {
+    return extend << ExtendMode_offset;
+  }
+
+  static Instr ImmExtendShift(unsigned left_shift) {
+    ASSERT(left_shift <= 4);
+    return left_shift << ImmExtendShift_offset;
+  }
+
+  static Instr ImmCondCmp(unsigned imm) {
+    ASSERT(is_uint5(imm));
+    return imm << ImmCondCmp_offset;
+  }
+
+  static Instr Nzcv(StatusFlags nzcv) {
+    return ((nzcv >> Flags_offset) & 0xf) << Nzcv_offset;
+  }
+
+  // MemOperand offset encoding.
+  static Instr ImmLSUnsigned(int imm12) {
+    ASSERT(is_uint12(imm12));
+    return imm12 << ImmLSUnsigned_offset;
+  }
+
+  static Instr ImmLS(int imm9) {
+    ASSERT(is_int9(imm9));
+    return truncate_to_int9(imm9) << ImmLS_offset;
+  }
+
+  static Instr ImmLSPair(int imm7, LSDataSize size) {
+    ASSERT(((imm7 >> size) << size) == imm7);
+    int scaled_imm7 = imm7 >> size;
+    ASSERT(is_int7(scaled_imm7));
+    return truncate_to_int7(scaled_imm7) << ImmLSPair_offset;
+  }
+
+  static Instr ImmShiftLS(unsigned shift_amount) {
+    ASSERT(is_uint1(shift_amount));
+    return shift_amount << ImmShiftLS_offset;
+  }
+
+  static Instr ImmException(int imm16) {
+    ASSERT(is_uint16(imm16));
+    return imm16 << ImmException_offset;
+  }
+
+  static Instr ImmSystemRegister(int imm15) {
+    ASSERT(is_uint15(imm15));
+    return imm15 << ImmSystemRegister_offset;
+  }
+
+  static Instr ImmHint(int imm7) {
+    ASSERT(is_uint7(imm7));
+    return imm7 << ImmHint_offset;
+  }
+
+  static LSDataSize CalcLSDataSize(LoadStoreOp op) {
+    ASSERT((SizeLS_offset + SizeLS_width) == (kInstructionSize * 8));
+    return static_cast<LSDataSize>(op >> SizeLS_offset);
+  }
+
+  // Move immediates encoding.
+  static Instr ImmMoveWide(uint64_t imm) {
+    ASSERT(is_uint16(imm));
+    return imm << ImmMoveWide_offset;
+  }
+
+  static Instr ShiftMoveWide(int64_t shift) {
+    ASSERT(is_uint2(shift));
+    return shift << ShiftMoveWide_offset;
+  }
+
+  // FP Immediates.
+  static Instr ImmFP32(float imm);
+  static Instr ImmFP64(double imm);
+
+  // FP register type.
+  static Instr FPType(FPRegister fd) {
+    return fd.Is64Bits() ? FP64 : FP32;
+  }
+
+  static Instr FPScale(unsigned scale) {
+    ASSERT(is_uint6(scale));
+    return scale << FPScale_offset;
+  }
+
+  // Size of the code generated in bytes
+  uint64_t SizeOfCodeGenerated() const {
+    ASSERT((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_)));
+    return pc_ - buffer_;
+  }
+
+  // Size of the code generated since label to the current position.
+  uint64_t SizeOfCodeGeneratedSince(Label* label) const {
+    ASSERT(label->IsBound());
+    ASSERT((pc_ >= label->target()) && (pc_ < (buffer_ + buffer_size_)));
+    return pc_ - label->target();
+  }
+
+
+  inline void BlockLiteralPool() {
+    literal_pool_monitor_++;
+  }
+
+  inline void ReleaseLiteralPool() {
+    if (--literal_pool_monitor_ == 0) {
+      // Has the literal pool been blocked for too long?
+      ASSERT(literals_.empty() ||
+             (pc_ < (literals_.back()->pc_ + kMaxLoadLiteralRange)));
+    }
+  }
+
+  inline bool IsLiteralPoolBlocked() {
+    return literal_pool_monitor_ != 0;
+  }
+
+  void CheckLiteralPool(LiteralPoolEmitOption option = JumpRequired);
+  void EmitLiteralPool(LiteralPoolEmitOption option = NoJumpRequired);
+  size_t LiteralPoolSize();
+
+ protected:
+  inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const {
+    return reg.Is64Bits() ? xzr : wzr;
+  }
+
+
+  void LoadStore(const CPURegister& rt,
+                 const MemOperand& addr,
+                 LoadStoreOp op);
+  static bool IsImmLSUnscaled(ptrdiff_t offset);
+  static bool IsImmLSScaled(ptrdiff_t offset, LSDataSize size);
+
+  void Logical(const Register& rd,
+               const Register& rn,
+               const Operand& operand,
+               LogicalOp op);
+  void LogicalImmediate(const Register& rd,
+                        const Register& rn,
+                        unsigned n,
+                        unsigned imm_s,
+                        unsigned imm_r,
+                        LogicalOp op);
+  static bool IsImmLogical(uint64_t value,
+                           unsigned width,
+                           unsigned* n,
+                           unsigned* imm_s,
+                           unsigned* imm_r);
+
+  void ConditionalCompare(const Register& rn,
+                          const Operand& operand,
+                          StatusFlags nzcv,
+                          Condition cond,
+                          ConditionalCompareOp op);
+  static bool IsImmConditionalCompare(int64_t immediate);
+
+  void AddSubWithCarry(const Register& rd,
+                       const Register& rn,
+                       const Operand& operand,
+                       FlagsUpdate S,
+                       AddSubWithCarryOp op);
+
+  // Functions for emulating operands not directly supported by the instruction
+  // set.
+  void EmitShift(const Register& rd,
+                 const Register& rn,
+                 Shift shift,
+                 unsigned amount);
+  void EmitExtendShift(const Register& rd,
+                       const Register& rn,
+                       Extend extend,
+                       unsigned left_shift);
+
+  void AddSub(const Register& rd,
+              const Register& rn,
+              const Operand& operand,
+              FlagsUpdate S,
+              AddSubOp op);
+  static bool IsImmAddSub(int64_t immediate);
+
+  // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified
+  // registers. Only simple loads are supported; sign- and zero-extension (such
+  // as in LDPSW_x or LDRB_w) are not supported.
+  static LoadStoreOp LoadOpFor(const CPURegister& rt);
+  static LoadStorePairOp LoadPairOpFor(const CPURegister& rt,
+                                       const CPURegister& rt2);
+  static LoadStoreOp StoreOpFor(const CPURegister& rt);
+  static LoadStorePairOp StorePairOpFor(const CPURegister& rt,
+                                        const CPURegister& rt2);
+  static LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2);
+  static LoadStorePairNonTemporalOp StorePairNonTemporalOpFor(
+    const CPURegister& rt, const CPURegister& rt2);
+
+
+ private:
+  // Instruction helpers.
+  void MoveWide(const Register& rd,
+                uint64_t imm,
+                int shift,
+                MoveWideImmediateOp mov_op);
+  void DataProcShiftedRegister(const Register& rd,
+                               const Register& rn,
+                               const Operand& operand,
+                               FlagsUpdate S,
+                               Instr op);
+  void DataProcExtendedRegister(const Register& rd,
+                                const Register& rn,
+                                const Operand& operand,
+                                FlagsUpdate S,
+                                Instr op);
+  void LoadStorePair(const CPURegister& rt,
+                     const CPURegister& rt2,
+                     const MemOperand& addr,
+                     LoadStorePairOp op);
+  void LoadStorePairNonTemporal(const CPURegister& rt,
+                                const CPURegister& rt2,
+                                const MemOperand& addr,
+                                LoadStorePairNonTemporalOp op);
+  void LoadLiteral(const CPURegister& rt, uint64_t imm, LoadLiteralOp op);
+  void ConditionalSelect(const Register& rd,
+                         const Register& rn,
+                         const Register& rm,
+                         Condition cond,
+                         ConditionalSelectOp op);
+  void DataProcessing1Source(const Register& rd,
+                             const Register& rn,
+                             DataProcessing1SourceOp op);
+  void DataProcessing3Source(const Register& rd,
+                             const Register& rn,
+                             const Register& rm,
+                             const Register& ra,
+                             DataProcessing3SourceOp op);
+  void FPDataProcessing1Source(const FPRegister& fd,
+                               const FPRegister& fn,
+                               FPDataProcessing1SourceOp op);
+  void FPDataProcessing2Source(const FPRegister& fd,
+                               const FPRegister& fn,
+                               const FPRegister& fm,
+                               FPDataProcessing2SourceOp op);
+  void FPDataProcessing3Source(const FPRegister& fd,
+                               const FPRegister& fn,
+                               const FPRegister& fm,
+                               const FPRegister& fa,
+                               FPDataProcessing3SourceOp op);
+
+  // Encoding helpers.
+  static bool IsImmFP32(float imm);
+  static bool IsImmFP64(double imm);
+
+  void RecordLiteral(int64_t imm, unsigned size);
+
+  // Emit the instruction at pc_.
+  void Emit(Instr instruction) {
+    ASSERT(sizeof(*pc_) == 1);
+    ASSERT(sizeof(instruction) == kInstructionSize);
+    ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_));
+
+#ifdef DEBUG
+    finalized_ = false;
+#endif
+
+    memcpy(pc_, &instruction, sizeof(instruction));
+    pc_ += sizeof(instruction);
+    CheckBufferSpace();
+  }
+
+  // Emit data inline in the instruction stream.
+  void EmitData(void const * data, unsigned size) {
+    ASSERT(sizeof(*pc_) == 1);
+    ASSERT((pc_ + size) <= (buffer_ + buffer_size_));
+
+#ifdef DEBUG
+    finalized_ = false;
+#endif
+
+    // TODO: Record this 'instruction' as data, so that it can be disassembled
+    // correctly.
+    memcpy(pc_, data, size);
+    pc_ += size;
+    CheckBufferSpace();
+  }
+
+  inline void CheckBufferSpace() {
+    ASSERT(pc_ < (buffer_ + buffer_size_));
+    if (pc_ > next_literal_pool_check_) {
+      CheckLiteralPool();
+    }
+  }
+
+  // The buffer into which code and relocation info are generated.
+  Instruction* buffer_;
+  // Buffer size, in bytes.
+  unsigned buffer_size_;
+  Instruction* pc_;
+  std::list<Literal*> literals_;
+  Instruction* next_literal_pool_check_;
+  unsigned literal_pool_monitor_;
+
+  friend class BlockLiteralPoolScope;
+
+#ifdef DEBUG
+  bool finalized_;
+#endif
+};
+
+class BlockLiteralPoolScope {
+ public:
+  explicit BlockLiteralPoolScope(Assembler* assm) : assm_(assm) {
+    assm_->BlockLiteralPool();
+  }
+
+  ~BlockLiteralPoolScope() {
+    assm_->ReleaseLiteralPool();
+  }
+
+ private:
+  Assembler* assm_;
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_ASSEMBLER_A64_H_
diff --git a/disas/libvixl/src/a64/constants-a64.h b/disas/libvixl/src/a64/constants-a64.h
new file mode 100644
index 0000000..2e0336d
--- /dev/null
+++ b/disas/libvixl/src/a64/constants-a64.h
@@ -0,0 +1,1104 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_CONSTANTS_A64_H_
+#define VIXL_A64_CONSTANTS_A64_H_
+
+namespace vixl {
+
+const unsigned kNumberOfRegisters = 32;
+const unsigned kNumberOfFPRegisters = 32;
+// Callee saved registers are x21-x30(lr).
+const int kNumberOfCalleeSavedRegisters = 10;
+const int kFirstCalleeSavedRegisterIndex = 21;
+// Callee saved FP registers are d8-d15.
+const int kNumberOfCalleeSavedFPRegisters = 8;
+const int kFirstCalleeSavedFPRegisterIndex = 8;
+
+#define REGISTER_CODE_LIST(R)                                                  \
+R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
+R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
+R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
+R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
+#define INSTRUCTION_FIELDS_LIST(V_)                                            \
+/* Register fields */                                                          \
+V_(Rd, 4, 0, Bits)                        /* Destination register.     */      \
+V_(Rn, 9, 5, Bits)                        /* First source register.    */      \
+V_(Rm, 20, 16, Bits)                      /* Second source register.   */      \
+V_(Ra, 14, 10, Bits)                      /* Third source register.    */      \
+V_(Rt, 4, 0, Bits)                        /* Load dest / store source. */      \
+V_(Rt2, 14, 10, Bits)                     /* Load second dest /        */      \
+                                         /* store second source.      */       \
+V_(PrefetchMode, 4, 0, Bits)                                                   \
+                                                                               \
+/* Common bits */                                                              \
+V_(SixtyFourBits, 31, 31, Bits)                                                \
+V_(FlagsUpdate, 29, 29, Bits)                                                  \
+                                                                               \
+/* PC relative addressing */                                                   \
+V_(ImmPCRelHi, 23, 5, SignedBits)                                              \
+V_(ImmPCRelLo, 30, 29, Bits)                                                   \
+                                                                               \
+/* Add/subtract/logical shift register */                                      \
+V_(ShiftDP, 23, 22, Bits)                                                      \
+V_(ImmDPShift, 15, 10, Bits)                                                   \
+                                                                               \
+/* Add/subtract immediate */                                                   \
+V_(ImmAddSub, 21, 10, Bits)                                                    \
+V_(ShiftAddSub, 23, 22, Bits)                                                  \
+                                                                               \
+/* Add/substract extend */                                                     \
+V_(ImmExtendShift, 12, 10, Bits)                                               \
+V_(ExtendMode, 15, 13, Bits)                                                   \
+                                                                               \
+/* Move wide */                                                                \
+V_(ImmMoveWide, 20, 5, Bits)                                                   \
+V_(ShiftMoveWide, 22, 21, Bits)                                                \
+                                                                               \
+/* Logical immediate, bitfield and extract */                                  \
+V_(BitN, 22, 22, Bits)                                                         \
+V_(ImmRotate, 21, 16, Bits)                                                    \
+V_(ImmSetBits, 15, 10, Bits)                                                   \
+V_(ImmR, 21, 16, Bits)                                                         \
+V_(ImmS, 15, 10, Bits)                                                         \
+                                                                               \
+/* Test and branch immediate */                                                \
+V_(ImmTestBranch, 18, 5, SignedBits)                                           \
+V_(ImmTestBranchBit40, 23, 19, Bits)                                           \
+V_(ImmTestBranchBit5, 31, 31, Bits)                                            \
+                                                                               \
+/* Conditionals */                                                             \
+V_(Condition, 15, 12, Bits)                                                    \
+V_(ConditionBranch, 3, 0, Bits)                                                \
+V_(Nzcv, 3, 0, Bits)                                                           \
+V_(ImmCondCmp, 20, 16, Bits)                                                   \
+V_(ImmCondBranch, 23, 5, SignedBits)                                           \
+                                                                               \
+/* Floating point */                                                           \
+V_(FPType, 23, 22, Bits)                                                       \
+V_(ImmFP, 20, 13, Bits)                                                        \
+V_(FPScale, 15, 10, Bits)                                                      \
+                                                                               \
+/* Load Store */                                                               \
+V_(ImmLS, 20, 12, SignedBits)                                                  \
+V_(ImmLSUnsigned, 21, 10, Bits)                                                \
+V_(ImmLSPair, 21, 15, SignedBits)                                              \
+V_(SizeLS, 31, 30, Bits)                                                       \
+V_(ImmShiftLS, 12, 12, Bits)                                                   \
+                                                                               \
+/* Other immediates */                                                         \
+V_(ImmUncondBranch, 25, 0, SignedBits)                                         \
+V_(ImmCmpBranch, 23, 5, SignedBits)                                            \
+V_(ImmLLiteral, 23, 5, SignedBits)                                             \
+V_(ImmException, 20, 5, Bits)                                                  \
+V_(ImmHint, 11, 5, Bits)                                                       \
+                                                                               \
+/* System (MRS, MSR) */                                                        \
+V_(ImmSystemRegister, 19, 5, Bits)                                             \
+V_(SysO0, 19, 19, Bits)                                                        \
+V_(SysOp1, 18, 16, Bits)                                                       \
+V_(SysOp2, 7, 5, Bits)                                                         \
+V_(CRn, 15, 12, Bits)                                                          \
+V_(CRm, 11, 8, Bits)                                                           \
+
+
+#define SYSTEM_REGISTER_FIELDS_LIST(V_, M_)                                    \
+/* NZCV */                                                                     \
+V_(Flags, 31, 28, Bits)                                                        \
+V_(N, 31, 31, Bits)                                                            \
+V_(Z, 30, 30, Bits)                                                            \
+V_(C, 29, 29, Bits)                                                            \
+V_(V, 28, 28, Bits)                                                            \
+M_(NZCV, Flags_mask)                                                           \
+                                                                               \
+/* FPCR */                                                                     \
+V_(AHP, 26, 26, Bits)                                                          \
+V_(DN, 25, 25, Bits)                                                           \
+V_(FZ, 24, 24, Bits)                                                           \
+V_(RMode, 23, 22, Bits)                                                        \
+M_(FPCR, AHP_mask | DN_mask | FZ_mask | RMode_mask)
+
+
+// Fields offsets.
+#define DECLARE_FIELDS_OFFSETS(Name, HighBit, LowBit, X)                       \
+const int Name##_offset = LowBit;                                              \
+const int Name##_width = HighBit - LowBit + 1;                                 \
+const uint32_t Name##_mask = ((1 << Name##_width) - 1) << LowBit;
+#define NOTHING(A, B)
+INSTRUCTION_FIELDS_LIST(DECLARE_FIELDS_OFFSETS)
+SYSTEM_REGISTER_FIELDS_LIST(DECLARE_FIELDS_OFFSETS, NOTHING)
+#undef NOTHING
+#undef DECLARE_FIELDS_BITS
+
+// ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), formed
+// from ImmPCRelLo and ImmPCRelHi.
+const int ImmPCRel_mask = ImmPCRelLo_mask | ImmPCRelHi_mask;
+
+// Condition codes.
+enum Condition {
+  eq = 0,
+  ne = 1,
+  hs = 2,
+  lo = 3,
+  mi = 4,
+  pl = 5,
+  vs = 6,
+  vc = 7,
+  hi = 8,
+  ls = 9,
+  ge = 10,
+  lt = 11,
+  gt = 12,
+  le = 13,
+  al = 14,
+  nv = 15  // Behaves as always/al.
+};
+
+inline Condition InvertCondition(Condition cond) {
+  // Conditions al and nv behave identically, as "always true". They can't be
+  // inverted, because there is no "always false" condition.
+  ASSERT((cond != al) && (cond != nv));
+  return static_cast<Condition>(cond ^ 1);
+}
+
+enum FlagsUpdate {
+  SetFlags   = 1,
+  LeaveFlags = 0
+};
+
+enum StatusFlags {
+  NoFlag    = 0,
+
+  // Derive the flag combinations from the system register bit descriptions.
+  NFlag     = N_mask,
+  ZFlag     = Z_mask,
+  CFlag     = C_mask,
+  VFlag     = V_mask,
+  NZFlag    = NFlag | ZFlag,
+  NCFlag    = NFlag | CFlag,
+  NVFlag    = NFlag | VFlag,
+  ZCFlag    = ZFlag | CFlag,
+  ZVFlag    = ZFlag | VFlag,
+  CVFlag    = CFlag | VFlag,
+  NZCFlag   = NFlag | ZFlag | CFlag,
+  NZVFlag   = NFlag | ZFlag | VFlag,
+  NCVFlag   = NFlag | CFlag | VFlag,
+  ZCVFlag   = ZFlag | CFlag | VFlag,
+  NZCVFlag  = NFlag | ZFlag | CFlag | VFlag,
+
+  // Floating-point comparison results.
+  FPEqualFlag       = ZCFlag,
+  FPLessThanFlag    = NFlag,
+  FPGreaterThanFlag = CFlag,
+  FPUnorderedFlag   = CVFlag
+};
+
+enum Shift {
+  NO_SHIFT = -1,
+  LSL = 0x0,
+  LSR = 0x1,
+  ASR = 0x2,
+  ROR = 0x3
+};
+
+enum Extend {
+  NO_EXTEND = -1,
+  UXTB      = 0,
+  UXTH      = 1,
+  UXTW      = 2,
+  UXTX      = 3,
+  SXTB      = 4,
+  SXTH      = 5,
+  SXTW      = 6,
+  SXTX      = 7
+};
+
+enum SystemHint {
+  NOP   = 0,
+  YIELD = 1,
+  WFE   = 2,
+  WFI   = 3,
+  SEV   = 4,
+  SEVL  = 5
+};
+
+// System/special register names.
+// This information is not encoded as one field but as the concatenation of
+// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
+enum SystemRegister {
+  NZCV = ((0x1 << SysO0_offset) |
+          (0x3 << SysOp1_offset) |
+          (0x4 << CRn_offset) |
+          (0x2 << CRm_offset) |
+          (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset,
+  FPCR = ((0x1 << SysO0_offset) |
+          (0x3 << SysOp1_offset) |
+          (0x4 << CRn_offset) |
+          (0x4 << CRm_offset) |
+          (0x0 << SysOp2_offset)) >> ImmSystemRegister_offset
+};
+
+// Instruction enumerations.
+//
+// These are the masks that define a class of instructions, and the list of
+// instructions within each class. Each enumeration has a Fixed, FMask and
+// Mask value.
+//
+// Fixed: The fixed bits in this instruction class.
+// FMask: The mask used to extract the fixed bits in the class.
+// Mask:  The mask used to identify the instructions within a class.
+//
+// The enumerations can be used like this:
+//
+// ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed);
+// switch(instr->Mask(PCRelAddressingMask)) {
+//   case ADR:  Format("adr 'Xd, 'AddrPCRelByte"); break;
+//   case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break;
+//   default:   printf("Unknown instruction\n");
+// }
+
+
+// Generic fields.
+enum GenericInstrField {
+  SixtyFourBits        = 0x80000000,
+  ThirtyTwoBits        = 0x00000000,
+  FP32                 = 0x00000000,
+  FP64                 = 0x00400000
+};
+
+// PC relative addressing.
+enum PCRelAddressingOp {
+  PCRelAddressingFixed = 0x10000000,
+  PCRelAddressingFMask = 0x1F000000,
+  PCRelAddressingMask  = 0x9F000000,
+  ADR                  = PCRelAddressingFixed | 0x00000000,
+  ADRP                 = PCRelAddressingFixed | 0x80000000
+};
+
+// Add/sub (immediate, shifted and extended.)
+const int kSFOffset = 31;
+enum AddSubOp {
+  AddSubOpMask      = 0x60000000,
+  AddSubSetFlagsBit = 0x20000000,
+  ADD               = 0x00000000,
+  ADDS              = ADD | AddSubSetFlagsBit,
+  SUB               = 0x40000000,
+  SUBS              = SUB | AddSubSetFlagsBit
+};
+
+#define ADD_SUB_OP_LIST(V)  \
+  V(ADD),                   \
+  V(ADDS),                  \
+  V(SUB),                   \
+  V(SUBS)
+
+enum AddSubImmediateOp {
+  AddSubImmediateFixed = 0x11000000,
+  AddSubImmediateFMask = 0x1F000000,
+  AddSubImmediateMask  = 0xFF000000,
+  #define ADD_SUB_IMMEDIATE(A)           \
+  A##_w_imm = AddSubImmediateFixed | A,  \
+  A##_x_imm = AddSubImmediateFixed | A | SixtyFourBits
+  ADD_SUB_OP_LIST(ADD_SUB_IMMEDIATE)
+  #undef ADD_SUB_IMMEDIATE
+};
+
+enum AddSubShiftedOp {
+  AddSubShiftedFixed   = 0x0B000000,
+  AddSubShiftedFMask   = 0x1F200000,
+  AddSubShiftedMask    = 0xFF200000,
+  #define ADD_SUB_SHIFTED(A)             \
+  A##_w_shift = AddSubShiftedFixed | A,  \
+  A##_x_shift = AddSubShiftedFixed | A | SixtyFourBits
+  ADD_SUB_OP_LIST(ADD_SUB_SHIFTED)
+  #undef ADD_SUB_SHIFTED
+};
+
+enum AddSubExtendedOp {
+  AddSubExtendedFixed  = 0x0B200000,
+  AddSubExtendedFMask  = 0x1F200000,
+  AddSubExtendedMask   = 0xFFE00000,
+  #define ADD_SUB_EXTENDED(A)           \
+  A##_w_ext = AddSubExtendedFixed | A,  \
+  A##_x_ext = AddSubExtendedFixed | A | SixtyFourBits
+  ADD_SUB_OP_LIST(ADD_SUB_EXTENDED)
+  #undef ADD_SUB_EXTENDED
+};
+
+// Add/sub with carry.
+enum AddSubWithCarryOp {
+  AddSubWithCarryFixed = 0x1A000000,
+  AddSubWithCarryFMask = 0x1FE00000,
+  AddSubWithCarryMask  = 0xFFE0FC00,
+  ADC_w                = AddSubWithCarryFixed | ADD,
+  ADC_x                = AddSubWithCarryFixed | ADD | SixtyFourBits,
+  ADC                  = ADC_w,
+  ADCS_w               = AddSubWithCarryFixed | ADDS,
+  ADCS_x               = AddSubWithCarryFixed | ADDS | SixtyFourBits,
+  SBC_w                = AddSubWithCarryFixed | SUB,
+  SBC_x                = AddSubWithCarryFixed | SUB | SixtyFourBits,
+  SBC                  = SBC_w,
+  SBCS_w               = AddSubWithCarryFixed | SUBS,
+  SBCS_x               = AddSubWithCarryFixed | SUBS | SixtyFourBits
+};
+
+
+// Logical (immediate and shifted register).
+enum LogicalOp {
+  LogicalOpMask = 0x60200000,
+  NOT   = 0x00200000,
+  AND   = 0x00000000,
+  BIC   = AND | NOT,
+  ORR   = 0x20000000,
+  ORN   = ORR | NOT,
+  EOR   = 0x40000000,
+  EON   = EOR | NOT,
+  ANDS  = 0x60000000,
+  BICS  = ANDS | NOT
+};
+
+// Logical immediate.
+enum LogicalImmediateOp {
+  LogicalImmediateFixed = 0x12000000,
+  LogicalImmediateFMask = 0x1F800000,
+  LogicalImmediateMask  = 0xFF800000,
+  AND_w_imm   = LogicalImmediateFixed | AND,
+  AND_x_imm   = LogicalImmediateFixed | AND | SixtyFourBits,
+  ORR_w_imm   = LogicalImmediateFixed | ORR,
+  ORR_x_imm   = LogicalImmediateFixed | ORR | SixtyFourBits,
+  EOR_w_imm   = LogicalImmediateFixed | EOR,
+  EOR_x_imm   = LogicalImmediateFixed | EOR | SixtyFourBits,
+  ANDS_w_imm  = LogicalImmediateFixed | ANDS,
+  ANDS_x_imm  = LogicalImmediateFixed | ANDS | SixtyFourBits
+};
+
+// Logical shifted register.
+enum LogicalShiftedOp {
+  LogicalShiftedFixed = 0x0A000000,
+  LogicalShiftedFMask = 0x1F000000,
+  LogicalShiftedMask  = 0xFF200000,
+  AND_w               = LogicalShiftedFixed | AND,
+  AND_x               = LogicalShiftedFixed | AND | SixtyFourBits,
+  AND_shift           = AND_w,
+  BIC_w               = LogicalShiftedFixed | BIC,
+  BIC_x               = LogicalShiftedFixed | BIC | SixtyFourBits,
+  BIC_shift           = BIC_w,
+  ORR_w               = LogicalShiftedFixed | ORR,
+  ORR_x               = LogicalShiftedFixed | ORR | SixtyFourBits,
+  ORR_shift           = ORR_w,
+  ORN_w               = LogicalShiftedFixed | ORN,
+  ORN_x               = LogicalShiftedFixed | ORN | SixtyFourBits,
+  ORN_shift           = ORN_w,
+  EOR_w               = LogicalShiftedFixed | EOR,
+  EOR_x               = LogicalShiftedFixed | EOR | SixtyFourBits,
+  EOR_shift           = EOR_w,
+  EON_w               = LogicalShiftedFixed | EON,
+  EON_x               = LogicalShiftedFixed | EON | SixtyFourBits,
+  EON_shift           = EON_w,
+  ANDS_w              = LogicalShiftedFixed | ANDS,
+  ANDS_x              = LogicalShiftedFixed | ANDS | SixtyFourBits,
+  ANDS_shift          = ANDS_w,
+  BICS_w              = LogicalShiftedFixed | BICS,
+  BICS_x              = LogicalShiftedFixed | BICS | SixtyFourBits,
+  BICS_shift          = BICS_w
+};
+
+// Move wide immediate.
+enum MoveWideImmediateOp {
+  MoveWideImmediateFixed = 0x12800000,
+  MoveWideImmediateFMask = 0x1F800000,
+  MoveWideImmediateMask  = 0xFF800000,
+  MOVN                   = 0x00000000,
+  MOVZ                   = 0x40000000,
+  MOVK                   = 0x60000000,
+  MOVN_w                 = MoveWideImmediateFixed | MOVN,
+  MOVN_x                 = MoveWideImmediateFixed | MOVN | SixtyFourBits,
+  MOVZ_w                 = MoveWideImmediateFixed | MOVZ,
+  MOVZ_x                 = MoveWideImmediateFixed | MOVZ | SixtyFourBits,
+  MOVK_w                 = MoveWideImmediateFixed | MOVK,
+  MOVK_x                 = MoveWideImmediateFixed | MOVK | SixtyFourBits
+};
+
+// Bitfield.
+const int kBitfieldNOffset = 22;
+enum BitfieldOp {
+  BitfieldFixed = 0x13000000,
+  BitfieldFMask = 0x1F800000,
+  BitfieldMask  = 0xFF800000,
+  SBFM_w        = BitfieldFixed | 0x00000000,
+  SBFM_x        = BitfieldFixed | 0x80000000,
+  SBFM          = SBFM_w,
+  BFM_w         = BitfieldFixed | 0x20000000,
+  BFM_x         = BitfieldFixed | 0xA0000000,
+  BFM           = BFM_w,
+  UBFM_w        = BitfieldFixed | 0x40000000,
+  UBFM_x        = BitfieldFixed | 0xC0000000,
+  UBFM          = UBFM_w
+  // Bitfield N field.
+};
+
+// Extract.
+enum ExtractOp {
+  ExtractFixed = 0x13800000,
+  ExtractFMask = 0x1F800000,
+  ExtractMask  = 0xFFA00000,
+  EXTR_w       = ExtractFixed | 0x00000000,
+  EXTR_x       = ExtractFixed | 0x80000000,
+  EXTR         = EXTR_w
+};
+
+// Unconditional branch.
+enum UnconditionalBranchOp {
+  UnconditionalBranchFixed = 0x14000000,
+  UnconditionalBranchFMask = 0x7C000000,
+  UnconditionalBranchMask  = 0xFC000000,
+  B                        = UnconditionalBranchFixed | 0x00000000,
+  BL                       = UnconditionalBranchFixed | 0x80000000
+};
+
+// Unconditional branch to register.
+enum UnconditionalBranchToRegisterOp {
+  UnconditionalBranchToRegisterFixed = 0xD6000000,
+  UnconditionalBranchToRegisterFMask = 0xFE000000,
+  UnconditionalBranchToRegisterMask  = 0xFFFFFC1F,
+  BR      = UnconditionalBranchToRegisterFixed | 0x001F0000,
+  BLR     = UnconditionalBranchToRegisterFixed | 0x003F0000,
+  RET     = UnconditionalBranchToRegisterFixed | 0x005F0000
+};
+
+// Compare and branch.
+enum CompareBranchOp {
+  CompareBranchFixed = 0x34000000,
+  CompareBranchFMask = 0x7E000000,
+  CompareBranchMask  = 0xFF000000,
+  CBZ_w              = CompareBranchFixed | 0x00000000,
+  CBZ_x              = CompareBranchFixed | 0x80000000,
+  CBZ                = CBZ_w,
+  CBNZ_w             = CompareBranchFixed | 0x01000000,
+  CBNZ_x             = CompareBranchFixed | 0x81000000,
+  CBNZ               = CBNZ_w
+};
+
+// Test and branch.
+enum TestBranchOp {
+  TestBranchFixed = 0x36000000,
+  TestBranchFMask = 0x7E000000,
+  TestBranchMask  = 0x7F000000,
+  TBZ             = TestBranchFixed | 0x00000000,
+  TBNZ            = TestBranchFixed | 0x01000000
+};
+
+// Conditional branch.
+enum ConditionalBranchOp {
+  ConditionalBranchFixed = 0x54000000,
+  ConditionalBranchFMask = 0xFE000000,
+  ConditionalBranchMask  = 0xFF000010,
+  B_cond                 = ConditionalBranchFixed | 0x00000000
+};
+
+// System.
+// System instruction encoding is complicated because some instructions use op
+// and CR fields to encode parameters. To handle this cleanly, the system
+// instructions are split into more than one enum.
+
+enum SystemOp {
+  SystemFixed = 0xD5000000,
+  SystemFMask = 0xFFC00000
+};
+
+enum SystemSysRegOp {
+  SystemSysRegFixed = 0xD5100000,
+  SystemSysRegFMask = 0xFFD00000,
+  SystemSysRegMask  = 0xFFF00000,
+  MRS               = SystemSysRegFixed | 0x00200000,
+  MSR               = SystemSysRegFixed | 0x00000000
+};
+
+enum SystemHintOp {
+  SystemHintFixed = 0xD503201F,
+  SystemHintFMask = 0xFFFFF01F,
+  SystemHintMask  = 0xFFFFF01F,
+  HINT            = SystemHintFixed | 0x00000000
+};
+
+// Exception.
+enum ExceptionOp {
+  ExceptionFixed = 0xD4000000,
+  ExceptionFMask = 0xFF000000,
+  ExceptionMask  = 0xFFE0001F,
+  HLT            = ExceptionFixed | 0x00400000,
+  BRK            = ExceptionFixed | 0x00200000,
+  SVC            = ExceptionFixed | 0x00000001,
+  HVC            = ExceptionFixed | 0x00000002,
+  SMC            = ExceptionFixed | 0x00000003,
+  DCPS1          = ExceptionFixed | 0x00A00001,
+  DCPS2          = ExceptionFixed | 0x00A00002,
+  DCPS3          = ExceptionFixed | 0x00A00003
+};
+
+// Any load or store.
+enum LoadStoreAnyOp {
+  LoadStoreAnyFMask = 0x0a000000,
+  LoadStoreAnyFixed = 0x08000000
+};
+
+#define LOAD_STORE_PAIR_OP_LIST(V)  \
+  V(STP, w,   0x00000000),          \
+  V(LDP, w,   0x00400000),          \
+  V(LDPSW, x, 0x40400000),          \
+  V(STP, x,   0x80000000),          \
+  V(LDP, x,   0x80400000),          \
+  V(STP, s,   0x04000000),          \
+  V(LDP, s,   0x04400000),          \
+  V(STP, d,   0x44000000),          \
+  V(LDP, d,   0x44400000)
+
+// Load/store pair (post, pre and offset.)
+enum LoadStorePairOp {
+  LoadStorePairMask = 0xC4400000,
+  LoadStorePairLBit = 1 << 22,
+  #define LOAD_STORE_PAIR(A, B, C) \
+  A##_##B = C
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR)
+  #undef LOAD_STORE_PAIR
+};
+
+enum LoadStorePairPostIndexOp {
+  LoadStorePairPostIndexFixed = 0x28800000,
+  LoadStorePairPostIndexFMask = 0x3B800000,
+  LoadStorePairPostIndexMask  = 0xFFC00000,
+  #define LOAD_STORE_PAIR_POST_INDEX(A, B, C)  \
+  A##_##B##_post = LoadStorePairPostIndexFixed | A##_##B
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_POST_INDEX)
+  #undef LOAD_STORE_PAIR_POST_INDEX
+};
+
+enum LoadStorePairPreIndexOp {
+  LoadStorePairPreIndexFixed = 0x29800000,
+  LoadStorePairPreIndexFMask = 0x3B800000,
+  LoadStorePairPreIndexMask  = 0xFFC00000,
+  #define LOAD_STORE_PAIR_PRE_INDEX(A, B, C)  \
+  A##_##B##_pre = LoadStorePairPreIndexFixed | A##_##B
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_PRE_INDEX)
+  #undef LOAD_STORE_PAIR_PRE_INDEX
+};
+
+enum LoadStorePairOffsetOp {
+  LoadStorePairOffsetFixed = 0x29000000,
+  LoadStorePairOffsetFMask = 0x3B800000,
+  LoadStorePairOffsetMask  = 0xFFC00000,
+  #define LOAD_STORE_PAIR_OFFSET(A, B, C)  \
+  A##_##B##_off = LoadStorePairOffsetFixed | A##_##B
+  LOAD_STORE_PAIR_OP_LIST(LOAD_STORE_PAIR_OFFSET)
+  #undef LOAD_STORE_PAIR_OFFSET
+};
+
+enum LoadStorePairNonTemporalOp {
+  LoadStorePairNonTemporalFixed = 0x28000000,
+  LoadStorePairNonTemporalFMask = 0x3B800000,
+  LoadStorePairNonTemporalMask  = 0xFFC00000,
+  STNP_w = LoadStorePairNonTemporalFixed | STP_w,
+  LDNP_w = LoadStorePairNonTemporalFixed | LDP_w,
+  STNP_x = LoadStorePairNonTemporalFixed | STP_x,
+  LDNP_x = LoadStorePairNonTemporalFixed | LDP_x,
+  STNP_s = LoadStorePairNonTemporalFixed | STP_s,
+  LDNP_s = LoadStorePairNonTemporalFixed | LDP_s,
+  STNP_d = LoadStorePairNonTemporalFixed | STP_d,
+  LDNP_d = LoadStorePairNonTemporalFixed | LDP_d
+};
+
+// Load literal.
+enum LoadLiteralOp {
+  LoadLiteralFixed = 0x18000000,
+  LoadLiteralFMask = 0x3B000000,
+  LoadLiteralMask  = 0xFF000000,
+  LDR_w_lit        = LoadLiteralFixed | 0x00000000,
+  LDR_x_lit        = LoadLiteralFixed | 0x40000000,
+  LDRSW_x_lit      = LoadLiteralFixed | 0x80000000,
+  PRFM_lit         = LoadLiteralFixed | 0xC0000000,
+  LDR_s_lit        = LoadLiteralFixed | 0x04000000,
+  LDR_d_lit        = LoadLiteralFixed | 0x44000000
+};
+
+#define LOAD_STORE_OP_LIST(V)     \
+  V(ST, RB, w,  0x00000000),  \
+  V(ST, RH, w,  0x40000000),  \
+  V(ST, R, w,   0x80000000),  \
+  V(ST, R, x,   0xC0000000),  \
+  V(LD, RB, w,  0x00400000),  \
+  V(LD, RH, w,  0x40400000),  \
+  V(LD, R, w,   0x80400000),  \
+  V(LD, R, x,   0xC0400000),  \
+  V(LD, RSB, x, 0x00800000),  \
+  V(LD, RSH, x, 0x40800000),  \
+  V(LD, RSW, x, 0x80800000),  \
+  V(LD, RSB, w, 0x00C00000),  \
+  V(LD, RSH, w, 0x40C00000),  \
+  V(ST, R, s,   0x84000000),  \
+  V(ST, R, d,   0xC4000000),  \
+  V(LD, R, s,   0x84400000),  \
+  V(LD, R, d,   0xC4400000)
+
+
+// Load/store unscaled offset.
+enum LoadStoreUnscaledOffsetOp {
+  LoadStoreUnscaledOffsetFixed = 0x38000000,
+  LoadStoreUnscaledOffsetFMask = 0x3B200C00,
+  LoadStoreUnscaledOffsetMask  = 0xFFE00C00,
+  #define LOAD_STORE_UNSCALED(A, B, C, D)  \
+  A##U##B##_##C = LoadStoreUnscaledOffsetFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_UNSCALED)
+  #undef LOAD_STORE_UNSCALED
+};
+
+// Load/store (post, pre, offset and unsigned.)
+enum LoadStoreOp {
+  LoadStoreOpMask   = 0xC4C00000,
+  #define LOAD_STORE(A, B, C, D)  \
+  A##B##_##C = D
+  LOAD_STORE_OP_LIST(LOAD_STORE),
+  #undef LOAD_STORE
+  PRFM = 0xC0800000
+};
+
+// Load/store post index.
+enum LoadStorePostIndex {
+  LoadStorePostIndexFixed = 0x38000400,
+  LoadStorePostIndexFMask = 0x3B200C00,
+  LoadStorePostIndexMask  = 0xFFE00C00,
+  #define LOAD_STORE_POST_INDEX(A, B, C, D)  \
+  A##B##_##C##_post = LoadStorePostIndexFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_POST_INDEX)
+  #undef LOAD_STORE_POST_INDEX
+};
+
+// Load/store pre index.
+enum LoadStorePreIndex {
+  LoadStorePreIndexFixed = 0x38000C00,
+  LoadStorePreIndexFMask = 0x3B200C00,
+  LoadStorePreIndexMask  = 0xFFE00C00,
+  #define LOAD_STORE_PRE_INDEX(A, B, C, D)  \
+  A##B##_##C##_pre = LoadStorePreIndexFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_PRE_INDEX)
+  #undef LOAD_STORE_PRE_INDEX
+};
+
+// Load/store unsigned offset.
+enum LoadStoreUnsignedOffset {
+  LoadStoreUnsignedOffsetFixed = 0x39000000,
+  LoadStoreUnsignedOffsetFMask = 0x3B000000,
+  LoadStoreUnsignedOffsetMask  = 0xFFC00000,
+  PRFM_unsigned                = LoadStoreUnsignedOffsetFixed | PRFM,
+  #define LOAD_STORE_UNSIGNED_OFFSET(A, B, C, D) \
+  A##B##_##C##_unsigned = LoadStoreUnsignedOffsetFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_UNSIGNED_OFFSET)
+  #undef LOAD_STORE_UNSIGNED_OFFSET
+};
+
+// Load/store register offset.
+enum LoadStoreRegisterOffset {
+  LoadStoreRegisterOffsetFixed = 0x38200800,
+  LoadStoreRegisterOffsetFMask = 0x3B200C00,
+  LoadStoreRegisterOffsetMask  = 0xFFE00C00,
+  PRFM_reg                     = LoadStoreRegisterOffsetFixed | PRFM,
+  #define LOAD_STORE_REGISTER_OFFSET(A, B, C, D) \
+  A##B##_##C##_reg = LoadStoreRegisterOffsetFixed | D
+  LOAD_STORE_OP_LIST(LOAD_STORE_REGISTER_OFFSET)
+  #undef LOAD_STORE_REGISTER_OFFSET
+};
+
+// Conditional compare.
+enum ConditionalCompareOp {
+  ConditionalCompareMask = 0x60000000,
+  CCMN                   = 0x20000000,
+  CCMP                   = 0x60000000
+};
+
+// Conditional compare register.
+enum ConditionalCompareRegisterOp {
+  ConditionalCompareRegisterFixed = 0x1A400000,
+  ConditionalCompareRegisterFMask = 0x1FE00800,
+  ConditionalCompareRegisterMask  = 0xFFE00C10,
+  CCMN_w = ConditionalCompareRegisterFixed | CCMN,
+  CCMN_x = ConditionalCompareRegisterFixed | SixtyFourBits | CCMN,
+  CCMP_w = ConditionalCompareRegisterFixed | CCMP,
+  CCMP_x = ConditionalCompareRegisterFixed | SixtyFourBits | CCMP
+};
+
+// Conditional compare immediate.
+enum ConditionalCompareImmediateOp {
+  ConditionalCompareImmediateFixed = 0x1A400800,
+  ConditionalCompareImmediateFMask = 0x1FE00800,
+  ConditionalCompareImmediateMask  = 0xFFE00C10,
+  CCMN_w_imm = ConditionalCompareImmediateFixed | CCMN,
+  CCMN_x_imm = ConditionalCompareImmediateFixed | SixtyFourBits | CCMN,
+  CCMP_w_imm = ConditionalCompareImmediateFixed | CCMP,
+  CCMP_x_imm = ConditionalCompareImmediateFixed | SixtyFourBits | CCMP
+};
+
+// Conditional select.
+enum ConditionalSelectOp {
+  ConditionalSelectFixed = 0x1A800000,
+  ConditionalSelectFMask = 0x1FE00000,
+  ConditionalSelectMask  = 0xFFE00C00,
+  CSEL_w                 = ConditionalSelectFixed | 0x00000000,
+  CSEL_x                 = ConditionalSelectFixed | 0x80000000,
+  CSEL                   = CSEL_w,
+  CSINC_w                = ConditionalSelectFixed | 0x00000400,
+  CSINC_x                = ConditionalSelectFixed | 0x80000400,
+  CSINC                  = CSINC_w,
+  CSINV_w                = ConditionalSelectFixed | 0x40000000,
+  CSINV_x                = ConditionalSelectFixed | 0xC0000000,
+  CSINV                  = CSINV_w,
+  CSNEG_w                = ConditionalSelectFixed | 0x40000400,
+  CSNEG_x                = ConditionalSelectFixed | 0xC0000400,
+  CSNEG                  = CSNEG_w
+};
+
+// Data processing 1 source.
+enum DataProcessing1SourceOp {
+  DataProcessing1SourceFixed = 0x5AC00000,
+  DataProcessing1SourceFMask = 0x5FE00000,
+  DataProcessing1SourceMask  = 0xFFFFFC00,
+  RBIT    = DataProcessing1SourceFixed | 0x00000000,
+  RBIT_w  = RBIT,
+  RBIT_x  = RBIT | SixtyFourBits,
+  REV16   = DataProcessing1SourceFixed | 0x00000400,
+  REV16_w = REV16,
+  REV16_x = REV16 | SixtyFourBits,
+  REV     = DataProcessing1SourceFixed | 0x00000800,
+  REV_w   = REV,
+  REV32_x = REV | SixtyFourBits,
+  REV_x   = DataProcessing1SourceFixed | SixtyFourBits | 0x00000C00,
+  CLZ     = DataProcessing1SourceFixed | 0x00001000,
+  CLZ_w   = CLZ,
+  CLZ_x   = CLZ | SixtyFourBits,
+  CLS     = DataProcessing1SourceFixed | 0x00001400,
+  CLS_w   = CLS,
+  CLS_x   = CLS | SixtyFourBits
+};
+
+// Data processing 2 source.
+enum DataProcessing2SourceOp {
+  DataProcessing2SourceFixed = 0x1AC00000,
+  DataProcessing2SourceFMask = 0x5FE00000,
+  DataProcessing2SourceMask  = 0xFFE0FC00,
+  UDIV_w  = DataProcessing2SourceFixed | 0x00000800,
+  UDIV_x  = DataProcessing2SourceFixed | 0x80000800,
+  UDIV    = UDIV_w,
+  SDIV_w  = DataProcessing2SourceFixed | 0x00000C00,
+  SDIV_x  = DataProcessing2SourceFixed | 0x80000C00,
+  SDIV    = SDIV_w,
+  LSLV_w  = DataProcessing2SourceFixed | 0x00002000,
+  LSLV_x  = DataProcessing2SourceFixed | 0x80002000,
+  LSLV    = LSLV_w,
+  LSRV_w  = DataProcessing2SourceFixed | 0x00002400,
+  LSRV_x  = DataProcessing2SourceFixed | 0x80002400,
+  LSRV    = LSRV_w,
+  ASRV_w  = DataProcessing2SourceFixed | 0x00002800,
+  ASRV_x  = DataProcessing2SourceFixed | 0x80002800,
+  ASRV    = ASRV_w,
+  RORV_w  = DataProcessing2SourceFixed | 0x00002C00,
+  RORV_x  = DataProcessing2SourceFixed | 0x80002C00,
+  RORV    = RORV_w,
+  CRC32B  = DataProcessing2SourceFixed | 0x00004000,
+  CRC32H  = DataProcessing2SourceFixed | 0x00004400,
+  CRC32W  = DataProcessing2SourceFixed | 0x00004800,
+  CRC32X  = DataProcessing2SourceFixed | SixtyFourBits | 0x00004C00,
+  CRC32CB = DataProcessing2SourceFixed | 0x00005000,
+  CRC32CH = DataProcessing2SourceFixed | 0x00005400,
+  CRC32CW = DataProcessing2SourceFixed | 0x00005800,
+  CRC32CX = DataProcessing2SourceFixed | SixtyFourBits | 0x00005C00
+};
+
+// Data processing 3 source.
+enum DataProcessing3SourceOp {
+  DataProcessing3SourceFixed = 0x1B000000,
+  DataProcessing3SourceFMask = 0x1F000000,
+  DataProcessing3SourceMask  = 0xFFE08000,
+  MADD_w                     = DataProcessing3SourceFixed | 0x00000000,
+  MADD_x                     = DataProcessing3SourceFixed | 0x80000000,
+  MADD                       = MADD_w,
+  MSUB_w                     = DataProcessing3SourceFixed | 0x00008000,
+  MSUB_x                     = DataProcessing3SourceFixed | 0x80008000,
+  MSUB                       = MSUB_w,
+  SMADDL_x                   = DataProcessing3SourceFixed | 0x80200000,
+  SMSUBL_x                   = DataProcessing3SourceFixed | 0x80208000,
+  SMULH_x                    = DataProcessing3SourceFixed | 0x80400000,
+  UMADDL_x                   = DataProcessing3SourceFixed | 0x80A00000,
+  UMSUBL_x                   = DataProcessing3SourceFixed | 0x80A08000,
+  UMULH_x                    = DataProcessing3SourceFixed | 0x80C00000
+};
+
+// Floating point compare.
+enum FPCompareOp {
+  FPCompareFixed = 0x1E202000,
+  FPCompareFMask = 0x5F203C00,
+  FPCompareMask  = 0xFFE0FC1F,
+  FCMP_s         = FPCompareFixed | 0x00000000,
+  FCMP_d         = FPCompareFixed | FP64 | 0x00000000,
+  FCMP           = FCMP_s,
+  FCMP_s_zero    = FPCompareFixed | 0x00000008,
+  FCMP_d_zero    = FPCompareFixed | FP64 | 0x00000008,
+  FCMP_zero      = FCMP_s_zero,
+  FCMPE_s        = FPCompareFixed | 0x00000010,
+  FCMPE_d        = FPCompareFixed | FP64 | 0x00000010,
+  FCMPE_s_zero   = FPCompareFixed | 0x00000018,
+  FCMPE_d_zero   = FPCompareFixed | FP64 | 0x00000018
+};
+
+// Floating point conditional compare.
+enum FPConditionalCompareOp {
+  FPConditionalCompareFixed = 0x1E200400,
+  FPConditionalCompareFMask = 0x5F200C00,
+  FPConditionalCompareMask  = 0xFFE00C10,
+  FCCMP_s                   = FPConditionalCompareFixed | 0x00000000,
+  FCCMP_d                   = FPConditionalCompareFixed | FP64 | 0x00000000,
+  FCCMP                     = FCCMP_s,
+  FCCMPE_s                  = FPConditionalCompareFixed | 0x00000010,
+  FCCMPE_d                  = FPConditionalCompareFixed | FP64 | 0x00000010,
+  FCCMPE                    = FCCMPE_s
+};
+
+// Floating point conditional select.
+enum FPConditionalSelectOp {
+  FPConditionalSelectFixed = 0x1E200C00,
+  FPConditionalSelectFMask = 0x5F200C00,
+  FPConditionalSelectMask  = 0xFFE00C00,
+  FCSEL_s                  = FPConditionalSelectFixed | 0x00000000,
+  FCSEL_d                  = FPConditionalSelectFixed | FP64 | 0x00000000,
+  FCSEL                    = FCSEL_s
+};
+
+// Floating point immediate.
+enum FPImmediateOp {
+  FPImmediateFixed = 0x1E201000,
+  FPImmediateFMask = 0x5F201C00,
+  FPImmediateMask  = 0xFFE01C00,
+  FMOV_s_imm       = FPImmediateFixed | 0x00000000,
+  FMOV_d_imm       = FPImmediateFixed | FP64 | 0x00000000
+};
+
+// Floating point data processing 1 source.
+enum FPDataProcessing1SourceOp {
+  FPDataProcessing1SourceFixed = 0x1E204000,
+  FPDataProcessing1SourceFMask = 0x5F207C00,
+  FPDataProcessing1SourceMask  = 0xFFFFFC00,
+  FMOV_s   = FPDataProcessing1SourceFixed | 0x00000000,
+  FMOV_d   = FPDataProcessing1SourceFixed | FP64 | 0x00000000,
+  FMOV     = FMOV_s,
+  FABS_s   = FPDataProcessing1SourceFixed | 0x00008000,
+  FABS_d   = FPDataProcessing1SourceFixed | FP64 | 0x00008000,
+  FABS     = FABS_s,
+  FNEG_s   = FPDataProcessing1SourceFixed | 0x00010000,
+  FNEG_d   = FPDataProcessing1SourceFixed | FP64 | 0x00010000,
+  FNEG     = FNEG_s,
+  FSQRT_s  = FPDataProcessing1SourceFixed | 0x00018000,
+  FSQRT_d  = FPDataProcessing1SourceFixed | FP64 | 0x00018000,
+  FSQRT    = FSQRT_s,
+  FCVT_ds  = FPDataProcessing1SourceFixed | 0x00028000,
+  FCVT_sd  = FPDataProcessing1SourceFixed | FP64 | 0x00020000,
+  FRINTN_s = FPDataProcessing1SourceFixed | 0x00040000,
+  FRINTN_d = FPDataProcessing1SourceFixed | FP64 | 0x00040000,
+  FRINTN   = FRINTN_s,
+  FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000,
+  FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000,
+  FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000,
+  FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000,
+  FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000,
+  FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000,
+  FRINTZ   = FRINTZ_s,
+  FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000,
+  FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000,
+  FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000,
+  FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000,
+  FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000,
+  FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000
+};
+
+// Floating point data processing 2 source.
+enum FPDataProcessing2SourceOp {
+  FPDataProcessing2SourceFixed = 0x1E200800,
+  FPDataProcessing2SourceFMask = 0x5F200C00,
+  FPDataProcessing2SourceMask  = 0xFFE0FC00,
+  FMUL     = FPDataProcessing2SourceFixed | 0x00000000,
+  FMUL_s   = FMUL,
+  FMUL_d   = FMUL | FP64,
+  FDIV     = FPDataProcessing2SourceFixed | 0x00001000,
+  FDIV_s   = FDIV,
+  FDIV_d   = FDIV | FP64,
+  FADD     = FPDataProcessing2SourceFixed | 0x00002000,
+  FADD_s   = FADD,
+  FADD_d   = FADD | FP64,
+  FSUB     = FPDataProcessing2SourceFixed | 0x00003000,
+  FSUB_s   = FSUB,
+  FSUB_d   = FSUB | FP64,
+  FMAX     = FPDataProcessing2SourceFixed | 0x00004000,
+  FMAX_s   = FMAX,
+  FMAX_d   = FMAX | FP64,
+  FMIN     = FPDataProcessing2SourceFixed | 0x00005000,
+  FMIN_s   = FMIN,
+  FMIN_d   = FMIN | FP64,
+  FMAXNM   = FPDataProcessing2SourceFixed | 0x00006000,
+  FMAXNM_s = FMAXNM,
+  FMAXNM_d = FMAXNM | FP64,
+  FMINNM   = FPDataProcessing2SourceFixed | 0x00007000,
+  FMINNM_s = FMINNM,
+  FMINNM_d = FMINNM | FP64,
+  FNMUL    = FPDataProcessing2SourceFixed | 0x00008000,
+  FNMUL_s  = FNMUL,
+  FNMUL_d  = FNMUL | FP64
+};
+
+// Floating point data processing 3 source.
+enum FPDataProcessing3SourceOp {
+  FPDataProcessing3SourceFixed = 0x1F000000,
+  FPDataProcessing3SourceFMask = 0x5F000000,
+  FPDataProcessing3SourceMask  = 0xFFE08000,
+  FMADD_s                      = FPDataProcessing3SourceFixed | 0x00000000,
+  FMSUB_s                      = FPDataProcessing3SourceFixed | 0x00008000,
+  FNMADD_s                     = FPDataProcessing3SourceFixed | 0x00200000,
+  FNMSUB_s                     = FPDataProcessing3SourceFixed | 0x00208000,
+  FMADD_d                      = FPDataProcessing3SourceFixed | 0x00400000,
+  FMSUB_d                      = FPDataProcessing3SourceFixed | 0x00408000,
+  FNMADD_d                     = FPDataProcessing3SourceFixed | 0x00600000,
+  FNMSUB_d                     = FPDataProcessing3SourceFixed | 0x00608000
+};
+
+// Conversion between floating point and integer.
+enum FPIntegerConvertOp {
+  FPIntegerConvertFixed = 0x1E200000,
+  FPIntegerConvertFMask = 0x5F20FC00,
+  FPIntegerConvertMask  = 0xFFFFFC00,
+  FCVTNS    = FPIntegerConvertFixed | 0x00000000,
+  FCVTNS_ws = FCVTNS,
+  FCVTNS_xs = FCVTNS | SixtyFourBits,
+  FCVTNS_wd = FCVTNS | FP64,
+  FCVTNS_xd = FCVTNS | SixtyFourBits | FP64,
+  FCVTNU    = FPIntegerConvertFixed | 0x00010000,
+  FCVTNU_ws = FCVTNU,
+  FCVTNU_xs = FCVTNU | SixtyFourBits,
+  FCVTNU_wd = FCVTNU | FP64,
+  FCVTNU_xd = FCVTNU | SixtyFourBits | FP64,
+  FCVTPS    = FPIntegerConvertFixed | 0x00080000,
+  FCVTPS_ws = FCVTPS,
+  FCVTPS_xs = FCVTPS | SixtyFourBits,
+  FCVTPS_wd = FCVTPS | FP64,
+  FCVTPS_xd = FCVTPS | SixtyFourBits | FP64,
+  FCVTPU    = FPIntegerConvertFixed | 0x00090000,
+  FCVTPU_ws = FCVTPU,
+  FCVTPU_xs = FCVTPU | SixtyFourBits,
+  FCVTPU_wd = FCVTPU | FP64,
+  FCVTPU_xd = FCVTPU | SixtyFourBits | FP64,
+  FCVTMS    = FPIntegerConvertFixed | 0x00100000,
+  FCVTMS_ws = FCVTMS,
+  FCVTMS_xs = FCVTMS | SixtyFourBits,
+  FCVTMS_wd = FCVTMS | FP64,
+  FCVTMS_xd = FCVTMS | SixtyFourBits | FP64,
+  FCVTMU    = FPIntegerConvertFixed | 0x00110000,
+  FCVTMU_ws = FCVTMU,
+  FCVTMU_xs = FCVTMU | SixtyFourBits,
+  FCVTMU_wd = FCVTMU | FP64,
+  FCVTMU_xd = FCVTMU | SixtyFourBits | FP64,
+  FCVTZS    = FPIntegerConvertFixed | 0x00180000,
+  FCVTZS_ws = FCVTZS,
+  FCVTZS_xs = FCVTZS | SixtyFourBits,
+  FCVTZS_wd = FCVTZS | FP64,
+  FCVTZS_xd = FCVTZS | SixtyFourBits | FP64,
+  FCVTZU    = FPIntegerConvertFixed | 0x00190000,
+  FCVTZU_ws = FCVTZU,
+  FCVTZU_xs = FCVTZU | SixtyFourBits,
+  FCVTZU_wd = FCVTZU | FP64,
+  FCVTZU_xd = FCVTZU | SixtyFourBits | FP64,
+  SCVTF     = FPIntegerConvertFixed | 0x00020000,
+  SCVTF_sw  = SCVTF,
+  SCVTF_sx  = SCVTF | SixtyFourBits,
+  SCVTF_dw  = SCVTF | FP64,
+  SCVTF_dx  = SCVTF | SixtyFourBits | FP64,
+  UCVTF     = FPIntegerConvertFixed | 0x00030000,
+  UCVTF_sw  = UCVTF,
+  UCVTF_sx  = UCVTF | SixtyFourBits,
+  UCVTF_dw  = UCVTF | FP64,
+  UCVTF_dx  = UCVTF | SixtyFourBits | FP64,
+  FCVTAS    = FPIntegerConvertFixed | 0x00040000,
+  FCVTAS_ws = FCVTAS,
+  FCVTAS_xs = FCVTAS | SixtyFourBits,
+  FCVTAS_wd = FCVTAS | FP64,
+  FCVTAS_xd = FCVTAS | SixtyFourBits | FP64,
+  FCVTAU    = FPIntegerConvertFixed | 0x00050000,
+  FCVTAU_ws = FCVTAU,
+  FCVTAU_xs = FCVTAU | SixtyFourBits,
+  FCVTAU_wd = FCVTAU | FP64,
+  FCVTAU_xd = FCVTAU | SixtyFourBits | FP64,
+  FMOV_ws   = FPIntegerConvertFixed | 0x00060000,
+  FMOV_sw   = FPIntegerConvertFixed | 0x00070000,
+  FMOV_xd   = FMOV_ws | SixtyFourBits | FP64,
+  FMOV_dx   = FMOV_sw | SixtyFourBits | FP64
+};
+
+// Conversion between fixed point and floating point.
+enum FPFixedPointConvertOp {
+  FPFixedPointConvertFixed = 0x1E000000,
+  FPFixedPointConvertFMask = 0x5F200000,
+  FPFixedPointConvertMask  = 0xFFFF0000,
+  FCVTZS_fixed    = FPFixedPointConvertFixed | 0x00180000,
+  FCVTZS_ws_fixed = FCVTZS_fixed,
+  FCVTZS_xs_fixed = FCVTZS_fixed | SixtyFourBits,
+  FCVTZS_wd_fixed = FCVTZS_fixed | FP64,
+  FCVTZS_xd_fixed = FCVTZS_fixed | SixtyFourBits | FP64,
+  FCVTZU_fixed    = FPFixedPointConvertFixed | 0x00190000,
+  FCVTZU_ws_fixed = FCVTZU_fixed,
+  FCVTZU_xs_fixed = FCVTZU_fixed | SixtyFourBits,
+  FCVTZU_wd_fixed = FCVTZU_fixed | FP64,
+  FCVTZU_xd_fixed = FCVTZU_fixed | SixtyFourBits | FP64,
+  SCVTF_fixed     = FPFixedPointConvertFixed | 0x00020000,
+  SCVTF_sw_fixed  = SCVTF_fixed,
+  SCVTF_sx_fixed  = SCVTF_fixed | SixtyFourBits,
+  SCVTF_dw_fixed  = SCVTF_fixed | FP64,
+  SCVTF_dx_fixed  = SCVTF_fixed | SixtyFourBits | FP64,
+  UCVTF_fixed     = FPFixedPointConvertFixed | 0x00030000,
+  UCVTF_sw_fixed  = UCVTF_fixed,
+  UCVTF_sx_fixed  = UCVTF_fixed | SixtyFourBits,
+  UCVTF_dw_fixed  = UCVTF_fixed | FP64,
+  UCVTF_dx_fixed  = UCVTF_fixed | SixtyFourBits | FP64
+};
+
+// Unimplemented and unallocated instructions. These are defined to make fixed
+// bit assertion easier.
+enum UnimplementedOp {
+  UnimplementedFixed = 0x00000000,
+  UnimplementedFMask = 0x00000000
+};
+
+enum UnallocatedOp {
+  UnallocatedFixed = 0x00000000,
+  UnallocatedFMask = 0x00000000
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_CONSTANTS_A64_H_
diff --git a/disas/libvixl/src/a64/cpu-a64.cc b/disas/libvixl/src/a64/cpu-a64.cc
new file mode 100644
index 0000000..8586563
--- /dev/null
+++ b/disas/libvixl/src/a64/cpu-a64.cc
@@ -0,0 +1,148 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utils.h"
+#include "a64/cpu-a64.h"
+
+namespace vixl {
+
+// Initialise to smallest possible cache size.
+unsigned CPU::dcache_line_size_ = 1;
+unsigned CPU::icache_line_size_ = 1;
+
+
+// Currently computes I and D cache line size.
+void CPU::SetUp() {
+  uint32_t cache_type_register = GetCacheType();
+
+  // The cache type register holds information about the caches, including I
+  // D caches line size.
+  static const int kDCacheLineSizeShift = 16;
+  static const int kICacheLineSizeShift = 0;
+  static const uint32_t kDCacheLineSizeMask = 0xf << kDCacheLineSizeShift;
+  static const uint32_t kICacheLineSizeMask = 0xf << kICacheLineSizeShift;
+
+  // The cache type register holds the size of the I and D caches as a power of
+  // two.
+  uint32_t dcache_line_size_power_of_two =
+      (cache_type_register & kDCacheLineSizeMask) >> kDCacheLineSizeShift;
+  uint32_t icache_line_size_power_of_two =
+      (cache_type_register & kICacheLineSizeMask) >> kICacheLineSizeShift;
+
+  dcache_line_size_ = 1 << dcache_line_size_power_of_two;
+  icache_line_size_ = 1 << icache_line_size_power_of_two;
+}
+
+
+uint32_t CPU::GetCacheType() {
+#ifdef USE_SIMULATOR
+  // This will lead to a cache with 1 byte long lines, which is fine since the
+  // simulator will not need this information.
+  return 0;
+#else
+  uint32_t cache_type_register;
+  // Copy the content of the cache type register to a core register.
+  __asm__ __volatile__ ("mrs %[ctr], ctr_el0"  // NOLINT
+                        : [ctr] "=r" (cache_type_register));
+  return cache_type_register;
+#endif
+}
+
+
+void CPU::EnsureIAndDCacheCoherency(void *address, size_t length) {
+#ifdef USE_SIMULATOR
+  USE(address);
+  USE(length);
+  // TODO: consider adding cache simulation to ensure every address run has been
+  // synchronised.
+#else
+  // The code below assumes user space cache operations are allowed.
+
+  uintptr_t start = reinterpret_cast<uintptr_t>(address);
+  // Sizes will be used to generate a mask big enough to cover a pointer.
+  uintptr_t dsize = static_cast<uintptr_t>(dcache_line_size_);
+  uintptr_t isize = static_cast<uintptr_t>(icache_line_size_);
+  // Cache line sizes are always a power of 2.
+  ASSERT(CountSetBits(dsize, 64) == 1);
+  ASSERT(CountSetBits(isize, 64) == 1);
+  uintptr_t dstart = start & ~(dsize - 1);
+  uintptr_t istart = start & ~(isize - 1);
+  uintptr_t end = start + length;
+
+  __asm__ __volatile__ (  // NOLINT
+    // Clean every line of the D cache containing the target data.
+    "0:                                \n\t"
+    // dc      : Data Cache maintenance
+    //    c    : Clean
+    //     va  : by (Virtual) Address
+    //       u : to the point of Unification
+    // The point of unification for a processor is the point by which the
+    // instruction and data caches are guaranteed to see the same copy of a
+    // memory location. See ARM DDI 0406B page B2-12 for more information.
+    "dc   cvau, %[dline]                \n\t"
+    "add  %[dline], %[dline], %[dsize]  \n\t"
+    "cmp  %[dline], %[end]              \n\t"
+    "b.lt 0b                            \n\t"
+    // Barrier to make sure the effect of the code above is visible to the rest
+    // of the world.
+    // dsb    : Data Synchronisation Barrier
+    //    ish : Inner SHareable domain
+    // The point of unification for an Inner Shareable shareability domain is
+    // the point by which the instruction and data caches of all the processors
+    // in that Inner Shareable shareability domain are guaranteed to see the
+    // same copy of a memory location.  See ARM DDI 0406B page B2-12 for more
+    // information.
+    "dsb  ish                           \n\t"
+    // Invalidate every line of the I cache containing the target data.
+    "1:                                 \n\t"
+    // ic      : instruction cache maintenance
+    //    i    : invalidate
+    //     va  : by address
+    //       u : to the point of unification
+    "ic   ivau, %[iline]                \n\t"
+    "add  %[iline], %[iline], %[isize]  \n\t"
+    "cmp  %[iline], %[end]              \n\t"
+    "b.lt 1b                            \n\t"
+    // Barrier to make sure the effect of the code above is visible to the rest
+    // of the world.
+    "dsb  ish                           \n\t"
+    // Barrier to ensure any prefetching which happened before this code is
+    // discarded.
+    // isb : Instruction Synchronisation Barrier
+    "isb                                \n\t"
+    : [dline] "+r" (dstart),
+      [iline] "+r" (istart)
+    : [dsize] "r"  (dsize),
+      [isize] "r"  (isize),
+      [end]   "r"  (end)
+    // This code does not write to memory but without the dependency gcc might
+    // move this code before the code is generated.
+    : "cc", "memory"
+  );  // NOLINT
+#endif
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/cpu-a64.h b/disas/libvixl/src/a64/cpu-a64.h
new file mode 100644
index 0000000..dfd8f01
--- /dev/null
+++ b/disas/libvixl/src/a64/cpu-a64.h
@@ -0,0 +1,56 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_CPU_A64_H
+#define VIXL_CPU_A64_H
+
+#include "globals.h"
+
+namespace vixl {
+
+class CPU {
+ public:
+  // Initialise CPU support.
+  static void SetUp();
+
+  // Ensures the data at a given address and with a given size is the same for
+  // the I and D caches. I and D caches are not automatically coherent on ARM
+  // so this operation is required before any dynamically generated code can
+  // safely run.
+  static void EnsureIAndDCacheCoherency(void *address, size_t length);
+
+ private:
+  // Return the content of the cache type register.
+  static uint32_t GetCacheType();
+
+  // I and D cache line size in bytes.
+  static unsigned icache_line_size_;
+  static unsigned dcache_line_size_;
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_CPU_A64_H
diff --git a/disas/libvixl/src/a64/debugger-a64.cc b/disas/libvixl/src/a64/debugger-a64.cc
new file mode 100644
index 0000000..ecdc835
--- /dev/null
+++ b/disas/libvixl/src/a64/debugger-a64.cc
@@ -0,0 +1,1511 @@
+// Copyright 2013 ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/debugger-a64.h"
+
+namespace vixl {
+
+// List of commands supported by the debugger.
+#define DEBUG_COMMAND_LIST(C)  \
+C(HelpCommand)                 \
+C(ContinueCommand)             \
+C(StepCommand)                 \
+C(DisasmCommand)               \
+C(PrintCommand)                \
+C(MemCommand)
+
+// Debugger command lines are broken up in token of different type to make
+// processing easier later on.
+class Token {
+ public:
+  virtual ~Token() {}
+
+  // Token type.
+  virtual bool IsRegister() const { return false; }
+  virtual bool IsFPRegister() const { return false; }
+  virtual bool IsIdentifier() const { return false; }
+  virtual bool IsAddress() const { return false; }
+  virtual bool IsInteger() const { return false; }
+  virtual bool IsFormat() const { return false; }
+  virtual bool IsUnknown() const { return false; }
+  // Token properties.
+  virtual bool CanAddressMemory() const { return false; }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const = 0;
+
+  static Token* Tokenize(const char* arg);
+};
+
+// Tokens often hold one value.
+template<typename T> class ValueToken : public Token {
+ public:
+  explicit ValueToken(T value) : value_(value) {}
+  ValueToken() {}
+
+  T value() const { return value_; }
+
+ protected:
+  T value_;
+};
+
+// Integer registers (X or W) and their aliases.
+// Format: wn or xn with 0 <= n < 32 or a name in the aliases list.
+class RegisterToken : public ValueToken<const Register> {
+ public:
+  explicit RegisterToken(const Register reg)
+      : ValueToken<const Register>(reg) {}
+
+  virtual bool IsRegister() const { return true; }
+  virtual bool CanAddressMemory() const { return value().Is64Bits(); }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const ;
+  const char* Name() const;
+
+  static Token* Tokenize(const char* arg);
+  static RegisterToken* Cast(Token* tok) {
+    ASSERT(tok->IsRegister());
+    return reinterpret_cast<RegisterToken*>(tok);
+  }
+
+ private:
+  static const int kMaxAliasNumber = 4;
+  static const char* kXAliases[kNumberOfRegisters][kMaxAliasNumber];
+  static const char* kWAliases[kNumberOfRegisters][kMaxAliasNumber];
+};
+
+// Floating point registers (D or S).
+// Format: sn or dn with 0 <= n < 32.
+class FPRegisterToken : public ValueToken<const FPRegister> {
+ public:
+  explicit FPRegisterToken(const FPRegister fpreg)
+      : ValueToken<const FPRegister>(fpreg) {}
+
+  virtual bool IsFPRegister() const { return true; }
+  virtual void Print(FILE* out = stdout) const ;
+
+  static Token* Tokenize(const char* arg);
+  static FPRegisterToken* Cast(Token* tok) {
+    ASSERT(tok->IsFPRegister());
+    return reinterpret_cast<FPRegisterToken*>(tok);
+  }
+};
+
+
+// Non-register identifiers.
+// Format: Alphanumeric string starting with a letter.
+class IdentifierToken : public ValueToken<char*> {
+ public:
+  explicit IdentifierToken(const char* name) {
+    int size = strlen(name) + 1;
+    value_ = new char[size];
+    strncpy(value_, name, size);
+  }
+  virtual ~IdentifierToken() { delete[] value_; }
+
+  virtual bool IsIdentifier() const { return true; }
+  virtual bool CanAddressMemory() const { return strcmp(value(), "pc") == 0; }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const;
+
+  static Token* Tokenize(const char* arg);
+  static IdentifierToken* Cast(Token* tok) {
+    ASSERT(tok->IsIdentifier());
+    return reinterpret_cast<IdentifierToken*>(tok);
+  }
+};
+
+// 64-bit address literal.
+// Format: 0x... with up to 16 hexadecimal digits.
+class AddressToken : public ValueToken<uint8_t*> {
+ public:
+  explicit AddressToken(uint8_t* address) : ValueToken<uint8_t*>(address) {}
+
+  virtual bool IsAddress() const { return true; }
+  virtual bool CanAddressMemory() const { return true; }
+  virtual uint8_t* ToAddress(Debugger* debugger) const;
+  virtual void Print(FILE* out = stdout) const ;
+
+  static Token* Tokenize(const char* arg);
+  static AddressToken* Cast(Token* tok) {
+    ASSERT(tok->IsAddress());
+    return reinterpret_cast<AddressToken*>(tok);
+  }
+};
+
+
+// 64-bit decimal integer literal.
+// Format: n.
+class IntegerToken : public ValueToken<int64_t> {
+ public:
+  explicit IntegerToken(int value) : ValueToken<int64_t>(value) {}
+
+  virtual bool IsInteger() const { return true; }
+  virtual void Print(FILE* out = stdout) const;
+
+  static Token* Tokenize(const char* arg);
+  static IntegerToken* Cast(Token* tok) {
+    ASSERT(tok->IsInteger());
+    return reinterpret_cast<IntegerToken*>(tok);
+  }
+};
+
+// Literal describing how to print a chunk of data (up to 64 bits).
+// Format: %qt
+// where q (qualifier) is one of
+//  * s: signed integer
+//  * u: unsigned integer
+//  * a: hexadecimal floating point
+// and t (type) is one of
+//  * x: 64-bit integer
+//  * w: 32-bit integer
+//  * h: 16-bit integer
+//  * b: 8-bit integer
+//  * c: character
+//  * d: double
+//  * s: float
+// When no qualifier is given for integers, they are printed in hexadecinal.
+class FormatToken : public Token {
+ public:
+  FormatToken() {}
+
+  virtual bool IsFormat() const { return true; }
+  virtual int SizeOf() const = 0;
+  virtual void PrintData(void* data, FILE* out = stdout) const = 0;
+  virtual void Print(FILE* out = stdout) const = 0;
+
+  static Token* Tokenize(const char* arg);
+  static FormatToken* Cast(Token* tok) {
+    ASSERT(tok->IsFormat());
+    return reinterpret_cast<FormatToken*>(tok);
+  }
+};
+
+
+template<typename T> class Format : public FormatToken {
+ public:
+  explicit Format(const char* fmt) : fmt_(fmt) {}
+
+  virtual int SizeOf() const { return sizeof(T); }
+  virtual void PrintData(void* data, FILE* out = stdout) const {
+    T value;
+    memcpy(&value, data, sizeof(value));
+    fprintf(out, fmt_, value);
+  }
+  virtual void Print(FILE* out = stdout) const;
+
+ private:
+  const char* fmt_;
+};
+
+// Tokens which don't fit any of the above.
+class UnknownToken : public Token {
+ public:
+  explicit UnknownToken(const char* arg) {
+    int size = strlen(arg) + 1;
+    unknown_ = new char[size];
+    strncpy(unknown_, arg, size);
+  }
+  virtual ~UnknownToken() { delete[] unknown_; }
+
+  virtual bool IsUnknown() const { return true; }
+  virtual void Print(FILE* out = stdout) const;
+
+ private:
+  char* unknown_;
+};
+
+
+// All debugger commands must subclass DebugCommand and implement Run, Print
+// and Build. Commands must also define kHelp and kAliases.
+class DebugCommand {
+ public:
+  explicit DebugCommand(Token* name) : name_(IdentifierToken::Cast(name)) {}
+  DebugCommand() : name_(NULL) {}
+  virtual ~DebugCommand() { delete name_; }
+
+  const char* name() { return name_->value(); }
+  // Run the command on the given debugger. The command returns true if
+  // execution should move to the next instruction.
+  virtual bool Run(Debugger * debugger) = 0;
+  virtual void Print(FILE* out = stdout);
+
+  static bool Match(const char* name, const char** aliases);
+  static DebugCommand* Parse(char* line);
+  static void PrintHelp(const char** aliases,
+                        const char* args,
+                        const char* help);
+
+ private:
+  IdentifierToken* name_;
+};
+
+// For all commands below see their respective kHelp and kAliases in
+// debugger-a64.cc
+class HelpCommand : public DebugCommand {
+ public:
+  explicit HelpCommand(Token* name) : DebugCommand(name) {}
+
+  virtual bool Run(Debugger* debugger);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+};
+
+
+class ContinueCommand : public DebugCommand {
+ public:
+  explicit ContinueCommand(Token* name) : DebugCommand(name) {}
+
+  virtual bool Run(Debugger* debugger);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+};
+
+
+class StepCommand : public DebugCommand {
+ public:
+  StepCommand(Token* name, IntegerToken* count)
+      : DebugCommand(name), count_(count) {}
+  virtual ~StepCommand() { delete count_; }
+
+  int64_t count() { return count_->value(); }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  IntegerToken* count_;
+};
+
+class DisasmCommand : public DebugCommand {
+ public:
+  DisasmCommand(Token* name, Token* target, IntegerToken* count)
+      : DebugCommand(name), target_(target), count_(count) {}
+  virtual ~DisasmCommand() {
+    delete target_;
+    delete count_;
+  }
+
+  Token* target() { return target_; }
+  int64_t count() { return count_->value(); }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  Token* target_;
+  IntegerToken* count_;
+};
+
+
+class PrintCommand : public DebugCommand {
+ public:
+  PrintCommand(Token* name, Token* target)
+      : DebugCommand(name), target_(target) {}
+  virtual ~PrintCommand() { delete target_; }
+
+  Token* target() { return target_; }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  Token* target_;
+};
+
+class MemCommand : public DebugCommand {
+ public:
+  MemCommand(Token* name,
+             Token* target,
+             IntegerToken* count,
+             FormatToken* format)
+      : DebugCommand(name), target_(target), count_(count), format_(format) {}
+  virtual ~MemCommand() {
+    delete target_;
+    delete count_;
+    delete format_;
+  }
+
+  Token* target() { return target_; }
+  int64_t count() { return count_->value(); }
+  FormatToken* format() { return format_; }
+  virtual bool Run(Debugger* debugger);
+  virtual void Print(FILE* out = stdout);
+
+  static DebugCommand* Build(std::vector<Token*> args);
+
+  static const char* kHelp;
+  static const char* kAliases[];
+  static const char* kArguments;
+
+ private:
+  Token* target_;
+  IntegerToken* count_;
+  FormatToken* format_;
+};
+
+// Commands which name does not match any of the known commnand.
+class UnknownCommand : public DebugCommand {
+ public:
+  explicit UnknownCommand(std::vector<Token*> args) : args_(args) {}
+  virtual ~UnknownCommand();
+
+  virtual bool Run(Debugger* debugger);
+
+ private:
+  std::vector<Token*> args_;
+};
+
+// Commands which name match a known command but the syntax is invalid.
+class InvalidCommand : public DebugCommand {
+ public:
+  InvalidCommand(std::vector<Token*> args, int index, const char* cause)
+      : args_(args), index_(index), cause_(cause) {}
+  virtual ~InvalidCommand();
+
+  virtual bool Run(Debugger* debugger);
+
+ private:
+  std::vector<Token*> args_;
+  int index_;
+  const char* cause_;
+};
+
+const char* HelpCommand::kAliases[] = { "help", NULL };
+const char* HelpCommand::kArguments = NULL;
+const char* HelpCommand::kHelp = "  print this help";
+
+const char* ContinueCommand::kAliases[] = { "continue", "c", NULL };
+const char* ContinueCommand::kArguments = NULL;
+const char* ContinueCommand::kHelp = "  resume execution";
+
+const char* StepCommand::kAliases[] = { "stepi", "si", NULL };
+const char* StepCommand::kArguments = "[n = 1]";
+const char* StepCommand::kHelp = "  execute n next instruction(s)";
+
+const char* DisasmCommand::kAliases[] = { "dis", "d", NULL };
+const char* DisasmCommand::kArguments = "[addr = pc] [n = 1]";
+const char* DisasmCommand::kHelp =
+  "  disassemble n instruction(s) at address addr.\n"
+  "  addr can be an immediate address, a register or the pc."
+;
+
+const char* PrintCommand::kAliases[] = { "print", "p", NULL };
+const char* PrintCommand::kArguments =  "<entity>";
+const char* PrintCommand::kHelp =
+  "  print the given entity\n"
+  "  entity can be 'regs' for W and X registers, 'fpregs' for S and D\n"
+  "  registers, 'sysregs' for system registers (including NZCV) or 'pc'."
+;
+
+const char* MemCommand::kAliases[] = { "mem", "m", NULL };
+const char* MemCommand::kArguments = "<addr> [n = 1] [format = %x]";
+const char* MemCommand::kHelp =
+  "  print n memory item(s) at address addr according to the given format.\n"
+  "  addr can be an immediate address, a register or the pc.\n"
+  "  format is made of a qualifer: 's', 'u', 'a' (signed, unsigned, hexa)\n"
+  "  and a type 'x', 'w', 'h', 'b' (64- to 8-bit integer), 'c' (character),\n"
+  "  's' (float) or 'd' (double). E.g 'mem sp %w' will print a 32-bit word\n"
+  "  from the stack as an hexadecimal number."
+;
+
+const char* RegisterToken::kXAliases[kNumberOfRegisters][kMaxAliasNumber] = {
+  { "x0", NULL },
+  { "x1", NULL },
+  { "x2", NULL },
+  { "x3", NULL },
+  { "x4", NULL },
+  { "x5", NULL },
+  { "x6", NULL },
+  { "x7", NULL },
+  { "x8", NULL },
+  { "x9", NULL },
+  { "x10", NULL },
+  { "x11", NULL },
+  { "x12", NULL },
+  { "x13", NULL },
+  { "x14", NULL },
+  { "x15", NULL },
+  { "ip0", "x16", NULL },
+  { "ip1", "x17", NULL },
+  { "x18", "pr", NULL },
+  { "x19", NULL },
+  { "x20", NULL },
+  { "x21", NULL },
+  { "x22", NULL },
+  { "x23", NULL },
+  { "x24", NULL },
+  { "x25", NULL },
+  { "x26", NULL },
+  { "x27", NULL },
+  { "x28", NULL },
+  { "fp", "x29", NULL },
+  { "lr", "x30", NULL },
+  { "sp", NULL}
+};
+
+const char* RegisterToken::kWAliases[kNumberOfRegisters][kMaxAliasNumber] = {
+  { "w0", NULL },
+  { "w1", NULL },
+  { "w2", NULL },
+  { "w3", NULL },
+  { "w4", NULL },
+  { "w5", NULL },
+  { "w6", NULL },
+  { "w7", NULL },
+  { "w8", NULL },
+  { "w9", NULL },
+  { "w10", NULL },
+  { "w11", NULL },
+  { "w12", NULL },
+  { "w13", NULL },
+  { "w14", NULL },
+  { "w15", NULL },
+  { "w16", NULL },
+  { "w17", NULL },
+  { "w18", NULL },
+  { "w19", NULL },
+  { "w20", NULL },
+  { "w21", NULL },
+  { "w22", NULL },
+  { "w23", NULL },
+  { "w24", NULL },
+  { "w25", NULL },
+  { "w26", NULL },
+  { "w27", NULL },
+  { "w28", NULL },
+  { "w29", NULL },
+  { "w30", NULL },
+  { "wsp", NULL }
+};
+
+
+Debugger::Debugger(Decoder* decoder, FILE* stream)
+    : Simulator(decoder, stream),
+      log_parameters_(0),
+      debug_parameters_(0),
+      pending_request_(false),
+      steps_(0),
+      last_command_(NULL) {
+  disasm_ = new PrintDisassembler(stdout);
+  printer_ = new Decoder();
+  printer_->AppendVisitor(disasm_);
+}
+
+
+void Debugger::Run() {
+  while (pc_ != kEndOfSimAddress) {
+    if (pending_request()) {
+      LogProcessorState();
+      RunDebuggerShell();
+    }
+
+    ExecuteInstruction();
+  }
+}
+
+
+void Debugger::PrintInstructions(void* address, int64_t count) {
+  if (count == 0) {
+    return;
+  }
+
+  Instruction* from = Instruction::Cast(address);
+  if (count < 0) {
+    count = -count;
+    from -= (count - 1) * kInstructionSize;
+  }
+  Instruction* to = from + count * kInstructionSize;
+
+  for (Instruction* current = from;
+       current < to;
+       current = current->NextInstruction()) {
+    printer_->Decode(current);
+  }
+}
+
+
+void Debugger::PrintMemory(const uint8_t* address,
+                           int64_t count,
+                           const FormatToken* format) {
+  if (count == 0) {
+    return;
+  }
+
+  const uint8_t* from = address;
+  int size = format->SizeOf();
+  if (count < 0) {
+    count = -count;
+    from -= (count - 1) * size;
+  }
+  const uint8_t* to = from + count * size;
+
+  for (const uint8_t* current = from; current < to; current += size) {
+    if (((current - from) % 16) == 0) {
+      printf("\n%p: ", current);
+    }
+
+    uint64_t data = MemoryRead(current, size);
+    format->PrintData(&data);
+    printf(" ");
+  }
+  printf("\n\n");
+}
+
+
+void Debugger::VisitException(Instruction* instr) {
+  switch (instr->Mask(ExceptionMask)) {
+    case BRK:
+      DoBreakpoint(instr);
+      return;
+    case HLT:
+      switch (instr->ImmException()) {
+        case kUnreachableOpcode:
+          DoUnreachable(instr);
+          return;
+        case kTraceOpcode:
+          DoTrace(instr);
+          return;
+        case kLogOpcode:
+          DoLog(instr);
+          return;
+      }
+      // Fall through
+    default: Simulator::VisitException(instr);
+  }
+}
+
+
+void Debugger::LogSystemRegisters() {
+  if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters();
+}
+
+
+void Debugger::LogRegisters() {
+  if (log_parameters_ & LOG_REGS) PrintRegisters();
+}
+
+
+void Debugger::LogFPRegisters() {
+  if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters();
+}
+
+
+void Debugger::LogProcessorState() {
+  LogSystemRegisters();
+  LogRegisters();
+  LogFPRegisters();
+}
+
+
+// Read a command. A command will be at most kMaxDebugShellLine char long and
+// ends with '\n\0'.
+// TODO: Should this be a utility function?
+char* Debugger::ReadCommandLine(const char* prompt, char* buffer, int length) {
+  int fgets_calls = 0;
+  char* end = NULL;
+
+  printf("%s", prompt);
+  fflush(stdout);
+
+  do {
+    if (fgets(buffer, length, stdin) == NULL) {
+      printf(" ** Error while reading command. **\n");
+      return NULL;
+    }
+
+    fgets_calls++;
+    end = strchr(buffer, '\n');
+  } while (end == NULL);
+
+  if (fgets_calls != 1) {
+    printf(" ** Command too long. **\n");
+    return NULL;
+  }
+
+  // Remove the newline from the end of the command.
+  ASSERT(end[1] == '\0');
+  ASSERT((end - buffer) < (length - 1));
+  end[0] = '\0';
+
+  return buffer;
+}
+
+
+void Debugger::RunDebuggerShell() {
+  if (IsDebuggerRunning()) {
+    if (steps_ > 0) {
+      // Finish stepping first.
+      --steps_;
+      return;
+    }
+
+    printf("Next: ");
+    PrintInstructions(pc());
+    bool done = false;
+    while (!done) {
+      char buffer[kMaxDebugShellLine];
+      char* line = ReadCommandLine("vixl> ", buffer, kMaxDebugShellLine);
+
+      if (line == NULL) continue;  // An error occurred.
+
+      DebugCommand* command = DebugCommand::Parse(line);
+      if (command != NULL) {
+        last_command_ = command;
+      }
+
+      if (last_command_ != NULL) {
+        done = last_command_->Run(this);
+      } else {
+        printf("No previous command to run!\n");
+      }
+    }
+
+    if ((debug_parameters_ & DBG_BREAK) != 0) {
+      // The break request has now been handled, move to next instruction.
+      debug_parameters_ &= ~DBG_BREAK;
+      increment_pc();
+    }
+  }
+}
+
+
+void Debugger::DoBreakpoint(Instruction* instr) {
+  ASSERT(instr->Mask(ExceptionMask) == BRK);
+
+  printf("Hit breakpoint at pc=%p.\n", reinterpret_cast<void*>(instr));
+  set_debug_parameters(debug_parameters() | DBG_BREAK | DBG_ACTIVE);
+  // Make the shell point to the brk instruction.
+  set_pc(instr);
+}
+
+
+void Debugger::DoUnreachable(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kUnreachableOpcode));
+
+  fprintf(stream_, "Hit UNREACHABLE marker at pc=%p.\n",
+          reinterpret_cast<void*>(instr));
+  abort();
+}
+
+
+void Debugger::DoTrace(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kTraceOpcode));
+
+  // Read the arguments encoded inline in the instruction stream.
+  uint32_t parameters;
+  uint32_t command;
+
+  ASSERT(sizeof(*instr) == 1);
+  memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
+  memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
+
+  switch (command) {
+    case TRACE_ENABLE:
+      set_log_parameters(log_parameters() | parameters);
+      break;
+    case TRACE_DISABLE:
+      set_log_parameters(log_parameters() & ~parameters);
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  set_pc(instr->InstructionAtOffset(kTraceLength));
+}
+
+
+void Debugger::DoLog(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kLogOpcode));
+
+  // Read the arguments encoded inline in the instruction stream.
+  uint32_t parameters;
+
+  ASSERT(sizeof(*instr) == 1);
+  memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
+
+  // We don't support a one-shot LOG_DISASM.
+  ASSERT((parameters & LOG_DISASM) == 0);
+  // Print the requested information.
+  if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true);
+  if (parameters & LOG_REGS) PrintRegisters(true);
+  if (parameters & LOG_FP_REGS) PrintFPRegisters(true);
+
+  set_pc(instr->InstructionAtOffset(kLogLength));
+}
+
+
+static bool StringToUInt64(uint64_t* value, const char* line, int base = 10) {
+  char* endptr = NULL;
+  errno = 0;  // Reset errors.
+  uint64_t parsed = strtoul(line, &endptr, base);
+
+  if (errno == ERANGE) {
+    // Overflow.
+    return false;
+  }
+
+  if (endptr == line) {
+    // No digits were parsed.
+    return false;
+  }
+
+  if (*endptr != '\0') {
+    // Non-digit characters present at the end.
+    return false;
+  }
+
+  *value = parsed;
+  return true;
+}
+
+
+static bool StringToInt64(int64_t* value, const char* line, int base = 10) {
+  char* endptr = NULL;
+  errno = 0;  // Reset errors.
+  int64_t parsed = strtol(line, &endptr, base);
+
+  if (errno == ERANGE) {
+    // Overflow, undeflow.
+    return false;
+  }
+
+  if (endptr == line) {
+    // No digits were parsed.
+    return false;
+  }
+
+  if (*endptr != '\0') {
+    // Non-digit characters present at the end.
+    return false;
+  }
+
+  *value = parsed;
+  return true;
+}
+
+
+uint8_t* Token::ToAddress(Debugger* debugger) const {
+  USE(debugger);
+  UNREACHABLE();
+  return NULL;
+}
+
+
+Token* Token::Tokenize(const char* arg) {
+  if ((arg == NULL) || (*arg == '\0')) {
+    return NULL;
+  }
+
+  // The order is important. For example Identifier::Tokenize would consider
+  // any register to be a valid identifier.
+
+  Token* token = RegisterToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = FPRegisterToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = IdentifierToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = AddressToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = IntegerToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  token = FormatToken::Tokenize(arg);
+  if (token != NULL) {
+    return token;
+  }
+
+  return new UnknownToken(arg);
+}
+
+
+uint8_t* RegisterToken::ToAddress(Debugger* debugger) const {
+  ASSERT(CanAddressMemory());
+  uint64_t reg_value = debugger->xreg(value().code(), Reg31IsStackPointer);
+  uint8_t* address = NULL;
+  memcpy(&address, &reg_value, sizeof(address));
+  return address;
+}
+
+
+void RegisterToken::Print(FILE* out) const {
+  ASSERT(value().IsValid());
+  fprintf(out, "[Register %s]", Name());
+}
+
+
+const char* RegisterToken::Name() const {
+  if (value().Is32Bits()) {
+    return kWAliases[value().code()][0];
+  } else {
+    return kXAliases[value().code()][0];
+  }
+}
+
+
+Token* RegisterToken::Tokenize(const char* arg) {
+  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
+    // Is it a X register or alias?
+    for (const char** current = kXAliases[i]; *current != NULL; current++) {
+      if (strcmp(arg, *current) == 0) {
+        return new RegisterToken(Register::XRegFromCode(i));
+      }
+    }
+
+    // Is it a W register or alias?
+    for (const char** current = kWAliases[i]; *current != NULL; current++) {
+      if (strcmp(arg, *current) == 0) {
+        return new RegisterToken(Register::WRegFromCode(i));
+      }
+    }
+  }
+
+  return NULL;
+}
+
+
+void FPRegisterToken::Print(FILE* out) const {
+  ASSERT(value().IsValid());
+  char prefix = value().Is32Bits() ? 's' : 'd';
+  fprintf(out, "[FPRegister %c%" PRIu32 "]", prefix, value().code());
+}
+
+
+Token* FPRegisterToken::Tokenize(const char* arg) {
+  if (strlen(arg) < 2) {
+    return NULL;
+  }
+
+  switch (*arg) {
+    case 's':
+    case 'd':
+      const char* cursor = arg + 1;
+      uint64_t code = 0;
+      if (!StringToUInt64(&code, cursor)) {
+        return NULL;
+      }
+
+      if (code > kNumberOfFPRegisters) {
+        return NULL;
+      }
+
+      FPRegister fpreg = NoFPReg;
+      switch (*arg) {
+        case 's': fpreg = FPRegister::SRegFromCode(code); break;
+        case 'd': fpreg = FPRegister::DRegFromCode(code); break;
+        default: UNREACHABLE();
+      }
+
+      return new FPRegisterToken(fpreg);
+  }
+
+  return NULL;
+}
+
+
+uint8_t* IdentifierToken::ToAddress(Debugger* debugger) const {
+  ASSERT(CanAddressMemory());
+  Instruction* pc_value = debugger->pc();
+  uint8_t* address = NULL;
+  memcpy(&address, &pc_value, sizeof(address));
+  return address;
+}
+
+void IdentifierToken::Print(FILE* out) const {
+  fprintf(out, "[Identifier %s]", value());
+}
+
+
+Token* IdentifierToken::Tokenize(const char* arg) {
+  if (!isalpha(arg[0])) {
+    return NULL;
+  }
+
+  const char* cursor = arg + 1;
+  while ((*cursor != '\0') && isalnum(*cursor)) {
+    ++cursor;
+  }
+
+  if (*cursor == '\0') {
+    return new IdentifierToken(arg);
+  }
+
+  return NULL;
+}
+
+
+uint8_t* AddressToken::ToAddress(Debugger* debugger) const {
+  USE(debugger);
+  return value();
+}
+
+
+void AddressToken::Print(FILE* out) const {
+  fprintf(out, "[Address %p]", value());
+}
+
+
+Token* AddressToken::Tokenize(const char* arg) {
+  if ((strlen(arg) < 3) || (arg[0] != '0') || (arg[1] != 'x')) {
+    return NULL;
+  }
+
+  uint64_t ptr = 0;
+  if (!StringToUInt64(&ptr, arg, 16)) {
+    return NULL;
+  }
+
+  uint8_t* address = reinterpret_cast<uint8_t*>(ptr);
+  return new AddressToken(address);
+}
+
+
+void IntegerToken::Print(FILE* out) const {
+  fprintf(out, "[Integer %" PRId64 "]", value());
+}
+
+
+Token* IntegerToken::Tokenize(const char* arg) {
+  int64_t value = 0;
+  if (!StringToInt64(&value, arg)) {
+    return NULL;
+  }
+
+  return new IntegerToken(value);
+}
+
+
+Token* FormatToken::Tokenize(const char* arg) {
+  if (arg[0] != '%') {
+    return NULL;
+  }
+
+  int length = strlen(arg);
+  if ((length < 2) || (length > 3)) {
+    return NULL;
+  }
+
+  char type = arg[length - 1];
+  if (length == 2) {
+    switch (type) {
+      case 'x': return new Format<uint64_t>("%016" PRIx64);
+      case 'w': return new Format<uint32_t>("%08" PRIx32);
+      case 'h': return new Format<uint16_t>("%04" PRIx16);
+      case 'b': return new Format<uint8_t>("%02" PRIx8);
+      case 'c': return new Format<char>("%c");
+      case 'd': return new Format<double>("%g");
+      case 's': return new Format<float>("%g");
+      default: return NULL;
+    }
+  }
+
+  ASSERT(length == 3);
+  switch (arg[1]) {
+    case 's':
+      switch (type) {
+        case 'x': return new Format<int64_t>("%+20" PRId64);
+        case 'w': return new Format<int32_t>("%+11" PRId32);
+        case 'h': return new Format<int16_t>("%+6" PRId16);
+        case 'b': return new Format<int8_t>("%+4" PRId8);
+        default: return NULL;
+      }
+    case 'u':
+      switch (type) {
+        case 'x': return new Format<uint64_t>("%20" PRIu64);
+        case 'w': return new Format<uint32_t>("%10" PRIu32);
+        case 'h': return new Format<uint16_t>("%5" PRIu16);
+        case 'b': return new Format<uint8_t>("%3" PRIu8);
+        default: return NULL;
+      }
+    case 'a':
+      switch (type) {
+        case 'd': return new Format<double>("%a");
+        case 's': return new Format<float>("%a");
+        default: return NULL;
+      }
+    default: return NULL;
+  }
+}
+
+
+template<typename T>
+void Format<T>::Print(FILE* out) const {
+  fprintf(out, "[Format %s - %lu byte(s)]", fmt_, sizeof(T));
+}
+
+
+void UnknownToken::Print(FILE* out) const {
+  fprintf(out, "[Unknown %s]", unknown_);
+}
+
+
+void DebugCommand::Print(FILE* out) {
+  fprintf(out, "%s", name());
+}
+
+
+bool DebugCommand::Match(const char* name, const char** aliases) {
+  for (const char** current = aliases; *current != NULL; current++) {
+    if (strcmp(name, *current) == 0) {
+       return true;
+    }
+  }
+
+  return false;
+}
+
+
+DebugCommand* DebugCommand::Parse(char* line) {
+  std::vector<Token*> args;
+
+  for (char* chunk = strtok(line, " ");
+       chunk != NULL;
+       chunk = strtok(NULL, " ")) {
+    args.push_back(Token::Tokenize(chunk));
+  }
+
+  if (args.size() == 0) {
+    return NULL;
+  }
+
+  if (!args[0]->IsIdentifier()) {
+    return new InvalidCommand(args, 0, "command name is not an identifier");
+  }
+
+  const char* name = IdentifierToken::Cast(args[0])->value();
+  #define RETURN_IF_MATCH(Command)       \
+  if (Match(name, Command::kAliases)) {  \
+    return Command::Build(args);         \
+  }
+  DEBUG_COMMAND_LIST(RETURN_IF_MATCH);
+  #undef RETURN_IF_MATCH
+
+  return new UnknownCommand(args);
+}
+
+
+void DebugCommand::PrintHelp(const char** aliases,
+                             const char* args,
+                             const char* help) {
+  ASSERT(aliases[0] != NULL);
+  ASSERT(help != NULL);
+
+  printf("\n----\n\n");
+  for (const char** current = aliases; *current != NULL; current++) {
+    if (args != NULL) {
+      printf("%s %s\n", *current, args);
+    } else {
+      printf("%s\n", *current);
+    }
+  }
+  printf("\n%s\n", help);
+}
+
+
+bool HelpCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+  USE(debugger);
+
+  #define PRINT_HELP(Command)                     \
+    DebugCommand::PrintHelp(Command::kAliases,    \
+                            Command::kArguments,  \
+                            Command::kHelp);
+  DEBUG_COMMAND_LIST(PRINT_HELP);
+  #undef PRINT_HELP
+  printf("\n----\n\n");
+
+  return false;
+}
+
+
+DebugCommand* HelpCommand::Build(std::vector<Token*> args) {
+  if (args.size() != 1) {
+    return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new HelpCommand(args[0]);
+}
+
+
+bool ContinueCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  debugger->set_debug_parameters(debugger->debug_parameters() & ~DBG_ACTIVE);
+  return true;
+}
+
+
+DebugCommand* ContinueCommand::Build(std::vector<Token*> args) {
+  if (args.size() != 1) {
+    return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new ContinueCommand(args[0]);
+}
+
+
+bool StepCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  int64_t steps = count();
+  if (steps < 0) {
+    printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
+  } else if (steps > 1) {
+    debugger->set_steps(steps - 1);
+  }
+
+  return true;
+}
+
+
+void StepCommand::Print(FILE* out) {
+  fprintf(out, "%s %" PRId64 "", name(), count());
+}
+
+
+DebugCommand* StepCommand::Build(std::vector<Token*> args) {
+  IntegerToken* count = NULL;
+  switch (args.size()) {
+    case 1: {  // step [1]
+      count = new IntegerToken(1);
+      break;
+    }
+    case 2: {  // step n
+      Token* first = args[1];
+      if (!first->IsInteger()) {
+        return new InvalidCommand(args, 1, "expects int");
+      }
+      count = IntegerToken::Cast(first);
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new StepCommand(args[0], count);
+}
+
+
+bool DisasmCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  uint8_t* from = target()->ToAddress(debugger);
+  debugger->PrintInstructions(from, count());
+
+  return false;
+}
+
+
+void DisasmCommand::Print(FILE* out) {
+  fprintf(out, "%s ", name());
+  target()->Print(out);
+  fprintf(out, " %" PRId64 "", count());
+}
+
+
+DebugCommand* DisasmCommand::Build(std::vector<Token*> args) {
+  Token* address = NULL;
+  IntegerToken* count = NULL;
+  switch (args.size()) {
+    case 1: {  // disasm [pc] [1]
+      address = new IdentifierToken("pc");
+      count = new IntegerToken(1);
+      break;
+    }
+    case 2: {  // disasm [pc] n or disasm address [1]
+      Token* first = args[1];
+      if (first->IsInteger()) {
+        address = new IdentifierToken("pc");
+        count = IntegerToken::Cast(first);
+      } else if (first->CanAddressMemory()) {
+        address = first;
+        count = new IntegerToken(1);
+      } else {
+        return new InvalidCommand(args, 1, "expects int or addr");
+      }
+      break;
+    }
+    case 3: {  // disasm address count
+      Token* first = args[1];
+      Token* second = args[2];
+      if (!first->CanAddressMemory() || !second->IsInteger()) {
+        return new InvalidCommand(args, -1, "disasm addr int");
+      }
+      address = first;
+      count = IntegerToken::Cast(second);
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "wrong arguments number");
+  }
+
+  return new DisasmCommand(args[0], address, count);
+}
+
+
+void PrintCommand::Print(FILE* out) {
+  fprintf(out, "%s ", name());
+  target()->Print(out);
+}
+
+
+bool PrintCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  Token* tok = target();
+  if (tok->IsIdentifier()) {
+    char* identifier = IdentifierToken::Cast(tok)->value();
+    if (strcmp(identifier, "regs") == 0) {
+      debugger->PrintRegisters(true);
+    } else if (strcmp(identifier, "fpregs") == 0) {
+      debugger->PrintFPRegisters(true);
+    } else if (strcmp(identifier, "sysregs") == 0) {
+      debugger->PrintSystemRegisters(true);
+    } else if (strcmp(identifier, "pc") == 0) {
+      printf("pc = %16p\n", reinterpret_cast<void*>(debugger->pc()));
+    } else {
+      printf(" ** Unknown identifier to print: %s **\n", identifier);
+    }
+
+    return false;
+  }
+
+  if (tok->IsRegister()) {
+    RegisterToken* reg_tok = RegisterToken::Cast(tok);
+    Register reg = reg_tok->value();
+    if (reg.Is32Bits()) {
+      printf("%s = %" PRId32 "\n",
+             reg_tok->Name(),
+             debugger->wreg(reg.code(), Reg31IsStackPointer));
+    } else {
+      printf("%s = %" PRId64 "\n",
+             reg_tok->Name(),
+             debugger->xreg(reg.code(), Reg31IsStackPointer));
+    }
+
+    return false;
+  }
+
+  if (tok->IsFPRegister()) {
+    FPRegister fpreg = FPRegisterToken::Cast(tok)->value();
+    if (fpreg.Is32Bits()) {
+      printf("s%u = %g\n", fpreg.code(), debugger->sreg(fpreg.code()));
+    } else {
+      printf("d%u = %g\n", fpreg.code(), debugger->dreg(fpreg.code()));
+    }
+
+    return false;
+  }
+
+  UNREACHABLE();
+  return false;
+}
+
+
+DebugCommand* PrintCommand::Build(std::vector<Token*> args) {
+  Token* target = NULL;
+  switch (args.size()) {
+    case 2: {
+      target = args[1];
+      if (!target->IsRegister()
+          && !target->IsFPRegister()
+          && !target->IsIdentifier()) {
+        return new InvalidCommand(args, 1, "expects reg or identifier");
+      }
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new PrintCommand(args[0], target);
+}
+
+
+bool MemCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+
+  uint8_t* address = target()->ToAddress(debugger);
+  debugger->PrintMemory(address, count(), format());
+
+  return false;
+}
+
+
+void MemCommand::Print(FILE* out) {
+  fprintf(out, "%s ", name());
+  target()->Print(out);
+  fprintf(out, " %" PRId64 " ", count());
+  format()->Print(out);
+}
+
+
+DebugCommand* MemCommand::Build(std::vector<Token*> args) {
+  if (args.size() < 2) {
+    return new InvalidCommand(args, -1, "too few arguments");
+  }
+
+  Token* target = args[1];
+  IntegerToken* count = NULL;
+  FormatToken* format = NULL;
+
+  if (!target->CanAddressMemory()) {
+    return new InvalidCommand(args, 1, "expects address");
+  }
+
+  switch (args.size()) {
+    case 2: {  // mem addressable [1] [%x]
+      count = new IntegerToken(1);
+      format = new Format<uint64_t>("%016x");
+      break;
+    }
+    case 3: {  // mem addr n [%x] or mem addr [n] %f
+      Token* second = args[2];
+      if (second->IsInteger()) {
+        count = IntegerToken::Cast(second);
+        format = new Format<uint64_t>("%016x");
+      } else if (second->IsFormat()) {
+        count = new IntegerToken(1);
+        format = FormatToken::Cast(second);
+      } else {
+        return new InvalidCommand(args, 2, "expects int or format");
+      }
+      break;
+    }
+    case 4: {  // mem addr n %f
+      Token* second = args[2];
+      Token* third = args[3];
+      if (!second->IsInteger() || !third->IsFormat()) {
+        return new InvalidCommand(args, -1, "mem addr >>int<< %F");
+      }
+
+      count = IntegerToken::Cast(second);
+      format = FormatToken::Cast(third);
+      break;
+    }
+    default:
+      return new InvalidCommand(args, -1, "too many arguments");
+  }
+
+  return new MemCommand(args[0], target, count, format);
+}
+
+
+UnknownCommand::~UnknownCommand() {
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    delete args_[i];
+  }
+}
+
+
+bool UnknownCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+  USE(debugger);
+
+  printf(" ** Unknown Command:");
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    printf(" ");
+    args_[i]->Print(stdout);
+  }
+  printf(" **\n");
+
+  return false;
+}
+
+
+InvalidCommand::~InvalidCommand() {
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    delete args_[i];
+  }
+}
+
+
+bool InvalidCommand::Run(Debugger* debugger) {
+  ASSERT(debugger->IsDebuggerRunning());
+  USE(debugger);
+
+  printf(" ** Invalid Command:");
+  const int size = args_.size();
+  for (int i = 0; i < size; ++i) {
+    printf(" ");
+    if (i == index_) {
+      printf(">>");
+      args_[i]->Print(stdout);
+      printf("<<");
+    } else {
+      args_[i]->Print(stdout);
+    }
+  }
+  printf(" **\n");
+  printf(" ** %s\n", cause_);
+
+  return false;
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/debugger-a64.h b/disas/libvixl/src/a64/debugger-a64.h
new file mode 100644
index 0000000..542d202
--- /dev/null
+++ b/disas/libvixl/src/a64/debugger-a64.h
@@ -0,0 +1,188 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_DEBUGGER_A64_H_
+#define VIXL_A64_DEBUGGER_A64_H_
+
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <vector>
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/constants-a64.h"
+#include "a64/simulator-a64.h"
+
+namespace vixl {
+
+// Debug instructions.
+//
+// VIXL's macro-assembler and debugger support a few pseudo instructions to
+// make debugging easier. These pseudo instructions do not exist on real
+// hardware.
+//
+// Each debug pseudo instruction is represented by a HLT instruction. The HLT
+// immediate field is used to identify the type of debug pseudo isntruction.
+// Each pseudo instruction use a custom encoding for additional arguments, as
+// described below.
+
+// Unreachable
+//
+// Instruction which should never be executed. This is used as a guard in parts
+// of the code that should not be reachable, such as in data encoded inline in
+// the instructions.
+const Instr kUnreachableOpcode = 0xdeb0;
+
+// Trace
+//  - parameter: TraceParameter stored as a uint32_t
+//  - command: TraceCommand stored as a uint32_t
+//
+// Allow for trace management in the generated code. See the corresponding
+// enums for more information on permitted actions.
+const Instr kTraceOpcode = 0xdeb2;
+const unsigned kTraceParamsOffset = 1 * kInstructionSize;
+const unsigned kTraceCommandOffset = 2 * kInstructionSize;
+const unsigned kTraceLength = 3 * kInstructionSize;
+
+// Log
+//  - parameter: TraceParameter stored as a uint32_t
+//
+// Output the requested information.
+const Instr kLogOpcode = 0xdeb3;
+const unsigned kLogParamsOffset = 1 * kInstructionSize;
+const unsigned kLogLength = 2 * kInstructionSize;
+
+// Trace commands.
+enum TraceCommand {
+  TRACE_ENABLE   = 1,
+  TRACE_DISABLE  = 2
+};
+
+// Trace parameters.
+enum TraceParameters {
+  LOG_DISASM     = 1 << 0,  // Log disassembly.
+  LOG_REGS       = 1 << 1,  // Log general purpose registers.
+  LOG_FP_REGS    = 1 << 2,  // Log floating-point registers.
+  LOG_SYS_REGS   = 1 << 3,  // Log the flags and system registers.
+
+  LOG_STATE      = LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS,
+  LOG_ALL        = LOG_DISASM | LOG_REGS | LOG_FP_REGS | LOG_SYS_REGS
+};
+
+// Debugger parameters
+enum DebugParameters {
+  DBG_ACTIVE = 1 << 0,  // The debugger is active.
+  DBG_BREAK  = 1 << 1   // The debugger is at a breakpoint.
+};
+
+// Forward declarations.
+class DebugCommand;
+class Token;
+class FormatToken;
+
+class Debugger : public Simulator {
+ public:
+  Debugger(Decoder* decoder, FILE* stream = stdout);
+
+  virtual void Run();
+  void VisitException(Instruction* instr);
+
+  inline int log_parameters() {
+    // The simulator can control disassembly, so make sure that the Debugger's
+    // log parameters agree with it.
+    if (disasm_trace()) {
+      log_parameters_ |= LOG_DISASM;
+    }
+    return log_parameters_;
+  }
+  inline void set_log_parameters(int parameters) {
+    set_disasm_trace((parameters & LOG_DISASM) != 0);
+    log_parameters_ = parameters;
+
+    update_pending_request();
+  }
+
+  inline int debug_parameters() { return debug_parameters_; }
+  inline void set_debug_parameters(int parameters) {
+    debug_parameters_ = parameters;
+
+    update_pending_request();
+  }
+
+  // Numbers of instructions to execute before the debugger shell is given
+  // back control.
+  inline int steps() { return steps_; }
+  inline void set_steps(int value) {
+    ASSERT(value > 1);
+    steps_ = value;
+  }
+
+  inline bool IsDebuggerRunning() {
+    return (debug_parameters_ & DBG_ACTIVE) != 0;
+  }
+
+  inline bool pending_request() { return pending_request_; }
+  inline void update_pending_request() {
+    const int kLoggingMask = LOG_STATE;
+    const bool logging = (log_parameters_ & kLoggingMask) != 0;
+    const bool debugging = IsDebuggerRunning();
+
+    pending_request_ = logging || debugging;
+  }
+
+  void PrintInstructions(void* address, int64_t count = 1);
+  void PrintMemory(const uint8_t* address,
+                   int64_t count,
+                   const FormatToken* format);
+
+ private:
+  void LogSystemRegisters();
+  void LogRegisters();
+  void LogFPRegisters();
+  void LogProcessorState();
+  char* ReadCommandLine(const char* prompt, char* buffer, int length);
+  void RunDebuggerShell();
+  void DoBreakpoint(Instruction* instr);
+  void DoUnreachable(Instruction* instr);
+  void DoTrace(Instruction* instr);
+  void DoLog(Instruction* instr);
+
+  int  log_parameters_;
+  int  debug_parameters_;
+  bool pending_request_;
+  int steps_;
+  DebugCommand* last_command_;
+  PrintDisassembler* disasm_;
+  Decoder* printer_;
+
+  // Length of the biggest command line accepted by the debugger shell.
+  static const int kMaxDebugShellLine = 256;
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_DEBUGGER_A64_H_
diff --git a/disas/libvixl/src/a64/decoder-a64.cc b/disas/libvixl/src/a64/decoder-a64.cc
new file mode 100644
index 0000000..9e9033c
--- /dev/null
+++ b/disas/libvixl/src/a64/decoder-a64.cc
@@ -0,0 +1,712 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/decoder-a64.h"
+
+namespace vixl {
+// Top-level instruction decode function.
+void Decoder::Decode(Instruction *instr) {
+  if (instr->Bits(28, 27) == 0) {
+    VisitUnallocated(instr);
+  } else {
+    switch (instr->Bits(27, 24)) {
+      // 0:   PC relative addressing.
+      case 0x0: DecodePCRelAddressing(instr); break;
+
+      // 1:   Add/sub immediate.
+      case 0x1: DecodeAddSubImmediate(instr); break;
+
+      // A:   Logical shifted register.
+      //      Add/sub with carry.
+      //      Conditional compare register.
+      //      Conditional compare immediate.
+      //      Conditional select.
+      //      Data processing 1 source.
+      //      Data processing 2 source.
+      // B:   Add/sub shifted register.
+      //      Add/sub extended register.
+      //      Data processing 3 source.
+      case 0xA:
+      case 0xB: DecodeDataProcessing(instr); break;
+
+      // 2:   Logical immediate.
+      //      Move wide immediate.
+      case 0x2: DecodeLogical(instr); break;
+
+      // 3:   Bitfield.
+      //      Extract.
+      case 0x3: DecodeBitfieldExtract(instr); break;
+
+      // 4:   Unconditional branch immediate.
+      //      Exception generation.
+      //      Compare and branch immediate.
+      // 5:   Compare and branch immediate.
+      //      Conditional branch.
+      //      System.
+      // 6,7: Unconditional branch.
+      //      Test and branch immediate.
+      case 0x4:
+      case 0x5:
+      case 0x6:
+      case 0x7: DecodeBranchSystemException(instr); break;
+
+      // 8,9: Load/store register pair post-index.
+      //      Load register literal.
+      //      Load/store register unscaled immediate.
+      //      Load/store register immediate post-index.
+      //      Load/store register immediate pre-index.
+      //      Load/store register offset.
+      //      Load/store exclusive.
+      // C,D: Load/store register pair offset.
+      //      Load/store register pair pre-index.
+      //      Load/store register unsigned immediate.
+      //      Advanced SIMD.
+      case 0x8:
+      case 0x9:
+      case 0xC:
+      case 0xD: DecodeLoadStore(instr); break;
+
+      // E:   FP fixed point conversion.
+      //      FP integer conversion.
+      //      FP data processing 1 source.
+      //      FP compare.
+      //      FP immediate.
+      //      FP data processing 2 source.
+      //      FP conditional compare.
+      //      FP conditional select.
+      //      Advanced SIMD.
+      // F:   FP data processing 3 source.
+      //      Advanced SIMD.
+      case 0xE:
+      case 0xF: DecodeFP(instr); break;
+    }
+  }
+}
+
+void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
+  visitors_.remove(new_visitor);
+  visitors_.push_front(new_visitor);
+}
+
+
+void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
+  visitors_.remove(new_visitor);
+  visitors_.push_back(new_visitor);
+}
+
+
+void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
+                                  DecoderVisitor* registered_visitor) {
+  visitors_.remove(new_visitor);
+  std::list<DecoderVisitor*>::iterator it;
+  for (it = visitors_.begin(); it != visitors_.end(); it++) {
+    if (*it == registered_visitor) {
+      visitors_.insert(it, new_visitor);
+      return;
+    }
+  }
+  // We reached the end of the list. The last element must be
+  // registered_visitor.
+  ASSERT(*it == registered_visitor);
+  visitors_.insert(it, new_visitor);
+}
+
+
+void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
+                                 DecoderVisitor* registered_visitor) {
+  visitors_.remove(new_visitor);
+  std::list<DecoderVisitor*>::iterator it;
+  for (it = visitors_.begin(); it != visitors_.end(); it++) {
+    if (*it == registered_visitor) {
+      it++;
+      visitors_.insert(it, new_visitor);
+      return;
+    }
+  }
+  // We reached the end of the list. The last element must be
+  // registered_visitor.
+  ASSERT(*it == registered_visitor);
+  visitors_.push_back(new_visitor);
+}
+
+
+void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
+  visitors_.remove(visitor);
+}
+
+
+void Decoder::DecodePCRelAddressing(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x0);
+  // We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
+  // decode.
+  ASSERT(instr->Bit(28) == 0x1);
+  VisitPCRelAddressing(instr);
+}
+
+
+void Decoder::DecodeBranchSystemException(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0x4) ||
+         (instr->Bits(27, 24) == 0x5) ||
+         (instr->Bits(27, 24) == 0x6) ||
+         (instr->Bits(27, 24) == 0x7) );
+
+  switch (instr->Bits(31, 29)) {
+    case 0:
+    case 4: {
+      VisitUnconditionalBranch(instr);
+      break;
+    }
+    case 1:
+    case 5: {
+      if (instr->Bit(25) == 0) {
+        VisitCompareBranch(instr);
+      } else {
+        VisitTestBranch(instr);
+      }
+      break;
+    }
+    case 2: {
+      if (instr->Bit(25) == 0) {
+        if ((instr->Bit(24) == 0x1) ||
+            (instr->Mask(0x01000010) == 0x00000010)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitConditionalBranch(instr);
+        }
+      } else {
+        VisitUnallocated(instr);
+      }
+      break;
+    }
+    case 6: {
+      if (instr->Bit(25) == 0) {
+        if (instr->Bit(24) == 0) {
+          if ((instr->Bits(4, 2) != 0) ||
+              (instr->Mask(0x00E0001D) == 0x00200001) ||
+              (instr->Mask(0x00E0001D) == 0x00400001) ||
+              (instr->Mask(0x00E0001E) == 0x00200002) ||
+              (instr->Mask(0x00E0001E) == 0x00400002) ||
+              (instr->Mask(0x00E0001C) == 0x00600000) ||
+              (instr->Mask(0x00E0001C) == 0x00800000) ||
+              (instr->Mask(0x00E0001F) == 0x00A00000) ||
+              (instr->Mask(0x00C0001C) == 0x00C00000)) {
+            VisitUnallocated(instr);
+          } else {
+            VisitException(instr);
+          }
+        } else {
+          if (instr->Bits(23, 22) == 0) {
+            const Instr masked_003FF0E0 = instr->Mask(0x003FF0E0);
+            if ((instr->Bits(21, 19) == 0x4) ||
+                (masked_003FF0E0 == 0x00033000) ||
+                (masked_003FF0E0 == 0x003FF020) ||
+                (masked_003FF0E0 == 0x003FF060) ||
+                (masked_003FF0E0 == 0x003FF0E0) ||
+                (instr->Mask(0x00388000) == 0x00008000) ||
+                (instr->Mask(0x0038E000) == 0x00000000) ||
+                (instr->Mask(0x0039E000) == 0x00002000) ||
+                (instr->Mask(0x003AE000) == 0x00002000) ||
+                (instr->Mask(0x003CE000) == 0x00042000) ||
+                (instr->Mask(0x003FFFC0) == 0x000320C0) ||
+                (instr->Mask(0x003FF100) == 0x00032100) ||
+                (instr->Mask(0x003FF200) == 0x00032200) ||
+                (instr->Mask(0x003FF400) == 0x00032400) ||
+                (instr->Mask(0x003FF800) == 0x00032800) ||
+                (instr->Mask(0x0038F000) == 0x00005000) ||
+                (instr->Mask(0x0038E000) == 0x00006000)) {
+              VisitUnallocated(instr);
+            } else {
+              VisitSystem(instr);
+            }
+          } else {
+            VisitUnallocated(instr);
+          }
+        }
+      } else {
+        if ((instr->Bit(24) == 0x1) ||
+            (instr->Bits(20, 16) != 0x1F) ||
+            (instr->Bits(15, 10) != 0) ||
+            (instr->Bits(4, 0) != 0) ||
+            (instr->Bits(24, 21) == 0x3) ||
+            (instr->Bits(24, 22) == 0x3)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitUnconditionalBranchToRegister(instr);
+        }
+      }
+      break;
+    }
+    case 3:
+    case 7: {
+      VisitUnallocated(instr);
+      break;
+    }
+  }
+}
+
+
+void Decoder::DecodeLoadStore(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0x8) ||
+         (instr->Bits(27, 24) == 0x9) ||
+         (instr->Bits(27, 24) == 0xC) ||
+         (instr->Bits(27, 24) == 0xD) );
+
+  if (instr->Bit(24) == 0) {
+    if (instr->Bit(28) == 0) {
+      if (instr->Bit(29) == 0) {
+        if (instr->Bit(26) == 0) {
+          // TODO: VisitLoadStoreExclusive.
+          VisitUnimplemented(instr);
+        } else {
+          DecodeAdvSIMDLoadStore(instr);
+        }
+      } else {
+        if ((instr->Bits(31, 30) == 0x3) ||
+            (instr->Mask(0xC4400000) == 0x40000000)) {
+          VisitUnallocated(instr);
+        } else {
+          if (instr->Bit(23) == 0) {
+            if (instr->Mask(0xC4400000) == 0xC0400000) {
+              VisitUnallocated(instr);
+            } else {
+              VisitLoadStorePairNonTemporal(instr);
+            }
+          } else {
+            VisitLoadStorePairPostIndex(instr);
+          }
+        }
+      }
+    } else {
+      if (instr->Bit(29) == 0) {
+        if (instr->Mask(0xC4000000) == 0xC4000000) {
+          VisitUnallocated(instr);
+        } else {
+          VisitLoadLiteral(instr);
+        }
+      } else {
+        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
+            (instr->Mask(0x44800000) == 0x44800000) ||
+            (instr->Mask(0x84800000) == 0x84800000)) {
+          VisitUnallocated(instr);
+        } else {
+          if (instr->Bit(21) == 0) {
+            switch (instr->Bits(11, 10)) {
+              case 0: {
+                VisitLoadStoreUnscaledOffset(instr);
+                break;
+              }
+              case 1: {
+                if (instr->Mask(0xC4C00000) == 0xC0800000) {
+                  VisitUnallocated(instr);
+                } else {
+                  VisitLoadStorePostIndex(instr);
+                }
+                break;
+              }
+              case 2: {
+                // TODO: VisitLoadStoreRegisterOffsetUnpriv.
+                VisitUnimplemented(instr);
+                break;
+              }
+              case 3: {
+                if (instr->Mask(0xC4C00000) == 0xC0800000) {
+                  VisitUnallocated(instr);
+                } else {
+                  VisitLoadStorePreIndex(instr);
+                }
+                break;
+              }
+            }
+          } else {
+            if (instr->Bits(11, 10) == 0x2) {
+              if (instr->Bit(14) == 0) {
+                VisitUnallocated(instr);
+              } else {
+                VisitLoadStoreRegisterOffset(instr);
+              }
+            } else {
+              VisitUnallocated(instr);
+            }
+          }
+        }
+      }
+    }
+  } else {
+    if (instr->Bit(28) == 0) {
+      if (instr->Bit(29) == 0) {
+        VisitUnallocated(instr);
+      } else {
+        if ((instr->Bits(31, 30) == 0x3) ||
+            (instr->Mask(0xC4400000) == 0x40000000)) {
+          VisitUnallocated(instr);
+        } else {
+          if (instr->Bit(23) == 0) {
+            VisitLoadStorePairOffset(instr);
+          } else {
+            VisitLoadStorePairPreIndex(instr);
+          }
+        }
+      }
+    } else {
+      if (instr->Bit(29) == 0) {
+        VisitUnallocated(instr);
+      } else {
+        if ((instr->Mask(0x84C00000) == 0x80C00000) ||
+            (instr->Mask(0x44800000) == 0x44800000) ||
+            (instr->Mask(0x84800000) == 0x84800000)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitLoadStoreUnsignedOffset(instr);
+        }
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeLogical(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x2);
+
+  if (instr->Mask(0x80400000) == 0x00400000) {
+    VisitUnallocated(instr);
+  } else {
+    if (instr->Bit(23) == 0) {
+      VisitLogicalImmediate(instr);
+    } else {
+      if (instr->Bits(30, 29) == 0x1) {
+        VisitUnallocated(instr);
+      } else {
+        VisitMoveWideImmediate(instr);
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeBitfieldExtract(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x3);
+
+  if ((instr->Mask(0x80400000) == 0x80000000) ||
+      (instr->Mask(0x80400000) == 0x00400000) ||
+      (instr->Mask(0x80008000) == 0x00008000)) {
+    VisitUnallocated(instr);
+  } else if (instr->Bit(23) == 0) {
+    if ((instr->Mask(0x80200000) == 0x00200000) ||
+        (instr->Mask(0x60000000) == 0x60000000)) {
+      VisitUnallocated(instr);
+    } else {
+      VisitBitfield(instr);
+    }
+  } else {
+    if ((instr->Mask(0x60200000) == 0x00200000) ||
+        (instr->Mask(0x60000000) != 0x00000000)) {
+      VisitUnallocated(instr);
+    } else {
+      VisitExtract(instr);
+    }
+  }
+}
+
+
+void Decoder::DecodeAddSubImmediate(Instruction* instr) {
+  ASSERT(instr->Bits(27, 24) == 0x1);
+  if (instr->Bit(23) == 1) {
+    VisitUnallocated(instr);
+  } else {
+    VisitAddSubImmediate(instr);
+  }
+}
+
+
+void Decoder::DecodeDataProcessing(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0xA) ||
+         (instr->Bits(27, 24) == 0xB) );
+
+  if (instr->Bit(24) == 0) {
+    if (instr->Bit(28) == 0) {
+      if (instr->Mask(0x80008000) == 0x00008000) {
+        VisitUnallocated(instr);
+      } else {
+        VisitLogicalShifted(instr);
+      }
+    } else {
+      switch (instr->Bits(23, 21)) {
+        case 0: {
+          if (instr->Mask(0x0000FC00) != 0) {
+            VisitUnallocated(instr);
+          } else {
+            VisitAddSubWithCarry(instr);
+          }
+          break;
+        }
+        case 2: {
+          if ((instr->Bit(29) == 0) ||
+              (instr->Mask(0x00000410) != 0)) {
+            VisitUnallocated(instr);
+          } else {
+            if (instr->Bit(11) == 0) {
+              VisitConditionalCompareRegister(instr);
+            } else {
+              VisitConditionalCompareImmediate(instr);
+            }
+          }
+          break;
+        }
+        case 4: {
+          if (instr->Mask(0x20000800) != 0x00000000) {
+            VisitUnallocated(instr);
+          } else {
+            VisitConditionalSelect(instr);
+          }
+          break;
+        }
+        case 6: {
+          if (instr->Bit(29) == 0x1) {
+            VisitUnallocated(instr);
+          } else {
+            if (instr->Bit(30) == 0) {
+              if ((instr->Bit(15) == 0x1) ||
+                  (instr->Bits(15, 11) == 0) ||
+                  (instr->Bits(15, 12) == 0x1) ||
+                  (instr->Bits(15, 12) == 0x3) ||
+                  (instr->Bits(15, 13) == 0x3) ||
+                  (instr->Mask(0x8000EC00) == 0x00004C00) ||
+                  (instr->Mask(0x8000E800) == 0x80004000) ||
+                  (instr->Mask(0x8000E400) == 0x80004000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitDataProcessing2Source(instr);
+              }
+            } else {
+              if ((instr->Bit(13) == 1) ||
+                  (instr->Bits(20, 16) != 0) ||
+                  (instr->Bits(15, 14) != 0) ||
+                  (instr->Mask(0xA01FFC00) == 0x00000C00) ||
+                  (instr->Mask(0x201FF800) == 0x00001800)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitDataProcessing1Source(instr);
+              }
+            }
+            break;
+          }
+        }
+        case 1:
+        case 3:
+        case 5:
+        case 7: VisitUnallocated(instr); break;
+      }
+    }
+  } else {
+    if (instr->Bit(28) == 0) {
+     if (instr->Bit(21) == 0) {
+        if ((instr->Bits(23, 22) == 0x3) ||
+            (instr->Mask(0x80008000) == 0x00008000)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitAddSubShifted(instr);
+        }
+      } else {
+        if ((instr->Mask(0x00C00000) != 0x00000000) ||
+            (instr->Mask(0x00001400) == 0x00001400) ||
+            (instr->Mask(0x00001800) == 0x00001800)) {
+          VisitUnallocated(instr);
+        } else {
+          VisitAddSubExtended(instr);
+        }
+      }
+    } else {
+      if ((instr->Bit(30) == 0x1) ||
+          (instr->Bits(30, 29) == 0x1) ||
+          (instr->Mask(0xE0600000) == 0x00200000) ||
+          (instr->Mask(0xE0608000) == 0x00400000) ||
+          (instr->Mask(0x60608000) == 0x00408000) ||
+          (instr->Mask(0x60E00000) == 0x00E00000) ||
+          (instr->Mask(0x60E00000) == 0x00800000) ||
+          (instr->Mask(0x60E00000) == 0x00600000)) {
+        VisitUnallocated(instr);
+      } else {
+        VisitDataProcessing3Source(instr);
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeFP(Instruction* instr) {
+  ASSERT((instr->Bits(27, 24) == 0xE) ||
+         (instr->Bits(27, 24) == 0xF) );
+
+  if (instr->Bit(28) == 0) {
+    DecodeAdvSIMDDataProcessing(instr);
+  } else {
+    if (instr->Bit(29) == 1) {
+      VisitUnallocated(instr);
+    } else {
+      if (instr->Bits(31, 30) == 0x3) {
+        VisitUnallocated(instr);
+      } else if (instr->Bits(31, 30) == 0x1) {
+        DecodeAdvSIMDDataProcessing(instr);
+      } else {
+        if (instr->Bit(24) == 0) {
+          if (instr->Bit(21) == 0) {
+            if ((instr->Bit(23) == 1) ||
+                (instr->Bit(18) == 1) ||
+                (instr->Mask(0x80008000) == 0x00000000) ||
+                (instr->Mask(0x000E0000) == 0x00000000) ||
+                (instr->Mask(0x000E0000) == 0x000A0000) ||
+                (instr->Mask(0x00160000) == 0x00000000) ||
+                (instr->Mask(0x00160000) == 0x00120000)) {
+              VisitUnallocated(instr);
+            } else {
+              VisitFPFixedPointConvert(instr);
+            }
+          } else {
+            if (instr->Bits(15, 10) == 32) {
+              VisitUnallocated(instr);
+            } else if (instr->Bits(15, 10) == 0) {
+              if ((instr->Bits(23, 22) == 0x3) ||
+                  (instr->Mask(0x000E0000) == 0x000A0000) ||
+                  (instr->Mask(0x000E0000) == 0x000C0000) ||
+                  (instr->Mask(0x00160000) == 0x00120000) ||
+                  (instr->Mask(0x00160000) == 0x00140000) ||
+                  (instr->Mask(0x20C40000) == 0x00800000) ||
+                  (instr->Mask(0x20C60000) == 0x00840000) ||
+                  (instr->Mask(0xA0C60000) == 0x80060000) ||
+                  (instr->Mask(0xA0C60000) == 0x00860000) ||
+                  (instr->Mask(0xA0C60000) == 0x00460000) ||
+                  (instr->Mask(0xA0CE0000) == 0x80860000) ||
+                  (instr->Mask(0xA0CE0000) == 0x804E0000) ||
+                  (instr->Mask(0xA0CE0000) == 0x000E0000) ||
+                  (instr->Mask(0xA0D60000) == 0x00160000) ||
+                  (instr->Mask(0xA0D60000) == 0x80560000) ||
+                  (instr->Mask(0xA0D60000) == 0x80960000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPIntegerConvert(instr);
+              }
+            } else if (instr->Bits(14, 10) == 16) {
+              const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
+              if ((instr->Mask(0x80180000) != 0) ||
+                  (masked_A0DF8000 == 0x00020000) ||
+                  (masked_A0DF8000 == 0x00030000) ||
+                  (masked_A0DF8000 == 0x00068000) ||
+                  (masked_A0DF8000 == 0x00428000) ||
+                  (masked_A0DF8000 == 0x00430000) ||
+                  (masked_A0DF8000 == 0x00468000) ||
+                  (instr->Mask(0xA0D80000) == 0x00800000) ||
+                  (instr->Mask(0xA0DE0000) == 0x00C00000) ||
+                  (instr->Mask(0xA0DF0000) == 0x00C30000) ||
+                  (instr->Mask(0xA0DC0000) == 0x00C40000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPDataProcessing1Source(instr);
+              }
+            } else if (instr->Bits(13, 10) == 8) {
+              if ((instr->Bits(15, 14) != 0) ||
+                  (instr->Bits(2, 0) != 0) ||
+                  (instr->Mask(0x80800000) != 0x00000000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPCompare(instr);
+              }
+            } else if (instr->Bits(12, 10) == 4) {
+              if ((instr->Bits(9, 5) != 0) ||
+                  (instr->Mask(0x80800000) != 0x00000000)) {
+                VisitUnallocated(instr);
+              } else {
+                VisitFPImmediate(instr);
+              }
+            } else {
+              if (instr->Mask(0x80800000) != 0x00000000) {
+                VisitUnallocated(instr);
+              } else {
+                switch (instr->Bits(11, 10)) {
+                  case 1: {
+                    VisitFPConditionalCompare(instr);
+                    break;
+                  }
+                  case 2: {
+                    if ((instr->Bits(15, 14) == 0x3) ||
+                        (instr->Mask(0x00009000) == 0x00009000) ||
+                        (instr->Mask(0x0000A000) == 0x0000A000)) {
+                      VisitUnallocated(instr);
+                    } else {
+                      VisitFPDataProcessing2Source(instr);
+                    }
+                    break;
+                  }
+                  case 3: {
+                    VisitFPConditionalSelect(instr);
+                    break;
+                  }
+                  default: UNREACHABLE();
+                }
+              }
+            }
+          }
+        } else {
+          // Bit 30 == 1 has been handled earlier.
+          ASSERT(instr->Bit(30) == 0);
+          if (instr->Mask(0xA0800000) != 0) {
+            VisitUnallocated(instr);
+          } else {
+            VisitFPDataProcessing3Source(instr);
+          }
+        }
+      }
+    }
+  }
+}
+
+
+void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) {
+  // TODO: Implement Advanced SIMD load/store instruction decode.
+  ASSERT(instr->Bits(29, 25) == 0x6);
+  VisitUnimplemented(instr);
+}
+
+
+void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) {
+  // TODO: Implement Advanced SIMD data processing instruction decode.
+  ASSERT(instr->Bits(27, 25) == 0x7);
+  VisitUnimplemented(instr);
+}
+
+
+#define DEFINE_VISITOR_CALLERS(A)                                              \
+  void Decoder::Visit##A(Instruction *instr) {                                 \
+    ASSERT(instr->Mask(A##FMask) == A##Fixed);                                 \
+    std::list<DecoderVisitor*>::iterator it;                                   \
+    for (it = visitors_.begin(); it != visitors_.end(); it++) {                \
+      (*it)->Visit##A(instr);                                                  \
+    }                                                                          \
+  }
+VISITOR_LIST(DEFINE_VISITOR_CALLERS)
+#undef DEFINE_VISITOR_CALLERS
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/decoder-a64.h b/disas/libvixl/src/a64/decoder-a64.h
new file mode 100644
index 0000000..bbbbd81
--- /dev/null
+++ b/disas/libvixl/src/a64/decoder-a64.h
@@ -0,0 +1,198 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_DECODER_A64_H_
+#define VIXL_A64_DECODER_A64_H_
+
+#include <list>
+
+#include "globals.h"
+#include "a64/instructions-a64.h"
+
+
+// List macro containing all visitors needed by the decoder class.
+
+#define VISITOR_LIST(V)             \
+  V(PCRelAddressing)                \
+  V(AddSubImmediate)                \
+  V(LogicalImmediate)               \
+  V(MoveWideImmediate)              \
+  V(Bitfield)                       \
+  V(Extract)                        \
+  V(UnconditionalBranch)            \
+  V(UnconditionalBranchToRegister)  \
+  V(CompareBranch)                  \
+  V(TestBranch)                     \
+  V(ConditionalBranch)              \
+  V(System)                         \
+  V(Exception)                      \
+  V(LoadStorePairPostIndex)         \
+  V(LoadStorePairOffset)            \
+  V(LoadStorePairPreIndex)          \
+  V(LoadStorePairNonTemporal)       \
+  V(LoadLiteral)                    \
+  V(LoadStoreUnscaledOffset)        \
+  V(LoadStorePostIndex)             \
+  V(LoadStorePreIndex)              \
+  V(LoadStoreRegisterOffset)        \
+  V(LoadStoreUnsignedOffset)        \
+  V(LogicalShifted)                 \
+  V(AddSubShifted)                  \
+  V(AddSubExtended)                 \
+  V(AddSubWithCarry)                \
+  V(ConditionalCompareRegister)     \
+  V(ConditionalCompareImmediate)    \
+  V(ConditionalSelect)              \
+  V(DataProcessing1Source)          \
+  V(DataProcessing2Source)          \
+  V(DataProcessing3Source)          \
+  V(FPCompare)                      \
+  V(FPConditionalCompare)           \
+  V(FPConditionalSelect)            \
+  V(FPImmediate)                    \
+  V(FPDataProcessing1Source)        \
+  V(FPDataProcessing2Source)        \
+  V(FPDataProcessing3Source)        \
+  V(FPIntegerConvert)               \
+  V(FPFixedPointConvert)            \
+  V(Unallocated)                    \
+  V(Unimplemented)
+
+namespace vixl {
+
+// The Visitor interface. Disassembler and simulator (and other tools)
+// must provide implementations for all of these functions.
+class DecoderVisitor {
+ public:
+  #define DECLARE(A) virtual void Visit##A(Instruction* instr) = 0;
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+  virtual ~DecoderVisitor() {}
+
+ private:
+  // Visitors are registered in a list.
+  std::list<DecoderVisitor*> visitors_;
+
+  friend class Decoder;
+};
+
+
+class Decoder: public DecoderVisitor {
+ public:
+  Decoder() {}
+
+  // Top-level instruction decoder function. Decodes an instruction and calls
+  // the visitor functions registered with the Decoder class.
+  void Decode(Instruction *instr);
+
+  // Register a new visitor class with the decoder.
+  // Decode() will call the corresponding visitor method from all registered
+  // visitor classes when decoding reaches the leaf node of the instruction
+  // decode tree.
+  // Visitors are called in the order.
+  // A visitor can only be registered once.
+  // Registering an already registered visitor will update its position.
+  //
+  //   d.AppendVisitor(V1);
+  //   d.AppendVisitor(V2);
+  //   d.PrependVisitor(V2);            // Move V2 at the start of the list.
+  //   d.InsertVisitorBefore(V3, V2);
+  //   d.AppendVisitor(V4);
+  //   d.AppendVisitor(V4);             // No effect.
+  //
+  //   d.Decode(i);
+  //
+  // will call in order visitor methods in V3, V2, V1, V4.
+  void AppendVisitor(DecoderVisitor* visitor);
+  void PrependVisitor(DecoderVisitor* visitor);
+  void InsertVisitorBefore(DecoderVisitor* new_visitor,
+                           DecoderVisitor* registered_visitor);
+  void InsertVisitorAfter(DecoderVisitor* new_visitor,
+                          DecoderVisitor* registered_visitor);
+
+  // Remove a previously registered visitor class from the list of visitors
+  // stored by the decoder.
+  void RemoveVisitor(DecoderVisitor* visitor);
+
+  #define DECLARE(A) void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+ private:
+  // Decode the PC relative addressing instruction, and call the corresponding
+  // visitors.
+  // On entry, instruction bits 27:24 = 0x0.
+  void DecodePCRelAddressing(Instruction* instr);
+
+  // Decode the add/subtract immediate instruction, and call the correspoding
+  // visitors.
+  // On entry, instruction bits 27:24 = 0x1.
+  void DecodeAddSubImmediate(Instruction* instr);
+
+  // Decode the branch, system command, and exception generation parts of
+  // the instruction tree, and call the corresponding visitors.
+  // On entry, instruction bits 27:24 = {0x4, 0x5, 0x6, 0x7}.
+  void DecodeBranchSystemException(Instruction* instr);
+
+  // Decode the load and store parts of the instruction tree, and call
+  // the corresponding visitors.
+  // On entry, instruction bits 27:24 = {0x8, 0x9, 0xC, 0xD}.
+  void DecodeLoadStore(Instruction* instr);
+
+  // Decode the logical immediate and move wide immediate parts of the
+  // instruction tree, and call the corresponding visitors.
+  // On entry, instruction bits 27:24 = 0x2.
+  void DecodeLogical(Instruction* instr);
+
+  // Decode the bitfield and extraction parts of the instruction tree,
+  // and call the corresponding visitors.
+  // On entry, instruction bits 27:24 = 0x3.
+  void DecodeBitfieldExtract(Instruction* instr);
+
+  // Decode the data processing parts of the instruction tree, and call the
+  // corresponding visitors.
+  // On entry, instruction bits 27:24 = {0x1, 0xA, 0xB}.
+  void DecodeDataProcessing(Instruction* instr);
+
+  // Decode the floating point parts of the instruction tree, and call the
+  // corresponding visitors.
+  // On entry, instruction bits 27:24 = {0xE, 0xF}.
+  void DecodeFP(Instruction* instr);
+
+  // Decode the Advanced SIMD (NEON) load/store part of the instruction tree,
+  // and call the corresponding visitors.
+  // On entry, instruction bits 29:25 = 0x6.
+  void DecodeAdvSIMDLoadStore(Instruction* instr);
+
+  // Decode the Advanced SIMD (NEON) data processing part of the instruction
+  // tree, and call the corresponding visitors.
+  // On entry, instruction bits 27:25 = 0x7.
+  void DecodeAdvSIMDDataProcessing(Instruction* instr);
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_DECODER_A64_H_
diff --git a/disas/libvixl/src/a64/disasm-a64.cc b/disas/libvixl/src/a64/disasm-a64.cc
new file mode 100644
index 0000000..4a49748
--- /dev/null
+++ b/disas/libvixl/src/a64/disasm-a64.cc
@@ -0,0 +1,1678 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/disasm-a64.h"
+
+namespace vixl {
+
+Disassembler::Disassembler() {
+  buffer_size_ = 256;
+  buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
+  buffer_pos_ = 0;
+  own_buffer_ = true;
+}
+
+
+Disassembler::Disassembler(char* text_buffer, int buffer_size) {
+  buffer_size_ = buffer_size;
+  buffer_ = text_buffer;
+  buffer_pos_ = 0;
+  own_buffer_ = false;
+}
+
+
+Disassembler::~Disassembler() {
+  if (own_buffer_) {
+    free(buffer_);
+  }
+}
+
+
+char* Disassembler::GetOutput() {
+  return buffer_;
+}
+
+
+void Disassembler::VisitAddSubImmediate(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
+                  (instr->ImmAddSub() == 0) ? true : false;
+  const char *mnemonic = "";
+  const char *form = "'Rds, 'Rns, 'IAddSub";
+  const char *form_cmp = "'Rns, 'IAddSub";
+  const char *form_mov = "'Rds, 'Rns";
+
+  switch (instr->Mask(AddSubImmediateMask)) {
+    case ADD_w_imm:
+    case ADD_x_imm: {
+      mnemonic = "add";
+      if (stack_op) {
+        mnemonic = "mov";
+        form = form_mov;
+      }
+      break;
+    }
+    case ADDS_w_imm:
+    case ADDS_x_imm: {
+      mnemonic = "adds";
+      if (rd_is_zr) {
+        mnemonic = "cmn";
+        form = form_cmp;
+      }
+      break;
+    }
+    case SUB_w_imm:
+    case SUB_x_imm: mnemonic = "sub"; break;
+    case SUBS_w_imm:
+    case SUBS_x_imm: {
+      mnemonic = "subs";
+      if (rd_is_zr) {
+        mnemonic = "cmp";
+        form = form_cmp;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitAddSubShifted(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm'HDP";
+  const char *form_cmp = "'Rn, 'Rm'HDP";
+  const char *form_neg = "'Rd, 'Rm'HDP";
+
+  switch (instr->Mask(AddSubShiftedMask)) {
+    case ADD_w_shift:
+    case ADD_x_shift: mnemonic = "add"; break;
+    case ADDS_w_shift:
+    case ADDS_x_shift: {
+      mnemonic = "adds";
+      if (rd_is_zr) {
+        mnemonic = "cmn";
+        form = form_cmp;
+      }
+      break;
+    }
+    case SUB_w_shift:
+    case SUB_x_shift: {
+      mnemonic = "sub";
+      if (rn_is_zr) {
+        mnemonic = "neg";
+        form = form_neg;
+      }
+      break;
+    }
+    case SUBS_w_shift:
+    case SUBS_x_shift: {
+      mnemonic = "subs";
+      if (rd_is_zr) {
+        mnemonic = "cmp";
+        form = form_cmp;
+      } else if (rn_is_zr) {
+        mnemonic = "negs";
+        form = form_neg;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitAddSubExtended(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  const char *mnemonic = "";
+  Extend mode = static_cast<Extend>(instr->ExtendMode());
+  const char *form = ((mode == UXTX) || (mode == SXTX)) ?
+                     "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
+  const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
+                         "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
+
+  switch (instr->Mask(AddSubExtendedMask)) {
+    case ADD_w_ext:
+    case ADD_x_ext: mnemonic = "add"; break;
+    case ADDS_w_ext:
+    case ADDS_x_ext: {
+      mnemonic = "adds";
+      if (rd_is_zr) {
+        mnemonic = "cmn";
+        form = form_cmp;
+      }
+      break;
+    }
+    case SUB_w_ext:
+    case SUB_x_ext: mnemonic = "sub"; break;
+    case SUBS_w_ext:
+    case SUBS_x_ext: {
+      mnemonic = "subs";
+      if (rd_is_zr) {
+        mnemonic = "cmp";
+        form = form_cmp;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm";
+  const char *form_neg = "'Rd, 'Rm";
+
+  switch (instr->Mask(AddSubWithCarryMask)) {
+    case ADC_w:
+    case ADC_x: mnemonic = "adc"; break;
+    case ADCS_w:
+    case ADCS_x: mnemonic = "adcs"; break;
+    case SBC_w:
+    case SBC_x: {
+      mnemonic = "sbc";
+      if (rn_is_zr) {
+        mnemonic = "ngc";
+        form = form_neg;
+      }
+      break;
+    }
+    case SBCS_w:
+    case SBCS_x: {
+      mnemonic = "sbcs";
+      if (rn_is_zr) {
+        mnemonic = "ngcs";
+        form = form_neg;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLogicalImmediate(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rds, 'Rn, 'ITri";
+
+  if (instr->ImmLogical() == 0) {
+    // The immediate encoded in the instruction is not in the expected format.
+    Format(instr, "unallocated", "(LogicalImmediate)");
+    return;
+  }
+
+  switch (instr->Mask(LogicalImmediateMask)) {
+    case AND_w_imm:
+    case AND_x_imm: mnemonic = "and"; break;
+    case ORR_w_imm:
+    case ORR_x_imm: {
+      mnemonic = "orr";
+      unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
+                                                        : kWRegSize;
+      if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
+        mnemonic = "mov";
+        form = "'Rds, 'ITri";
+      }
+      break;
+    }
+    case EOR_w_imm:
+    case EOR_x_imm: mnemonic = "eor"; break;
+    case ANDS_w_imm:
+    case ANDS_x_imm: {
+      mnemonic = "ands";
+      if (rd_is_zr) {
+        mnemonic = "tst";
+        form = "'Rn, 'ITri";
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
+  ASSERT((reg_size == kXRegSize) ||
+         ((reg_size == kWRegSize) && (value <= 0xffffffff)));
+
+  // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
+  if (((value & 0xffffffffffff0000UL) == 0UL) ||
+      ((value & 0xffffffff0000ffffUL) == 0UL) ||
+      ((value & 0xffff0000ffffffffUL) == 0UL) ||
+      ((value & 0x0000ffffffffffffUL) == 0UL)) {
+    return true;
+  }
+
+  // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
+  if ((reg_size == kXRegSize) &&
+      (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) ||
+       ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) ||
+       ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) ||
+       ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) {
+    return true;
+  }
+  if ((reg_size == kWRegSize) &&
+      (((value & 0xffff0000) == 0xffff0000) ||
+       ((value & 0x0000ffff) == 0x0000ffff))) {
+    return true;
+  }
+  return false;
+}
+
+
+void Disassembler::VisitLogicalShifted(Instruction* instr) {
+  bool rd_is_zr = RdIsZROrSP(instr);
+  bool rn_is_zr = RnIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm'HLo";
+
+  switch (instr->Mask(LogicalShiftedMask)) {
+    case AND_w:
+    case AND_x: mnemonic = "and"; break;
+    case BIC_w:
+    case BIC_x: mnemonic = "bic"; break;
+    case EOR_w:
+    case EOR_x: mnemonic = "eor"; break;
+    case EON_w:
+    case EON_x: mnemonic = "eon"; break;
+    case BICS_w:
+    case BICS_x: mnemonic = "bics"; break;
+    case ANDS_w:
+    case ANDS_x: {
+      mnemonic = "ands";
+      if (rd_is_zr) {
+        mnemonic = "tst";
+        form = "'Rn, 'Rm'HLo";
+      }
+      break;
+    }
+    case ORR_w:
+    case ORR_x: {
+      mnemonic = "orr";
+      if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
+        mnemonic = "mov";
+        form = "'Rd, 'Rm";
+      }
+      break;
+    }
+    case ORN_w:
+    case ORN_x: {
+      mnemonic = "orn";
+      if (rn_is_zr) {
+        mnemonic = "mvn";
+        form = "'Rd, 'Rm'HLo";
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
+
+  switch (instr->Mask(ConditionalCompareRegisterMask)) {
+    case CCMN_w:
+    case CCMN_x: mnemonic = "ccmn"; break;
+    case CCMP_w:
+    case CCMP_x: mnemonic = "ccmp"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
+
+  switch (instr->Mask(ConditionalCompareImmediateMask)) {
+    case CCMN_w_imm:
+    case CCMN_x_imm: mnemonic = "ccmn"; break;
+    case CCMP_w_imm:
+    case CCMP_x_imm: mnemonic = "ccmp"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitConditionalSelect(Instruction* instr) {
+  bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
+  bool rn_is_rm = (instr->Rn() == instr->Rm());
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
+  const char *form_test = "'Rd, 'CInv";
+  const char *form_update = "'Rd, 'Rn, 'CInv";
+
+  Condition cond = static_cast<Condition>(instr->Condition());
+  bool invertible_cond = (cond != al) && (cond != nv);
+
+  switch (instr->Mask(ConditionalSelectMask)) {
+    case CSEL_w:
+    case CSEL_x: mnemonic = "csel"; break;
+    case CSINC_w:
+    case CSINC_x: {
+      mnemonic = "csinc";
+      if (rnm_is_zr && invertible_cond) {
+        mnemonic = "cset";
+        form = form_test;
+      } else if (rn_is_rm && invertible_cond) {
+        mnemonic = "cinc";
+        form = form_update;
+      }
+      break;
+    }
+    case CSINV_w:
+    case CSINV_x: {
+      mnemonic = "csinv";
+      if (rnm_is_zr && invertible_cond) {
+        mnemonic = "csetm";
+        form = form_test;
+      } else if (rn_is_rm && invertible_cond) {
+        mnemonic = "cinv";
+        form = form_update;
+      }
+      break;
+    }
+    case CSNEG_w:
+    case CSNEG_x: {
+      mnemonic = "csneg";
+      if (rn_is_rm && invertible_cond) {
+        mnemonic = "cneg";
+        form = form_update;
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitBitfield(Instruction* instr) {
+  unsigned s = instr->ImmS();
+  unsigned r = instr->ImmR();
+  unsigned rd_size_minus_1 =
+    ((instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
+  const char *mnemonic = "";
+  const char *form = "";
+  const char *form_shift_right = "'Rd, 'Rn, 'IBr";
+  const char *form_extend = "'Rd, 'Wn";
+  const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
+  const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
+  const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
+
+  switch (instr->Mask(BitfieldMask)) {
+    case SBFM_w:
+    case SBFM_x: {
+      mnemonic = "sbfx";
+      form = form_bfx;
+      if (r == 0) {
+        form = form_extend;
+        if (s == 7) {
+          mnemonic = "sxtb";
+        } else if (s == 15) {
+          mnemonic = "sxth";
+        } else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
+          mnemonic = "sxtw";
+        } else {
+          form = form_bfx;
+        }
+      } else if (s == rd_size_minus_1) {
+        mnemonic = "asr";
+        form = form_shift_right;
+      } else if (s < r) {
+        mnemonic = "sbfiz";
+        form = form_bfiz;
+      }
+      break;
+    }
+    case UBFM_w:
+    case UBFM_x: {
+      mnemonic = "ubfx";
+      form = form_bfx;
+      if (r == 0) {
+        form = form_extend;
+        if (s == 7) {
+          mnemonic = "uxtb";
+        } else if (s == 15) {
+          mnemonic = "uxth";
+        } else {
+          form = form_bfx;
+        }
+      }
+      if (s == rd_size_minus_1) {
+        mnemonic = "lsr";
+        form = form_shift_right;
+      } else if (r == s + 1) {
+        mnemonic = "lsl";
+        form = form_lsl;
+      } else if (s < r) {
+        mnemonic = "ubfiz";
+        form = form_bfiz;
+      }
+      break;
+    }
+    case BFM_w:
+    case BFM_x: {
+      mnemonic = "bfxil";
+      form = form_bfx;
+      if (s < r) {
+        mnemonic = "bfi";
+        form = form_bfiz;
+      }
+    }
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitExtract(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
+
+  switch (instr->Mask(ExtractMask)) {
+    case EXTR_w:
+    case EXTR_x: {
+      if (instr->Rn() == instr->Rm()) {
+        mnemonic = "ror";
+        form = "'Rd, 'Rn, 'IExtract";
+      } else {
+        mnemonic = "extr";
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitPCRelAddressing(Instruction* instr) {
+  switch (instr->Mask(PCRelAddressingMask)) {
+    case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
+    // ADRP is not implemented.
+    default: Format(instr, "unimplemented", "(PCRelAddressing)");
+  }
+}
+
+
+void Disassembler::VisitConditionalBranch(Instruction* instr) {
+  switch (instr->Mask(ConditionalBranchMask)) {
+    case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Disassembler::VisitUnconditionalBranchToRegister(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Xn";
+
+  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
+    case BR: mnemonic = "br"; break;
+    case BLR: mnemonic = "blr"; break;
+    case RET: {
+      mnemonic = "ret";
+      if (instr->Rn() == kLinkRegCode) {
+        form = NULL;
+      }
+      break;
+    }
+    default: form = "(UnconditionalBranchToRegister)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'BImmUncn";
+
+  switch (instr->Mask(UnconditionalBranchMask)) {
+    case B: mnemonic = "b"; break;
+    case BL: mnemonic = "bl"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Rn";
+
+  switch (instr->Mask(DataProcessing1SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_w:           \
+    case A##_x: mnemonic = B; break;
+    FORMAT(RBIT, "rbit");
+    FORMAT(REV16, "rev16");
+    FORMAT(REV, "rev");
+    FORMAT(CLZ, "clz");
+    FORMAT(CLS, "cls");
+    #undef FORMAT
+    case REV32_x: mnemonic = "rev32"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitDataProcessing2Source(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Rd, 'Rn, 'Rm";
+
+  switch (instr->Mask(DataProcessing2SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_w:           \
+    case A##_x: mnemonic = B; break;
+    FORMAT(UDIV, "udiv");
+    FORMAT(SDIV, "sdiv");
+    FORMAT(LSLV, "lsl");
+    FORMAT(LSRV, "lsr");
+    FORMAT(ASRV, "asr");
+    FORMAT(RORV, "ror");
+    #undef FORMAT
+    default: form = "(DataProcessing2Source)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
+  bool ra_is_zr = RaIsZROrSP(instr);
+  const char *mnemonic = "";
+  const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
+  const char *form_rrr = "'Rd, 'Rn, 'Rm";
+  const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
+  const char *form_xww = "'Xd, 'Wn, 'Wm";
+  const char *form_xxx = "'Xd, 'Xn, 'Xm";
+
+  switch (instr->Mask(DataProcessing3SourceMask)) {
+    case MADD_w:
+    case MADD_x: {
+      mnemonic = "madd";
+      form = form_rrrr;
+      if (ra_is_zr) {
+        mnemonic = "mul";
+        form = form_rrr;
+      }
+      break;
+    }
+    case MSUB_w:
+    case MSUB_x: {
+      mnemonic = "msub";
+      form = form_rrrr;
+      if (ra_is_zr) {
+        mnemonic = "mneg";
+        form = form_rrr;
+      }
+      break;
+    }
+    case SMADDL_x: {
+      mnemonic = "smaddl";
+      if (ra_is_zr) {
+        mnemonic = "smull";
+        form = form_xww;
+      }
+      break;
+    }
+    case SMSUBL_x: {
+      mnemonic = "smsubl";
+      if (ra_is_zr) {
+        mnemonic = "smnegl";
+        form = form_xww;
+      }
+      break;
+    }
+    case UMADDL_x: {
+      mnemonic = "umaddl";
+      if (ra_is_zr) {
+        mnemonic = "umull";
+        form = form_xww;
+      }
+      break;
+    }
+    case UMSUBL_x: {
+      mnemonic = "umsubl";
+      if (ra_is_zr) {
+        mnemonic = "umnegl";
+        form = form_xww;
+      }
+      break;
+    }
+    case SMULH_x: {
+      mnemonic = "smulh";
+      form = form_xxx;
+      break;
+    }
+    case UMULH_x: {
+      mnemonic = "umulh";
+      form = form_xxx;
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitCompareBranch(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rt, 'BImmCmpa";
+
+  switch (instr->Mask(CompareBranchMask)) {
+    case CBZ_w:
+    case CBZ_x: mnemonic = "cbz"; break;
+    case CBNZ_w:
+    case CBNZ_x: mnemonic = "cbnz"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitTestBranch(Instruction* instr) {
+  const char *mnemonic = "";
+  // If the top bit of the immediate is clear, the tested register is
+  // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
+  // encoded in bit 31 of the instruction, we can reuse the Rt form, which
+  // uses bit 31 (normally "sf") to choose the register size.
+  const char *form = "'Rt, 'IS, 'BImmTest";
+
+  switch (instr->Mask(TestBranchMask)) {
+    case TBZ: mnemonic = "tbz"; break;
+    case TBNZ: mnemonic = "tbnz"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'IMoveImm";
+
+  // Print the shift separately for movk, to make it clear which half word will
+  // be overwritten. Movn and movz print the computed immediate, which includes
+  // shift calculation.
+  switch (instr->Mask(MoveWideImmediateMask)) {
+    case MOVN_w:
+    case MOVN_x: mnemonic = "movn"; break;
+    case MOVZ_w:
+    case MOVZ_x: mnemonic = "movz"; break;
+    case MOVK_w:
+    case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+#define LOAD_STORE_LIST(V)    \
+  V(STRB_w, "strb", "'Wt")    \
+  V(STRH_w, "strh", "'Wt")    \
+  V(STR_w, "str", "'Wt")      \
+  V(STR_x, "str", "'Xt")      \
+  V(LDRB_w, "ldrb", "'Wt")    \
+  V(LDRH_w, "ldrh", "'Wt")    \
+  V(LDR_w, "ldr", "'Wt")      \
+  V(LDR_x, "ldr", "'Xt")      \
+  V(LDRSB_x, "ldrsb", "'Xt")  \
+  V(LDRSH_x, "ldrsh", "'Xt")  \
+  V(LDRSW_x, "ldrsw", "'Xt")  \
+  V(LDRSB_w, "ldrsb", "'Wt")  \
+  V(LDRSH_w, "ldrsh", "'Wt")  \
+  V(STR_s, "str", "'St")      \
+  V(STR_d, "str", "'Dt")      \
+  V(LDR_s, "ldr", "'St")      \
+  V(LDR_d, "ldr", "'Dt")
+
+void Disassembler::VisitLoadStorePreIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePreIndex)";
+
+  switch (instr->Mask(LoadStorePreIndexMask)) {
+    #define LS_PREINDEX(A, B, C) \
+    case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
+    LOAD_STORE_LIST(LS_PREINDEX)
+    #undef LS_PREINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePostIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePostIndex)";
+
+  switch (instr->Mask(LoadStorePostIndexMask)) {
+    #define LS_POSTINDEX(A, B, C) \
+    case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
+    LOAD_STORE_LIST(LS_POSTINDEX)
+    #undef LS_POSTINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStoreUnsignedOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStoreUnsignedOffset)";
+
+  switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
+    #define LS_UNSIGNEDOFFSET(A, B, C) \
+    case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
+    LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
+    #undef LS_UNSIGNEDOFFSET
+    case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStoreRegisterOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStoreRegisterOffset)";
+
+  switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
+    #define LS_REGISTEROFFSET(A, B, C) \
+    case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
+    LOAD_STORE_LIST(LS_REGISTEROFFSET)
+    #undef LS_REGISTEROFFSET
+    case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStoreUnscaledOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Wt, ['Xns'ILS]";
+  const char *form_x = "'Xt, ['Xns'ILS]";
+  const char *form_s = "'St, ['Xns'ILS]";
+  const char *form_d = "'Dt, ['Xns'ILS]";
+
+  switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
+    case STURB_w:  mnemonic = "sturb"; break;
+    case STURH_w:  mnemonic = "sturh"; break;
+    case STUR_w:   mnemonic = "stur"; break;
+    case STUR_x:   mnemonic = "stur"; form = form_x; break;
+    case STUR_s:   mnemonic = "stur"; form = form_s; break;
+    case STUR_d:   mnemonic = "stur"; form = form_d; break;
+    case LDURB_w:  mnemonic = "ldurb"; break;
+    case LDURH_w:  mnemonic = "ldurh"; break;
+    case LDUR_w:   mnemonic = "ldur"; break;
+    case LDUR_x:   mnemonic = "ldur"; form = form_x; break;
+    case LDUR_s:   mnemonic = "ldur"; form = form_s; break;
+    case LDUR_d:   mnemonic = "ldur"; form = form_d; break;
+    case LDURSB_x: form = form_x;  // Fall through.
+    case LDURSB_w: mnemonic = "ldursb"; break;
+    case LDURSH_x: form = form_x;  // Fall through.
+    case LDURSH_w: mnemonic = "ldursh"; break;
+    case LDURSW_x: mnemonic = "ldursw"; form = form_x; break;
+    default: form = "(LoadStoreUnscaledOffset)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadLiteral(Instruction* instr) {
+  const char *mnemonic = "ldr";
+  const char *form = "(LoadLiteral)";
+
+  switch (instr->Mask(LoadLiteralMask)) {
+    case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
+    case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
+    case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
+    case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
+    default: mnemonic = "unimplemented";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+#define LOAD_STORE_PAIR_LIST(V)         \
+  V(STP_w, "stp", "'Wt, 'Wt2", "4")     \
+  V(LDP_w, "ldp", "'Wt, 'Wt2", "4")     \
+  V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \
+  V(STP_x, "stp", "'Xt, 'Xt2", "8")     \
+  V(LDP_x, "ldp", "'Xt, 'Xt2", "8")     \
+  V(STP_s, "stp", "'St, 'St2", "4")     \
+  V(LDP_s, "ldp", "'St, 'St2", "4")     \
+  V(STP_d, "stp", "'Dt, 'Dt2", "8")     \
+  V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
+
+void Disassembler::VisitLoadStorePairPostIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePairPostIndex)";
+
+  switch (instr->Mask(LoadStorePairPostIndexMask)) {
+    #define LSP_POSTINDEX(A, B, C, D) \
+    case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
+    LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
+    #undef LSP_POSTINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePairPreIndex(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePairPreIndex)";
+
+  switch (instr->Mask(LoadStorePairPreIndexMask)) {
+    #define LSP_PREINDEX(A, B, C, D) \
+    case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
+    LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
+    #undef LSP_PREINDEX
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePairOffset(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(LoadStorePairOffset)";
+
+  switch (instr->Mask(LoadStorePairOffsetMask)) {
+    #define LSP_OFFSET(A, B, C, D) \
+    case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
+    LOAD_STORE_PAIR_LIST(LSP_OFFSET)
+    #undef LSP_OFFSET
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitLoadStorePairNonTemporal(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form;
+
+  switch (instr->Mask(LoadStorePairNonTemporalMask)) {
+    case STNP_w: mnemonic = "stnp"; form = "'Wt, 'Wt2, ['Xns'ILP4]"; break;
+    case LDNP_w: mnemonic = "ldnp"; form = "'Wt, 'Wt2, ['Xns'ILP4]"; break;
+    case STNP_x: mnemonic = "stnp"; form = "'Xt, 'Xt2, ['Xns'ILP8]"; break;
+    case LDNP_x: mnemonic = "ldnp"; form = "'Xt, 'Xt2, ['Xns'ILP8]"; break;
+    case STNP_s: mnemonic = "stnp"; form = "'St, 'St2, ['Xns'ILP4]"; break;
+    case LDNP_s: mnemonic = "ldnp"; form = "'St, 'St2, ['Xns'ILP4]"; break;
+    case STNP_d: mnemonic = "stnp"; form = "'Dt, 'Dt2, ['Xns'ILP8]"; break;
+    case LDNP_d: mnemonic = "ldnp"; form = "'Dt, 'Dt2, ['Xns'ILP8]"; break;
+    default: form = "(LoadStorePairNonTemporal)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPCompare(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Fn, 'Fm";
+  const char *form_zero = "'Fn, #0.0";
+
+  switch (instr->Mask(FPCompareMask)) {
+    case FCMP_s_zero:
+    case FCMP_d_zero: form = form_zero;  // Fall through.
+    case FCMP_s:
+    case FCMP_d: mnemonic = "fcmp"; break;
+    default: form = "(FPCompare)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPConditionalCompare(Instruction* instr) {
+  const char *mnemonic = "unmplemented";
+  const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
+
+  switch (instr->Mask(FPConditionalCompareMask)) {
+    case FCCMP_s:
+    case FCCMP_d: mnemonic = "fccmp"; break;
+    case FCCMPE_s:
+    case FCCMPE_d: mnemonic = "fccmpe"; break;
+    default: form = "(FPConditionalCompare)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
+
+  switch (instr->Mask(FPConditionalSelectMask)) {
+    case FCSEL_s:
+    case FCSEL_d: mnemonic = "fcsel"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPDataProcessing1Source(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Fd, 'Fn";
+
+  switch (instr->Mask(FPDataProcessing1SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_s:           \
+    case A##_d: mnemonic = B; break;
+    FORMAT(FMOV, "fmov");
+    FORMAT(FABS, "fabs");
+    FORMAT(FNEG, "fneg");
+    FORMAT(FSQRT, "fsqrt");
+    FORMAT(FRINTN, "frintn");
+    FORMAT(FRINTP, "frintp");
+    FORMAT(FRINTM, "frintm");
+    FORMAT(FRINTZ, "frintz");
+    FORMAT(FRINTA, "frinta");
+    FORMAT(FRINTX, "frintx");
+    FORMAT(FRINTI, "frinti");
+    #undef FORMAT
+    case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
+    case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
+    default: form = "(FPDataProcessing1Source)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Fd, 'Fn, 'Fm";
+
+  switch (instr->Mask(FPDataProcessing2SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_s:           \
+    case A##_d: mnemonic = B; break;
+    FORMAT(FMUL, "fmul");
+    FORMAT(FDIV, "fdiv");
+    FORMAT(FADD, "fadd");
+    FORMAT(FSUB, "fsub");
+    FORMAT(FMAX, "fmax");
+    FORMAT(FMIN, "fmin");
+    FORMAT(FMAXNM, "fmaxnm");
+    FORMAT(FMINNM, "fminnm");
+    FORMAT(FNMUL, "fnmul");
+    #undef FORMAT
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
+
+  switch (instr->Mask(FPDataProcessing3SourceMask)) {
+    #define FORMAT(A, B)  \
+    case A##_s:           \
+    case A##_d: mnemonic = B; break;
+    FORMAT(FMADD, "fmadd");
+    FORMAT(FMSUB, "fmsub");
+    FORMAT(FNMADD, "fnmadd");
+    FORMAT(FNMSUB, "fnmsub");
+    #undef FORMAT
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPImmediate(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "(FPImmediate)";
+
+  switch (instr->Mask(FPImmediateMask)) {
+    case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
+    case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "(FPIntegerConvert)";
+  const char *form_rf = "'Rd, 'Fn";
+  const char *form_fr = "'Fd, 'Rn";
+
+  switch (instr->Mask(FPIntegerConvertMask)) {
+    case FMOV_ws:
+    case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
+    case FMOV_sw:
+    case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
+    case FCVTMS_ws:
+    case FCVTMS_xs:
+    case FCVTMS_wd:
+    case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
+    case FCVTMU_ws:
+    case FCVTMU_xs:
+    case FCVTMU_wd:
+    case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
+    case FCVTNS_ws:
+    case FCVTNS_xs:
+    case FCVTNS_wd:
+    case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
+    case FCVTNU_ws:
+    case FCVTNU_xs:
+    case FCVTNU_wd:
+    case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
+    case FCVTZU_xd:
+    case FCVTZU_ws:
+    case FCVTZU_wd:
+    case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
+    case FCVTZS_xd:
+    case FCVTZS_wd:
+    case FCVTZS_xs:
+    case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
+    case SCVTF_sw:
+    case SCVTF_sx:
+    case SCVTF_dw:
+    case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
+    case UCVTF_sw:
+    case UCVTF_sx:
+    case UCVTF_dw:
+    case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
+  const char *mnemonic = "";
+  const char *form = "'Rd, 'Fn, 'IFPFBits";
+  const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
+
+  switch (instr->Mask(FPFixedPointConvertMask)) {
+    case FCVTZS_ws_fixed:
+    case FCVTZS_xs_fixed:
+    case FCVTZS_wd_fixed:
+    case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
+    case FCVTZU_ws_fixed:
+    case FCVTZU_xs_fixed:
+    case FCVTZU_wd_fixed:
+    case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
+    case SCVTF_sw_fixed:
+    case SCVTF_sx_fixed:
+    case SCVTF_dw_fixed:
+    case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
+    case UCVTF_sw_fixed:
+    case UCVTF_sx_fixed:
+    case UCVTF_dw_fixed:
+    case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
+    default: UNREACHABLE();
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitSystem(Instruction* instr) {
+  // Some system instructions hijack their Op and Cp fields to represent a
+  // range of immediates instead of indicating a different instruction. This
+  // makes the decoding tricky.
+  const char *mnemonic = "unimplemented";
+  const char *form = "(System)";
+
+  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
+    switch (instr->Mask(SystemSysRegMask)) {
+      case MRS: {
+        mnemonic = "mrs";
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: form = "'Xt, nzcv"; break;
+          case FPCR: form = "'Xt, fpcr"; break;
+          default: form = "'Xt, (unknown)"; break;
+        }
+        break;
+      }
+      case MSR: {
+        mnemonic = "msr";
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: form = "nzcv, 'Xt"; break;
+          case FPCR: form = "fpcr, 'Xt"; break;
+          default: form = "(unknown), 'Xt"; break;
+        }
+        break;
+      }
+    }
+  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
+    ASSERT(instr->Mask(SystemHintMask) == HINT);
+    switch (instr->ImmHint()) {
+      case NOP: {
+        mnemonic = "nop";
+        form = NULL;
+        break;
+      }
+    }
+  }
+
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitException(Instruction* instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'IDebug";
+
+  switch (instr->Mask(ExceptionMask)) {
+    case HLT: mnemonic = "hlt"; break;
+    case BRK: mnemonic = "brk"; break;
+    case SVC: mnemonic = "svc"; break;
+    case HVC: mnemonic = "hvc"; break;
+    case SMC: mnemonic = "smc"; break;
+    case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
+    case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
+    case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
+    default: form = "(Exception)";
+  }
+  Format(instr, mnemonic, form);
+}
+
+
+void Disassembler::VisitUnimplemented(Instruction* instr) {
+  Format(instr, "unimplemented", "(Unimplemented)");
+}
+
+
+void Disassembler::VisitUnallocated(Instruction* instr) {
+  Format(instr, "unallocated", "(Unallocated)");
+}
+
+
+void Disassembler::ProcessOutput(Instruction* /*instr*/) {
+  // The base disasm does nothing more than disassembling into a buffer.
+}
+
+
+void Disassembler::Format(Instruction* instr, const char* mnemonic,
+                          const char* format) {
+  ASSERT(mnemonic != NULL);
+  ResetOutput();
+  Substitute(instr, mnemonic);
+  if (format != NULL) {
+    buffer_[buffer_pos_++] = ' ';
+    Substitute(instr, format);
+  }
+  buffer_[buffer_pos_] = 0;
+  ProcessOutput(instr);
+}
+
+
+void Disassembler::Substitute(Instruction* instr, const char* string) {
+  char chr = *string++;
+  while (chr != '\0') {
+    if (chr == '\'') {
+      string += SubstituteField(instr, string);
+    } else {
+      buffer_[buffer_pos_++] = chr;
+    }
+    chr = *string++;
+  }
+}
+
+
+int Disassembler::SubstituteField(Instruction* instr, const char* format) {
+  switch (format[0]) {
+    case 'R':  // Register. X or W, selected by sf bit.
+    case 'F':  // FP Register. S or D, selected by type field.
+    case 'W':
+    case 'X':
+    case 'S':
+    case 'D': return SubstituteRegisterField(instr, format);
+    case 'I': return SubstituteImmediateField(instr, format);
+    case 'L': return SubstituteLiteralField(instr, format);
+    case 'H': return SubstituteShiftField(instr, format);
+    case 'P': return SubstitutePrefetchField(instr, format);
+    case 'C': return SubstituteConditionField(instr, format);
+    case 'E': return SubstituteExtendField(instr, format);
+    case 'A': return SubstitutePCRelAddressField(instr, format);
+    case 'B': return SubstituteBranchTargetField(instr, format);
+    case 'O': return SubstituteLSRegOffsetField(instr, format);
+    default: {
+      UNREACHABLE();
+      return 1;
+    }
+  }
+}
+
+
+int Disassembler::SubstituteRegisterField(Instruction* instr,
+                                          const char* format) {
+  unsigned reg_num = 0;
+  unsigned field_len = 2;
+  switch (format[1]) {
+    case 'd': reg_num = instr->Rd(); break;
+    case 'n': reg_num = instr->Rn(); break;
+    case 'm': reg_num = instr->Rm(); break;
+    case 'a': reg_num = instr->Ra(); break;
+    case 't': {
+      if (format[2] == '2') {
+        reg_num = instr->Rt2();
+        field_len = 3;
+      } else {
+        reg_num = instr->Rt();
+      }
+      break;
+    }
+    default: UNREACHABLE();
+  }
+
+  // Increase field length for registers tagged as stack.
+  if (format[2] == 's') {
+    field_len = 3;
+  }
+
+  char reg_type;
+  if (format[0] == 'R') {
+    // Register type is R: use sf bit to choose X and W.
+    reg_type = instr->SixtyFourBits() ? 'x' : 'w';
+  } else if (format[0] == 'F') {
+    // Floating-point register: use type field to choose S or D.
+    reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd';
+  } else {
+    // Register type is specified. Make it lower case.
+    reg_type = format[0] + 0x20;
+  }
+
+  if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) {
+    // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
+    AppendToOutput("%c%d", reg_type, reg_num);
+  } else if (format[2] == 's') {
+    // Disassemble w31/x31 as stack pointer wsp/sp.
+    AppendToOutput("%s", (reg_type == 'w') ? "wsp" : "sp");
+  } else {
+    // Disassemble w31/x31 as zero register wzr/xzr.
+    AppendToOutput("%czr", reg_type);
+  }
+
+  return field_len;
+}
+
+
+int Disassembler::SubstituteImmediateField(Instruction* instr,
+                                           const char* format) {
+  ASSERT(format[0] == 'I');
+
+  switch (format[1]) {
+    case 'M': {  // IMoveImm or IMoveLSL.
+      if (format[5] == 'I') {
+        uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
+        AppendToOutput("#0x%" PRIx64, imm);
+      } else {
+        ASSERT(format[5] == 'L');
+        AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
+        if (instr->ShiftMoveWide() > 0) {
+          AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
+        }
+      }
+      return 8;
+    }
+    case 'L': {
+      switch (format[2]) {
+        case 'L': {  // ILLiteral - Immediate Load Literal.
+          AppendToOutput("pc%+" PRId64,
+                         instr->ImmLLiteral() << kLiteralEntrySizeLog2);
+          return 9;
+        }
+        case 'S': {  // ILS - Immediate Load/Store.
+          if (instr->ImmLS() != 0) {
+            AppendToOutput(", #%" PRId64, instr->ImmLS());
+          }
+          return 3;
+        }
+        case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
+          if (instr->ImmLSPair() != 0) {
+            // format[3] is the scale value. Convert to a number.
+            int scale = format[3] - 0x30;
+            AppendToOutput(", #%" PRId64, instr->ImmLSPair() * scale);
+          }
+          return 4;
+        }
+        case 'U': {  // ILU - Immediate Load/Store Unsigned.
+          if (instr->ImmLSUnsigned() != 0) {
+            AppendToOutput(", #%" PRIu64,
+                           instr->ImmLSUnsigned() << instr->SizeLS());
+          }
+          return 3;
+        }
+      }
+    }
+    case 'C': {  // ICondB - Immediate Conditional Branch.
+      int64_t offset = instr->ImmCondBranch() << 2;
+      char sign = (offset >= 0) ? '+' : '-';
+      AppendToOutput("#%c0x%" PRIx64, sign, offset);
+      return 6;
+    }
+    case 'A': {  // IAddSub.
+      ASSERT(instr->ShiftAddSub() <= 1);
+      int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
+      AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
+      return 7;
+    }
+    case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
+      if (format[3] == 'F') {  // IFPFbits.
+        AppendToOutput("#%d", 64 - instr->FPScale());
+        return 8;
+      } else {
+        AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
+                       format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
+        return 9;
+      }
+    }
+    case 'T': {  // ITri - Immediate Triangular Encoded.
+      AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
+      return 4;
+    }
+    case 'N': {  // INzcv.
+      int nzcv = (instr->Nzcv() << Flags_offset);
+      AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
+                                  ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
+                                  ((nzcv & CFlag) == 0) ? 'c' : 'C',
+                                  ((nzcv & VFlag) == 0) ? 'v' : 'V');
+      return 5;
+    }
+    case 'P': {  // IP - Conditional compare.
+      AppendToOutput("#%d", instr->ImmCondCmp());
+      return 2;
+    }
+    case 'B': {  // Bitfields.
+      return SubstituteBitfieldImmediateField(instr, format);
+    }
+    case 'E': {  // IExtract.
+      AppendToOutput("#%d", instr->ImmS());
+      return 8;
+    }
+    case 'S': {  // IS - Test and branch bit.
+      AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
+                            instr->ImmTestBranchBit40());
+      return 2;
+    }
+    case 'D': {  // IDebug - HLT and BRK instructions.
+      AppendToOutput("#0x%x", instr->ImmException());
+      return 6;
+    }
+    default: {
+      UNIMPLEMENTED();
+      return 0;
+    }
+  }
+}
+
+
+int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
+                                                   const char* format) {
+  ASSERT((format[0] == 'I') && (format[1] == 'B'));
+  unsigned r = instr->ImmR();
+  unsigned s = instr->ImmS();
+
+  switch (format[2]) {
+    case 'r': {  // IBr.
+      AppendToOutput("#%d", r);
+      return 3;
+    }
+    case 's': {  // IBs+1 or IBs-r+1.
+      if (format[3] == '+') {
+        AppendToOutput("#%d", s + 1);
+        return 5;
+      } else {
+        ASSERT(format[3] == '-');
+        AppendToOutput("#%d", s - r + 1);
+        return 7;
+      }
+    }
+    case 'Z': {  // IBZ-r.
+      ASSERT((format[3] == '-') && (format[4] == 'r'));
+      unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize;
+      AppendToOutput("#%d", reg_size - r);
+      return 5;
+    }
+    default: {
+      UNREACHABLE();
+      return 0;
+    }
+  }
+}
+
+
+int Disassembler::SubstituteLiteralField(Instruction* instr,
+                                         const char* format) {
+  ASSERT(strncmp(format, "LValue", 6) == 0);
+  USE(format);
+
+  switch (instr->Mask(LoadLiteralMask)) {
+    case LDR_w_lit:
+    case LDR_x_lit:
+    case LDR_s_lit:
+    case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
+    default: UNREACHABLE();
+  }
+
+  return 6;
+}
+
+
+int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
+  ASSERT(format[0] == 'H');
+  ASSERT(instr->ShiftDP() <= 0x3);
+
+  switch (format[1]) {
+    case 'D': {  // HDP.
+      ASSERT(instr->ShiftDP() != ROR);
+    }  // Fall through.
+    case 'L': {  // HLo.
+      if (instr->ImmDPShift() != 0) {
+        const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
+        AppendToOutput(", %s #%" PRId64, shift_type[instr->ShiftDP()],
+                       instr->ImmDPShift());
+      }
+      return 3;
+    }
+    default:
+      UNIMPLEMENTED();
+      return 0;
+  }
+}
+
+
+int Disassembler::SubstituteConditionField(Instruction* instr,
+                                           const char* format) {
+  ASSERT(format[0] == 'C');
+  const char* condition_code[] = { "eq", "ne", "hs", "lo",
+                                   "mi", "pl", "vs", "vc",
+                                   "hi", "ls", "ge", "lt",
+                                   "gt", "le", "al", "nv" };
+  int cond;
+  switch (format[1]) {
+    case 'B': cond = instr->ConditionBranch(); break;
+    case 'I': {
+      cond = InvertCondition(static_cast<Condition>(instr->Condition()));
+      break;
+    }
+    default: cond = instr->Condition();
+  }
+  AppendToOutput("%s", condition_code[cond]);
+  return 4;
+}
+
+
+int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
+                                              const char* format) {
+  USE(format);
+  ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
+
+  int offset = instr->ImmPCRel();
+
+  // Only ADR (AddrPCRelByte) is supported.
+  ASSERT(strcmp(format, "AddrPCRelByte") == 0);
+
+  char sign = '+';
+  if (offset < 0) {
+    offset = -offset;
+    sign = '-';
+  }
+  // TODO: Extend this to support printing the target address.
+  AppendToOutput("#%c0x%x", sign, offset);
+  return 13;
+}
+
+
+int Disassembler::SubstituteBranchTargetField(Instruction* instr,
+                                              const char* format) {
+  ASSERT(strncmp(format, "BImm", 4) == 0);
+
+  int64_t offset = 0;
+  switch (format[5]) {
+    // BImmUncn - unconditional branch immediate.
+    case 'n': offset = instr->ImmUncondBranch(); break;
+    // BImmCond - conditional branch immediate.
+    case 'o': offset = instr->ImmCondBranch(); break;
+    // BImmCmpa - compare and branch immediate.
+    case 'm': offset = instr->ImmCmpBranch(); break;
+    // BImmTest - test and branch immediate.
+    case 'e': offset = instr->ImmTestBranch(); break;
+    default: UNIMPLEMENTED();
+  }
+  offset <<= kInstructionSizeLog2;
+  char sign = '+';
+  if (offset < 0) {
+    offset = -offset;
+    sign = '-';
+  }
+  AppendToOutput("#%c0x%" PRIx64, sign, offset);
+  return 8;
+}
+
+
+int Disassembler::SubstituteExtendField(Instruction* instr,
+                                        const char* format) {
+  ASSERT(strncmp(format, "Ext", 3) == 0);
+  ASSERT(instr->ExtendMode() <= 7);
+  USE(format);
+
+  const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
+                                "sxtb", "sxth", "sxtw", "sxtx" };
+
+  // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
+  // registers becomes lsl.
+  if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
+      (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
+       (instr->ExtendMode() == UXTX))) {
+    if (instr->ImmExtendShift() > 0) {
+      AppendToOutput(", lsl #%d", instr->ImmExtendShift());
+    }
+  } else {
+    AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
+    if (instr->ImmExtendShift() > 0) {
+      AppendToOutput(" #%d", instr->ImmExtendShift());
+    }
+  }
+  return 3;
+}
+
+
+int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
+                                             const char* format) {
+  ASSERT(strncmp(format, "Offsetreg", 9) == 0);
+  const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
+                                "undefined", "undefined", "sxtw", "sxtx" };
+  USE(format);
+
+  unsigned shift = instr->ImmShiftLS();
+  Extend ext = static_cast<Extend>(instr->ExtendMode());
+  char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
+
+  unsigned rm = instr->Rm();
+  if (rm == kZeroRegCode) {
+    AppendToOutput("%czr", reg_type);
+  } else {
+    AppendToOutput("%c%d", reg_type, rm);
+  }
+
+  // Extend mode UXTX is an alias for shift mode LSL here.
+  if (!((ext == UXTX) && (shift == 0))) {
+    AppendToOutput(", %s", extend_mode[ext]);
+    if (shift != 0) {
+      AppendToOutput(" #%d", instr->SizeLS());
+    }
+  }
+  return 9;
+}
+
+
+int Disassembler::SubstitutePrefetchField(Instruction* instr,
+                                          const char* format) {
+  ASSERT(format[0] == 'P');
+  USE(format);
+
+  int prefetch_mode = instr->PrefetchMode();
+
+  const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
+  int level = (prefetch_mode >> 1) + 1;
+  const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
+
+  AppendToOutput("p%sl%d%s", ls, level, ks);
+  return 6;
+}
+
+
+void Disassembler::ResetOutput() {
+  buffer_pos_ = 0;
+  buffer_[buffer_pos_] = 0;
+}
+
+
+void Disassembler::AppendToOutput(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
+  va_end(args);
+}
+
+
+void PrintDisassembler::ProcessOutput(Instruction* instr) {
+  fprintf(stream_, "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s\n",
+          reinterpret_cast<uint64_t>(instr),
+          instr->InstructionBits(),
+          GetOutput());
+}
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/disasm-a64.h b/disas/libvixl/src/a64/disasm-a64.h
new file mode 100644
index 0000000..857a5ac
--- /dev/null
+++ b/disas/libvixl/src/a64/disasm-a64.h
@@ -0,0 +1,109 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_DISASM_A64_H
+#define VIXL_A64_DISASM_A64_H
+
+#include "globals.h"
+#include "utils.h"
+#include "instructions-a64.h"
+#include "decoder-a64.h"
+
+namespace vixl {
+
+class Disassembler: public DecoderVisitor {
+ public:
+  Disassembler();
+  Disassembler(char* text_buffer, int buffer_size);
+  virtual ~Disassembler();
+  char* GetOutput();
+
+  // Declare all Visitor functions.
+  #define DECLARE(A)  void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+ protected:
+  virtual void ProcessOutput(Instruction* instr);
+
+ private:
+  void Format(Instruction* instr, const char* mnemonic, const char* format);
+  void Substitute(Instruction* instr, const char* string);
+  int SubstituteField(Instruction* instr, const char* format);
+  int SubstituteRegisterField(Instruction* instr, const char* format);
+  int SubstituteImmediateField(Instruction* instr, const char* format);
+  int SubstituteLiteralField(Instruction* instr, const char* format);
+  int SubstituteBitfieldImmediateField(Instruction* instr, const char* format);
+  int SubstituteShiftField(Instruction* instr, const char* format);
+  int SubstituteExtendField(Instruction* instr, const char* format);
+  int SubstituteConditionField(Instruction* instr, const char* format);
+  int SubstitutePCRelAddressField(Instruction* instr, const char* format);
+  int SubstituteBranchTargetField(Instruction* instr, const char* format);
+  int SubstituteLSRegOffsetField(Instruction* instr, const char* format);
+  int SubstitutePrefetchField(Instruction* instr, const char* format);
+
+  inline bool RdIsZROrSP(Instruction* instr) const {
+    return (instr->Rd() == kZeroRegCode);
+  }
+
+  inline bool RnIsZROrSP(Instruction* instr) const {
+    return (instr->Rn() == kZeroRegCode);
+  }
+
+  inline bool RmIsZROrSP(Instruction* instr) const {
+    return (instr->Rm() == kZeroRegCode);
+  }
+
+  inline bool RaIsZROrSP(Instruction* instr) const {
+    return (instr->Ra() == kZeroRegCode);
+  }
+
+  bool IsMovzMovnImm(unsigned reg_size, uint64_t value);
+
+  void ResetOutput();
+  void AppendToOutput(const char* string, ...);
+
+  char* buffer_;
+  uint32_t buffer_pos_;
+  uint32_t buffer_size_;
+  bool own_buffer_;
+};
+
+
+class PrintDisassembler: public Disassembler {
+ public:
+  explicit PrintDisassembler(FILE* stream) : stream_(stream) { }
+  ~PrintDisassembler() { }
+
+ protected:
+  virtual void ProcessOutput(Instruction* instr);
+
+ private:
+  FILE *stream_;
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_DISASM_A64_H
diff --git a/disas/libvixl/src/a64/instructions-a64.cc b/disas/libvixl/src/a64/instructions-a64.cc
new file mode 100644
index 0000000..e87fa3a
--- /dev/null
+++ b/disas/libvixl/src/a64/instructions-a64.cc
@@ -0,0 +1,238 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/instructions-a64.h"
+#include "a64/assembler-a64.h"
+
+namespace vixl {
+
+
+static uint64_t RotateRight(uint64_t value,
+                            unsigned int rotate,
+                            unsigned int width) {
+  ASSERT(width <= 64);
+  rotate &= 63;
+  return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) |
+         (value >> rotate);
+}
+
+
+static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
+                                    uint64_t value,
+                                    unsigned width) {
+  ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
+         (width == 32));
+  ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
+  uint64_t result = value & ((1UL << width) - 1UL);
+  for (unsigned i = width; i < reg_size; i *= 2) {
+    result |= (result << i);
+  }
+  return result;
+}
+
+
+// Logical immediates can't encode zero, so a return value of zero is used to
+// indicate a failure case. Specifically, where the constraints on imm_s are
+// not met.
+uint64_t Instruction::ImmLogical() {
+  unsigned reg_size = SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t n = BitN();
+  int64_t imm_s = ImmSetBits();
+  int64_t imm_r = ImmRotate();
+
+  // An integer is constructed from the n, imm_s and imm_r bits according to
+  // the following table:
+  //
+  //  N   imms    immr    size        S             R
+  //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
+  //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
+  //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
+  //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
+  //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
+  //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
+  // (s bits must not be all set)
+  //
+  // A pattern is constructed of size bits, where the least significant S+1
+  // bits are set. The pattern is rotated right by R, and repeated across a
+  // 32 or 64-bit value, depending on destination register width.
+  //
+
+  if (n == 1) {
+    if (imm_s == 0x3F) {
+      return 0;
+    }
+    uint64_t bits = (1UL << (imm_s + 1)) - 1;
+    return RotateRight(bits, imm_r, 64);
+  } else {
+    if ((imm_s >> 1) == 0x1F) {
+      return 0;
+    }
+    for (int width = 0x20; width >= 0x2; width >>= 1) {
+      if ((imm_s & width) == 0) {
+        int mask = width - 1;
+        if ((imm_s & mask) == mask) {
+          return 0;
+        }
+        uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1;
+        return RepeatBitsAcrossReg(reg_size,
+                                   RotateRight(bits, imm_r & mask, width),
+                                   width);
+      }
+    }
+  }
+  UNREACHABLE();
+  return 0;
+}
+
+
+float Instruction::ImmFP32() {
+  //  ImmFP: abcdefgh (8 bits)
+  // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
+  // where B is b ^ 1
+  uint32_t bits = ImmFP();
+  uint32_t bit7 = (bits >> 7) & 0x1;
+  uint32_t bit6 = (bits >> 6) & 0x1;
+  uint32_t bit5_to_0 = bits & 0x3f;
+  uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
+
+  return rawbits_to_float(result);
+}
+
+
+double Instruction::ImmFP64() {
+  //  ImmFP: abcdefgh (8 bits)
+  // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
+  //         0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
+  // where B is b ^ 1
+  uint32_t bits = ImmFP();
+  uint64_t bit7 = (bits >> 7) & 0x1;
+  uint64_t bit6 = (bits >> 6) & 0x1;
+  uint64_t bit5_to_0 = bits & 0x3f;
+  uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
+
+  return rawbits_to_double(result);
+}
+
+
+LSDataSize CalcLSPairDataSize(LoadStorePairOp op) {
+  switch (op) {
+    case STP_x:
+    case LDP_x:
+    case STP_d:
+    case LDP_d: return LSDoubleWord;
+    default: return LSWord;
+  }
+}
+
+
+Instruction* Instruction::ImmPCOffsetTarget() {
+  ptrdiff_t offset;
+  if (IsPCRelAddressing()) {
+    // PC-relative addressing. Only ADR is supported.
+    offset = ImmPCRel();
+  } else {
+    // All PC-relative branches.
+    ASSERT(BranchType() != UnknownBranchType);
+    // Relative branch offsets are instruction-size-aligned.
+    offset = ImmBranch() << kInstructionSizeLog2;
+  }
+  return this + offset;
+}
+
+
+inline int Instruction::ImmBranch() const {
+  switch (BranchType()) {
+    case CondBranchType: return ImmCondBranch();
+    case UncondBranchType: return ImmUncondBranch();
+    case CompareBranchType: return ImmCmpBranch();
+    case TestBranchType: return ImmTestBranch();
+    default: UNREACHABLE();
+  }
+  return 0;
+}
+
+
+void Instruction::SetImmPCOffsetTarget(Instruction* target) {
+  if (IsPCRelAddressing()) {
+    SetPCRelImmTarget(target);
+  } else {
+    SetBranchImmTarget(target);
+  }
+}
+
+
+void Instruction::SetPCRelImmTarget(Instruction* target) {
+  // ADRP is not supported, so 'this' must point to an ADR instruction.
+  ASSERT(Mask(PCRelAddressingMask) == ADR);
+
+  Instr imm = Assembler::ImmPCRelAddress(target - this);
+
+  SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
+}
+
+
+void Instruction::SetBranchImmTarget(Instruction* target) {
+  ASSERT(((target - this) & 3) == 0);
+  Instr branch_imm = 0;
+  uint32_t imm_mask = 0;
+  int offset = (target - this) >> kInstructionSizeLog2;
+  switch (BranchType()) {
+    case CondBranchType: {
+      branch_imm = Assembler::ImmCondBranch(offset);
+      imm_mask = ImmCondBranch_mask;
+      break;
+    }
+    case UncondBranchType: {
+      branch_imm = Assembler::ImmUncondBranch(offset);
+      imm_mask = ImmUncondBranch_mask;
+      break;
+    }
+    case CompareBranchType: {
+      branch_imm = Assembler::ImmCmpBranch(offset);
+      imm_mask = ImmCmpBranch_mask;
+      break;
+    }
+    case TestBranchType: {
+      branch_imm = Assembler::ImmTestBranch(offset);
+      imm_mask = ImmTestBranch_mask;
+      break;
+    }
+    default: UNREACHABLE();
+  }
+  SetInstructionBits(Mask(~imm_mask) | branch_imm);
+}
+
+
+void Instruction::SetImmLLiteral(Instruction* source) {
+  ASSERT(((source - this) & 3) == 0);
+  int offset = (source - this) >> kLiteralEntrySizeLog2;
+  Instr imm = Assembler::ImmLLiteral(offset);
+  Instr mask = ImmLLiteral_mask;
+
+  SetInstructionBits(Mask(~mask) | imm);
+}
+}  // namespace vixl
+
diff --git a/disas/libvixl/src/a64/instructions-a64.h b/disas/libvixl/src/a64/instructions-a64.h
new file mode 100644
index 0000000..0f31fcd
--- /dev/null
+++ b/disas/libvixl/src/a64/instructions-a64.h
@@ -0,0 +1,344 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_INSTRUCTIONS_A64_H_
+#define VIXL_A64_INSTRUCTIONS_A64_H_
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/constants-a64.h"
+
+namespace vixl {
+// ISA constants. --------------------------------------------------------------
+
+typedef uint32_t Instr;
+const unsigned kInstructionSize = 4;
+const unsigned kInstructionSizeLog2 = 2;
+const unsigned kLiteralEntrySize = 4;
+const unsigned kLiteralEntrySizeLog2 = 2;
+const unsigned kMaxLoadLiteralRange = 1 * MBytes;
+
+const unsigned kWRegSize = 32;
+const unsigned kWRegSizeLog2 = 5;
+const unsigned kWRegSizeInBytes = kWRegSize / 8;
+const unsigned kXRegSize = 64;
+const unsigned kXRegSizeLog2 = 6;
+const unsigned kXRegSizeInBytes = kXRegSize / 8;
+const unsigned kSRegSize = 32;
+const unsigned kSRegSizeLog2 = 5;
+const unsigned kSRegSizeInBytes = kSRegSize / 8;
+const unsigned kDRegSize = 64;
+const unsigned kDRegSizeLog2 = 6;
+const unsigned kDRegSizeInBytes = kDRegSize / 8;
+const int64_t kWRegMask = 0x00000000ffffffffL;
+const int64_t kXRegMask = 0xffffffffffffffffL;
+const int64_t kSRegMask = 0x00000000ffffffffL;
+const int64_t kDRegMask = 0xffffffffffffffffL;
+const int64_t kXSignMask = 0x1L << 63;
+const int64_t kWSignMask = 0x1L << 31;
+const int64_t kByteMask = 0xffL;
+const int64_t kHalfWordMask = 0xffffL;
+const int64_t kWordMask = 0xffffffffL;
+const uint64_t kXMaxUInt = 0xffffffffffffffffUL;
+const uint64_t kWMaxUInt = 0xffffffffUL;
+const int64_t kXMaxInt = 0x7fffffffffffffffL;
+const int64_t kXMinInt = 0x8000000000000000L;
+const int32_t kWMaxInt = 0x7fffffff;
+const int32_t kWMinInt = 0x80000000;
+const unsigned kLinkRegCode = 30;
+const unsigned kZeroRegCode = 31;
+const unsigned kSPRegInternalCode = 63;
+const unsigned kRegCodeMask = 0x1f;
+
+// AArch64 floating-point specifics. These match IEEE-754.
+const unsigned kDoubleMantissaBits = 52;
+const unsigned kDoubleExponentBits = 11;
+const unsigned kFloatMantissaBits = 23;
+const unsigned kFloatExponentBits = 8;
+
+const float kFP32PositiveInfinity = rawbits_to_float(0x7f800000);
+const float kFP32NegativeInfinity = rawbits_to_float(0xff800000);
+const double kFP64PositiveInfinity = rawbits_to_double(0x7ff0000000000000UL);
+const double kFP64NegativeInfinity = rawbits_to_double(0xfff0000000000000UL);
+
+// This value is a signalling NaN as both a double and as a float (taking the
+// least-significant word).
+static const double kFP64SignallingNaN = rawbits_to_double(0x7ff000007f800001);
+static const float kFP32SignallingNaN = rawbits_to_float(0x7f800001);
+
+// A similar value, but as a quiet NaN.
+static const double kFP64QuietNaN = rawbits_to_double(0x7ff800007fc00001);
+static const float kFP32QuietNaN = rawbits_to_float(0x7fc00001);
+
+enum LSDataSize {
+  LSByte        = 0,
+  LSHalfword    = 1,
+  LSWord        = 2,
+  LSDoubleWord  = 3
+};
+
+LSDataSize CalcLSPairDataSize(LoadStorePairOp op);
+
+enum ImmBranchType {
+  UnknownBranchType = 0,
+  CondBranchType    = 1,
+  UncondBranchType  = 2,
+  CompareBranchType = 3,
+  TestBranchType    = 4
+};
+
+enum AddrMode {
+  Offset,
+  PreIndex,
+  PostIndex
+};
+
+enum FPRounding {
+  // The first four values are encodable directly by FPCR<RMode>.
+  FPTieEven = 0x0,
+  FPPositiveInfinity = 0x1,
+  FPNegativeInfinity = 0x2,
+  FPZero = 0x3,
+
+  // The final rounding mode is only available when explicitly specified by the
+  // instruction (such as with fcvta). It cannot be set in FPCR.
+  FPTieAway
+};
+
+enum Reg31Mode {
+  Reg31IsStackPointer,
+  Reg31IsZeroRegister
+};
+
+// Instructions. ---------------------------------------------------------------
+
+class Instruction {
+ public:
+  inline Instr InstructionBits() const {
+    return *(reinterpret_cast<const Instr*>(this));
+  }
+
+  inline void SetInstructionBits(Instr new_instr) {
+    *(reinterpret_cast<Instr*>(this)) = new_instr;
+  }
+
+  inline int Bit(int pos) const {
+    return (InstructionBits() >> pos) & 1;
+  }
+
+  inline uint32_t Bits(int msb, int lsb) const {
+    return unsigned_bitextract_32(msb, lsb, InstructionBits());
+  }
+
+  inline int32_t SignedBits(int msb, int lsb) const {
+    int32_t bits = *(reinterpret_cast<const int32_t*>(this));
+    return signed_bitextract_32(msb, lsb, bits);
+  }
+
+  inline Instr Mask(uint32_t mask) const {
+    return InstructionBits() & mask;
+  }
+
+  #define DEFINE_GETTER(Name, HighBit, LowBit, Func)             \
+  inline int64_t Name() const { return Func(HighBit, LowBit); }
+  INSTRUCTION_FIELDS_LIST(DEFINE_GETTER)
+  #undef DEFINE_GETTER
+
+  // ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST),
+  // formed from ImmPCRelLo and ImmPCRelHi.
+  int ImmPCRel() const {
+    int const offset = ((ImmPCRelHi() << ImmPCRelLo_width) | ImmPCRelLo());
+    int const width = ImmPCRelLo_width + ImmPCRelHi_width;
+    return signed_bitextract_32(width-1, 0, offset);
+  }
+
+  uint64_t ImmLogical();
+  float ImmFP32();
+  double ImmFP64();
+
+  inline LSDataSize SizeLSPair() const {
+    return CalcLSPairDataSize(
+             static_cast<LoadStorePairOp>(Mask(LoadStorePairMask)));
+  }
+
+  // Helpers.
+  inline bool IsCondBranchImm() const {
+    return Mask(ConditionalBranchFMask) == ConditionalBranchFixed;
+  }
+
+  inline bool IsUncondBranchImm() const {
+    return Mask(UnconditionalBranchFMask) == UnconditionalBranchFixed;
+  }
+
+  inline bool IsCompareBranch() const {
+    return Mask(CompareBranchFMask) == CompareBranchFixed;
+  }
+
+  inline bool IsTestBranch() const {
+    return Mask(TestBranchFMask) == TestBranchFixed;
+  }
+
+  inline bool IsPCRelAddressing() const {
+    return Mask(PCRelAddressingFMask) == PCRelAddressingFixed;
+  }
+
+  inline bool IsLogicalImmediate() const {
+    return Mask(LogicalImmediateFMask) == LogicalImmediateFixed;
+  }
+
+  inline bool IsAddSubImmediate() const {
+    return Mask(AddSubImmediateFMask) == AddSubImmediateFixed;
+  }
+
+  inline bool IsAddSubExtended() const {
+    return Mask(AddSubExtendedFMask) == AddSubExtendedFixed;
+  }
+
+  inline bool IsLoadOrStore() const {
+    return Mask(LoadStoreAnyFMask) == LoadStoreAnyFixed;
+  }
+
+  inline bool IsMovn() const {
+    return (Mask(MoveWideImmediateMask) == MOVN_x) ||
+           (Mask(MoveWideImmediateMask) == MOVN_w);
+  }
+
+  // Indicate whether Rd can be the stack pointer or the zero register. This
+  // does not check that the instruction actually has an Rd field.
+  inline Reg31Mode RdMode() const {
+    // The following instructions use sp or wsp as Rd:
+    //  Add/sub (immediate) when not setting the flags.
+    //  Add/sub (extended) when not setting the flags.
+    //  Logical (immediate) when not setting the flags.
+    // Otherwise, r31 is the zero register.
+    if (IsAddSubImmediate() || IsAddSubExtended()) {
+      if (Mask(AddSubSetFlagsBit)) {
+        return Reg31IsZeroRegister;
+      } else {
+        return Reg31IsStackPointer;
+      }
+    }
+    if (IsLogicalImmediate()) {
+      // Of the logical (immediate) instructions, only ANDS (and its aliases)
+      // can set the flags. The others can all write into sp.
+      // Note that some logical operations are not available to
+      // immediate-operand instructions, so we have to combine two masks here.
+      if (Mask(LogicalImmediateMask & LogicalOpMask) == ANDS) {
+        return Reg31IsZeroRegister;
+      } else {
+        return Reg31IsStackPointer;
+      }
+    }
+    return Reg31IsZeroRegister;
+  }
+
+  // Indicate whether Rn can be the stack pointer or the zero register. This
+  // does not check that the instruction actually has an Rn field.
+  inline Reg31Mode RnMode() const {
+    // The following instructions use sp or wsp as Rn:
+    //  All loads and stores.
+    //  Add/sub (immediate).
+    //  Add/sub (extended).
+    // Otherwise, r31 is the zero register.
+    if (IsLoadOrStore() || IsAddSubImmediate() || IsAddSubExtended()) {
+      return Reg31IsStackPointer;
+    }
+    return Reg31IsZeroRegister;
+  }
+
+  inline ImmBranchType BranchType() const {
+    if (IsCondBranchImm()) {
+      return CondBranchType;
+    } else if (IsUncondBranchImm()) {
+      return UncondBranchType;
+    } else if (IsCompareBranch()) {
+      return CompareBranchType;
+    } else if (IsTestBranch()) {
+      return TestBranchType;
+    } else {
+      return UnknownBranchType;
+    }
+  }
+
+  // Find the target of this instruction. 'this' may be a branch or a
+  // PC-relative addressing instruction.
+  Instruction* ImmPCOffsetTarget();
+
+  // Patch a PC-relative offset to refer to 'target'. 'this' may be a branch or
+  // a PC-relative addressing instruction.
+  void SetImmPCOffsetTarget(Instruction* target);
+  // Patch a literal load instruction to load from 'source'.
+  void SetImmLLiteral(Instruction* source);
+
+  inline uint8_t* LiteralAddress() {
+    int offset = ImmLLiteral() << kLiteralEntrySizeLog2;
+    return reinterpret_cast<uint8_t*>(this) + offset;
+  }
+
+  inline uint32_t Literal32() {
+    uint32_t literal;
+    memcpy(&literal, LiteralAddress(), sizeof(literal));
+
+    return literal;
+  }
+
+  inline uint64_t Literal64() {
+    uint64_t literal;
+    memcpy(&literal, LiteralAddress(), sizeof(literal));
+
+    return literal;
+  }
+
+  inline float LiteralFP32() {
+    return rawbits_to_float(Literal32());
+  }
+
+  inline double LiteralFP64() {
+    return rawbits_to_double(Literal64());
+  }
+
+  inline Instruction* NextInstruction() {
+    return this + kInstructionSize;
+  }
+
+  inline Instruction* InstructionAtOffset(int64_t offset) {
+    ASSERT(IsWordAligned(this + offset));
+    return this + offset;
+  }
+
+  template<typename T> static inline Instruction* Cast(T src) {
+    return reinterpret_cast<Instruction*>(src);
+  }
+
+ private:
+  inline int ImmBranch() const;
+
+  void SetPCRelImmTarget(Instruction* target);
+  void SetBranchImmTarget(Instruction* target);
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_INSTRUCTIONS_A64_H_
diff --git a/disas/libvixl/src/a64/instrument-a64.cc b/disas/libvixl/src/a64/instrument-a64.cc
new file mode 100644
index 0000000..507410d
--- /dev/null
+++ b/disas/libvixl/src/a64/instrument-a64.cc
@@ -0,0 +1,638 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/instrument-a64.h"
+
+namespace vixl {
+
+Counter::Counter(const char* name, CounterType type)
+    : count_(0), enabled_(false), type_(type) {
+  ASSERT(name != NULL);
+  strncpy(name_, name, kCounterNameMaxLength);
+}
+
+
+void Counter::Enable() {
+  enabled_ = true;
+}
+
+
+void Counter::Disable() {
+  enabled_ = false;
+}
+
+
+bool Counter::IsEnabled() {
+  return enabled_;
+}
+
+
+void Counter::Increment() {
+  if (enabled_) {
+    count_++;
+  }
+}
+
+
+uint64_t Counter::count() {
+  uint64_t result = count_;
+  if (type_ == Gauge) {
+    // If the counter is a Gauge, reset the count after reading.
+    count_ = 0;
+  }
+  return result;
+}
+
+
+const char* Counter::name() {
+  return name_;
+}
+
+
+CounterType Counter::type() {
+  return type_;
+}
+
+
+typedef struct {
+  const char* name;
+  CounterType type;
+} CounterDescriptor;
+
+
+static const CounterDescriptor kCounterList[] = {
+  {"Instruction", Cumulative},
+
+  {"Move Immediate", Gauge},
+  {"Add/Sub DP", Gauge},
+  {"Logical DP", Gauge},
+  {"Other Int DP", Gauge},
+  {"FP DP", Gauge},
+
+  {"Conditional Select", Gauge},
+  {"Conditional Compare", Gauge},
+
+  {"Unconditional Branch", Gauge},
+  {"Compare and Branch", Gauge},
+  {"Test and Branch", Gauge},
+  {"Conditional Branch", Gauge},
+
+  {"Load Integer", Gauge},
+  {"Load FP", Gauge},
+  {"Load Pair", Gauge},
+  {"Load Literal", Gauge},
+
+  {"Store Integer", Gauge},
+  {"Store FP", Gauge},
+  {"Store Pair", Gauge},
+
+  {"PC Addressing", Gauge},
+  {"Other", Gauge},
+};
+
+
+Instrument::Instrument(const char* datafile, uint64_t sample_period)
+    : output_stream_(stdout), sample_period_(sample_period) {
+
+  // Set up the output stream. If datafile is non-NULL, use that file. If it
+  // can't be opened, or datafile is NULL, use stdout.
+  if (datafile != NULL) {
+    output_stream_ = fopen(datafile, "w");
+    if (output_stream_ == NULL) {
+      printf("Can't open output file %s. Using stdout.\n", datafile);
+      output_stream_ = stdout;
+    }
+  }
+
+  static const int num_counters =
+    sizeof(kCounterList) / sizeof(CounterDescriptor);
+
+  // Dump an instrumentation description comment at the top of the file.
+  fprintf(output_stream_, "# counters=%d\n", num_counters);
+  fprintf(output_stream_, "# sample_period=%" PRIu64 "\n", sample_period_);
+
+  // Construct Counter objects from counter description array.
+  for (int i = 0; i < num_counters; i++) {
+    Counter* counter = new Counter(kCounterList[i].name, kCounterList[i].type);
+    counters_.push_back(counter);
+  }
+
+  DumpCounterNames();
+}
+
+
+Instrument::~Instrument() {
+  // Dump any remaining instruction data to the output file.
+  DumpCounters();
+
+  // Free all the counter objects.
+  std::list<Counter*>::iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    free(*it);
+  }
+
+  if (output_stream_ != stdout) {
+    fclose(output_stream_);
+  }
+}
+
+
+void Instrument::Update() {
+  // Increment the instruction counter, and dump all counters if a sample period
+  // has elapsed.
+  static Counter* counter = GetCounter("Instruction");
+  ASSERT(counter->type() == Cumulative);
+  counter->Increment();
+
+  if (counter->IsEnabled() && (counter->count() % sample_period_) == 0) {
+    DumpCounters();
+  }
+}
+
+
+void Instrument::DumpCounters() {
+  // Iterate through the counter objects, dumping their values to the output
+  // stream.
+  std::list<Counter*>::const_iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    fprintf(output_stream_, "%" PRIu64 ",", (*it)->count());
+  }
+  fprintf(output_stream_, "\n");
+  fflush(output_stream_);
+}
+
+
+void Instrument::DumpCounterNames() {
+  // Iterate through the counter objects, dumping the counter names to the
+  // output stream.
+  std::list<Counter*>::const_iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    fprintf(output_stream_, "%s,", (*it)->name());
+  }
+  fprintf(output_stream_, "\n");
+  fflush(output_stream_);
+}
+
+
+void Instrument::HandleInstrumentationEvent(unsigned event) {
+  switch (event) {
+    case InstrumentStateEnable: Enable(); break;
+    case InstrumentStateDisable: Disable(); break;
+    default: DumpEventMarker(event);
+  }
+}
+
+
+void Instrument::DumpEventMarker(unsigned marker) {
+  // Dumpan event marker to the output stream as a specially formatted comment
+  // line.
+  static Counter* counter = GetCounter("Instruction");
+
+  fprintf(output_stream_, "# %c%c @ %" PRId64 "\n", marker & 0xff,
+          (marker >> 8) & 0xff, counter->count());
+}
+
+
+Counter* Instrument::GetCounter(const char* name) {
+  // Get a Counter object by name from the counter list.
+  std::list<Counter*>::const_iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    if (strcmp((*it)->name(), name) == 0) {
+      return *it;
+    }
+  }
+
+  // A Counter by that name does not exist: print an error message to stderr
+  // and the output file, and exit.
+  static const char* error_message =
+    "# Error: Unknown counter \"%s\". Exiting.\n";
+  fprintf(stderr, error_message, name);
+  fprintf(output_stream_, error_message, name);
+  exit(1);
+}
+
+
+void Instrument::Enable() {
+  std::list<Counter*>::iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    (*it)->Enable();
+  }
+}
+
+
+void Instrument::Disable() {
+  std::list<Counter*>::iterator it;
+  for (it = counters_.begin(); it != counters_.end(); it++) {
+    (*it)->Disable();
+  }
+}
+
+
+void Instrument::VisitPCRelAddressing(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("PC Addressing");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitLogicalImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Logical DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitMoveWideImmediate(Instruction* instr) {
+  Update();
+  static Counter* counter = GetCounter("Move Immediate");
+
+  if (instr->IsMovn() && (instr->Rd() == kZeroRegCode)) {
+    unsigned imm = instr->ImmMoveWide();
+    HandleInstrumentationEvent(imm);
+  } else {
+    counter->Increment();
+  }
+}
+
+
+void Instrument::VisitBitfield(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitExtract(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnconditionalBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Unconditional Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnconditionalBranchToRegister(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Unconditional Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitCompareBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Compare and Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitTestBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Test and Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalBranch(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Branch");
+  counter->Increment();
+}
+
+
+void Instrument::VisitSystem(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+void Instrument::VisitException(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+void Instrument::InstrumentLoadStorePair(Instruction* instr) {
+  static Counter* load_pair_counter = GetCounter("Load Pair");
+  static Counter* store_pair_counter = GetCounter("Store Pair");
+
+  if (instr->Mask(LoadStorePairLBit) != 0) {
+    load_pair_counter->Increment();
+  } else {
+    store_pair_counter->Increment();
+  }
+}
+
+
+void Instrument::VisitLoadStorePairPostIndex(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadStorePairOffset(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadStorePairPreIndex(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadStorePairNonTemporal(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStorePair(instr);
+}
+
+
+void Instrument::VisitLoadLiteral(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Load Literal");
+  counter->Increment();
+}
+
+
+void Instrument::InstrumentLoadStore(Instruction* instr) {
+  static Counter* load_int_counter = GetCounter("Load Integer");
+  static Counter* store_int_counter = GetCounter("Store Integer");
+  static Counter* load_fp_counter = GetCounter("Load FP");
+  static Counter* store_fp_counter = GetCounter("Store FP");
+
+  switch (instr->Mask(LoadStoreOpMask)) {
+    case STRB_w:    // Fall through.
+    case STRH_w:    // Fall through.
+    case STR_w:     // Fall through.
+    case STR_x:     store_int_counter->Increment(); break;
+    case STR_s:     // Fall through.
+    case STR_d:     store_fp_counter->Increment(); break;
+    case LDRB_w:    // Fall through.
+    case LDRH_w:    // Fall through.
+    case LDR_w:     // Fall through.
+    case LDR_x:     // Fall through.
+    case LDRSB_x:   // Fall through.
+    case LDRSH_x:   // Fall through.
+    case LDRSW_x:   // Fall through.
+    case LDRSB_w:   // Fall through.
+    case LDRSH_w:   load_int_counter->Increment(); break;
+    case LDR_s:     // Fall through.
+    case LDR_d:     load_fp_counter->Increment(); break;
+  }
+}
+
+
+void Instrument::VisitLoadStoreUnscaledOffset(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStorePostIndex(Instruction* instr) {
+  USE(instr);
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStorePreIndex(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStoreRegisterOffset(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLoadStoreUnsignedOffset(Instruction* instr) {
+  Update();
+  InstrumentLoadStore(instr);
+}
+
+
+void Instrument::VisitLogicalShifted(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Logical DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubShifted(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubExtended(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitAddSubWithCarry(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Add/Sub DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalCompareRegister(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Compare");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalCompareImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Compare");
+  counter->Increment();
+}
+
+
+void Instrument::VisitConditionalSelect(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Select");
+  counter->Increment();
+}
+
+
+void Instrument::VisitDataProcessing1Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitDataProcessing2Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitDataProcessing3Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other Int DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPCompare(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPConditionalCompare(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Compare");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPConditionalSelect(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Conditional Select");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPImmediate(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPDataProcessing1Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPDataProcessing2Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPDataProcessing3Source(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPIntegerConvert(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitFPFixedPointConvert(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("FP DP");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnallocated(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+void Instrument::VisitUnimplemented(Instruction* instr) {
+  USE(instr);
+  Update();
+  static Counter* counter = GetCounter("Other");
+  counter->Increment();
+}
+
+
+}  // namespace v8::internal
diff --git a/disas/libvixl/src/a64/instrument-a64.h b/disas/libvixl/src/a64/instrument-a64.h
new file mode 100644
index 0000000..bee965b
--- /dev/null
+++ b/disas/libvixl/src/a64/instrument-a64.h
@@ -0,0 +1,108 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_INSTRUMENT_A64_H_
+#define VIXL_A64_INSTRUMENT_A64_H_
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/decoder-a64.h"
+#include "a64/constants-a64.h"
+#include "a64/instrument-a64.h"
+
+namespace vixl {
+
+const int kCounterNameMaxLength = 256;
+const uint64_t kDefaultInstrumentationSamplingPeriod = 1 << 22;
+
+
+enum InstrumentState {
+  InstrumentStateDisable = 0,
+  InstrumentStateEnable = 1
+};
+
+
+enum CounterType {
+  Gauge = 0,      // Gauge counters reset themselves after reading.
+  Cumulative = 1  // Cumulative counters keep their value after reading.
+};
+
+
+class Counter {
+ public:
+  Counter(const char* name, CounterType type = Gauge);
+  ~Counter();
+
+  void Increment();
+  void Enable();
+  void Disable();
+  bool IsEnabled();
+  uint64_t count();
+  const char* name();
+  CounterType type();
+
+ private:
+  char name_[kCounterNameMaxLength];
+  uint64_t count_;
+  bool enabled_;
+  CounterType type_;
+};
+
+
+class Instrument: public DecoderVisitor {
+ public:
+  explicit Instrument(const char* datafile = NULL,
+    uint64_t sample_period = kDefaultInstrumentationSamplingPeriod);
+  ~Instrument();
+
+  void Enable();
+  void Disable();
+
+  // Declare all Visitor functions.
+  #define DECLARE(A) void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+ private:
+  void Update();
+  void DumpCounters();
+  void DumpCounterNames();
+  void DumpEventMarker(unsigned marker);
+  void HandleInstrumentationEvent(unsigned event);
+  Counter* GetCounter(const char* name);
+
+  void InstrumentLoadStore(Instruction* instr);
+  void InstrumentLoadStorePair(Instruction* instr);
+
+  std::list<Counter*> counters_;
+
+  FILE *output_stream_;
+  uint64_t sample_period_;
+};
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_INSTRUMENT_A64_H_
diff --git a/disas/libvixl/src/a64/macro-assembler-a64.cc b/disas/libvixl/src/a64/macro-assembler-a64.cc
new file mode 100644
index 0000000..39a925c
--- /dev/null
+++ b/disas/libvixl/src/a64/macro-assembler-a64.cc
@@ -0,0 +1,1108 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "a64/macro-assembler-a64.h"
+namespace vixl {
+
+void MacroAssembler::And(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, (S == SetFlags) ? ANDS : AND);
+}
+
+
+void MacroAssembler::Tst(const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  And(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void MacroAssembler::Bic(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, (S == SetFlags) ? BICS : BIC);
+}
+
+
+void MacroAssembler::Orr(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, ORR);
+}
+
+
+void MacroAssembler::Orn(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, ORN);
+}
+
+
+void MacroAssembler::Eor(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, EOR);
+}
+
+
+void MacroAssembler::Eon(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  LogicalMacro(rd, rn, operand, EON);
+}
+
+
+void MacroAssembler::LogicalMacro(const Register& rd,
+                                  const Register& rn,
+                                  const Operand& operand,
+                                  LogicalOp op) {
+  if (operand.IsImmediate()) {
+    int64_t immediate = operand.immediate();
+    unsigned reg_size = rd.size();
+    ASSERT(rd.Is64Bits() || is_uint32(immediate));
+
+    // If the operation is NOT, invert the operation and immediate.
+    if ((op & NOT) == NOT) {
+      op = static_cast<LogicalOp>(op & ~NOT);
+      immediate = ~immediate;
+      if (rd.Is32Bits()) {
+        immediate &= kWRegMask;
+      }
+    }
+
+    // Special cases for all set or all clear immediates.
+    if (immediate == 0) {
+      switch (op) {
+        case AND:
+          Mov(rd, 0);
+          return;
+        case ORR:  // Fall through.
+        case EOR:
+          Mov(rd, rn);
+          return;
+        case ANDS:  // Fall through.
+        case BICS:
+          break;
+        default:
+          UNREACHABLE();
+      }
+    } else if ((rd.Is64Bits() && (immediate == -1L)) ||
+               (rd.Is32Bits() && (immediate == 0xffffffffL))) {
+      switch (op) {
+        case AND:
+          Mov(rd, rn);
+          return;
+        case ORR:
+          Mov(rd, immediate);
+          return;
+        case EOR:
+          Mvn(rd, rn);
+          return;
+        case ANDS:  // Fall through.
+        case BICS:
+          break;
+        default:
+          UNREACHABLE();
+      }
+    }
+
+    unsigned n, imm_s, imm_r;
+    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
+      // Immediate can be encoded in the instruction.
+      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
+    } else {
+      // Immediate can't be encoded: synthesize using move immediate.
+      Register temp = AppropriateTempFor(rn);
+      Mov(temp, immediate);
+      if (rd.Is(sp)) {
+        // If rd is the stack pointer we cannot use it as the destination
+        // register so we use the temp register as an intermediate again.
+        Logical(temp, rn, Operand(temp), op);
+        Mov(sp, temp);
+      } else {
+        Logical(rd, rn, Operand(temp), op);
+      }
+    }
+  } else if (operand.IsExtendedRegister()) {
+    ASSERT(operand.reg().size() <= rd.size());
+    // Add/sub extended supports shift <= 4. We want to support exactly the
+    // same modes here.
+    ASSERT(operand.shift_amount() <= 4);
+    ASSERT(operand.reg().Is64Bits() ||
+           ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
+    Register temp = AppropriateTempFor(rn, operand.reg());
+    EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    Logical(rd, rn, Operand(temp), op);
+  } else {
+    // The operand can be encoded in the instruction.
+    ASSERT(operand.IsShiftedRegister());
+    Logical(rd, rn, operand, op);
+  }
+}
+
+
+void MacroAssembler::Mov(const Register& rd, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate()) {
+    // Call the macro assembler for generic immediates.
+    Mov(rd, operand.immediate());
+  } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
+    // Emit a shift instruction if moving a shifted register. This operation
+    // could also be achieved using an orr instruction (like orn used by Mvn),
+    // but using a shift instruction makes the disassembly clearer.
+    EmitShift(rd, operand.reg(), operand.shift(), operand.shift_amount());
+  } else if (operand.IsExtendedRegister()) {
+    // Emit an extend instruction if moving an extended register. This handles
+    // extend with post-shift operations, too.
+    EmitExtendShift(rd, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+  } else {
+    // Otherwise, emit a register move only if the registers are distinct, or
+    // if they are not X registers. Note that mov(w0, w0) is not a no-op
+    // because it clears the top word of x0.
+    // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
+    if (!rd.Is(operand.reg()) || !rd.Is64Bits()) {
+      mov(rd, operand.reg());
+    }
+  }
+}
+
+
+void MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate()) {
+    // Call the macro assembler for generic immediates.
+    Mvn(rd, operand.immediate());
+  } else if (operand.IsExtendedRegister()) {
+    // Emit two instructions for the extend case. This differs from Mov, as
+    // the extend and invert can't be achieved in one instruction.
+    Register temp = AppropriateTempFor(rd, operand.reg());
+    EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    mvn(rd, Operand(temp));
+  } else {
+    // Otherwise, register and shifted register cases can be handled by the
+    // assembler directly, using orn.
+    mvn(rd, operand);
+  }
+}
+
+
+void MacroAssembler::Mov(const Register& rd, uint64_t imm) {
+  ASSERT(allow_macro_instructions_);
+  ASSERT(is_uint32(imm) || is_int32(imm) || rd.Is64Bits());
+
+  // Immediates on Aarch64 can be produced using an initial value, and zero to
+  // three move keep operations.
+  //
+  // Initial values can be generated with:
+  //  1. 64-bit move zero (movz).
+  //  2. 32-bit move negative (movn).
+  //  3. 64-bit move negative.
+  //  4. 32-bit orr immediate.
+  //  5. 64-bit orr immediate.
+  // Move-keep may then be used to modify each of the 16-bit nybbles.
+  //
+  // The code below supports all five initial value generators, and
+  // applying move-keep operations to move-zero initial values only.
+
+  unsigned reg_size = rd.size();
+  unsigned n, imm_s, imm_r;
+  if (IsImmMovz(imm, reg_size) && !rd.IsSP()) {
+    // Immediate can be represented in a move zero instruction.
+    movz(rd, imm);
+  } else if (IsImmMovn(imm, reg_size) && !rd.IsSP()) {
+    // Immediate can be represented in a move negative instruction. Movn can't
+    // write to the stack pointer.
+    movn(rd, rd.Is64Bits() ? ~imm : (~imm & kWRegMask));
+  } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
+    // Immediate can be represented in a logical orr instruction.
+    ASSERT(!rd.IsZero());
+    LogicalImmediate(rd, AppropriateZeroRegFor(rd), n, imm_s, imm_r, ORR);
+  } else {
+    // Generic immediate case. Imm will be represented by
+    //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
+    // A move-zero is generated for the first non-zero immX, and a move-keep
+    // for subsequent non-zero immX.
+
+    // Use a temporary register when moving to the stack pointer.
+    Register temp = rd.IsSP() ? AppropriateTempFor(rd) : rd;
+
+    ASSERT((reg_size % 16) == 0);
+    bool first_mov_done = false;
+    for (unsigned i = 0; i < (temp.size() / 16); i++) {
+      uint64_t imm16 = (imm >> (16 * i)) & 0xffffL;
+      if (imm16 != 0) {
+        if (!first_mov_done) {
+          // Move the first non-zero 16-bit chunk into the destination register.
+          movz(temp, imm16, 16 * i);
+          first_mov_done = true;
+        } else {
+          // Construct a wider constant.
+          movk(temp, imm16, 16 * i);
+        }
+      }
+    }
+
+    if (rd.IsSP()) {
+      mov(rd, temp);
+    }
+
+    ASSERT(first_mov_done);
+  }
+}
+
+
+// The movz instruction can generate immediates containing an arbitrary 16-bit
+// value, with remaining bits set, eg. 0x00001234, 0x0000123400000000.
+bool MacroAssembler::IsImmMovz(uint64_t imm, unsigned reg_size) {
+  if (reg_size == kXRegSize) {
+    if (((imm & 0xffffffffffff0000UL) == 0UL) ||
+        ((imm & 0xffffffff0000ffffUL) == 0UL) ||
+        ((imm & 0xffff0000ffffffffUL) == 0UL) ||
+        ((imm & 0x0000ffffffffffffUL) == 0UL)) {
+      return true;
+    }
+  } else {
+    ASSERT(reg_size == kWRegSize);
+    imm &= kWRegMask;
+    if (((imm & 0xffff0000) == 0) ||
+        ((imm & 0x0000ffff) == 0)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+// The movn instruction can generate immediates containing an arbitrary 16-bit
+// value, with remaining bits set, eg. 0xffff1234, 0xffff1234ffffffff.
+bool MacroAssembler::IsImmMovn(uint64_t imm, unsigned reg_size) {
+  return IsImmMovz(~imm, reg_size);
+}
+
+
+void MacroAssembler::Ccmp(const Register& rn,
+                          const Operand& operand,
+                          StatusFlags nzcv,
+                          Condition cond) {
+  ASSERT(allow_macro_instructions_);
+  ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
+}
+
+
+void MacroAssembler::Ccmn(const Register& rn,
+                          const Operand& operand,
+                          StatusFlags nzcv,
+                          Condition cond) {
+  ASSERT(allow_macro_instructions_);
+  ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
+}
+
+
+void MacroAssembler::ConditionalCompareMacro(const Register& rn,
+                                             const Operand& operand,
+                                             StatusFlags nzcv,
+                                             Condition cond,
+                                             ConditionalCompareOp op) {
+  ASSERT((cond != al) && (cond != nv));
+  if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) ||
+      (operand.IsImmediate() && IsImmConditionalCompare(operand.immediate()))) {
+    // The immediate can be encoded in the instruction, or the operand is an
+    // unshifted register: call the assembler.
+    ConditionalCompare(rn, operand, nzcv, cond, op);
+  } else {
+    // The operand isn't directly supported by the instruction: perform the
+    // operation on a temporary register.
+    Register temp(NoReg);
+    if (operand.IsImmediate()) {
+      temp = AppropriateTempFor(rn);
+      Mov(temp, operand.immediate());
+    } else if (operand.IsShiftedRegister()) {
+      ASSERT(operand.shift() != ROR);
+      ASSERT(is_uintn(rn.size() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
+                      operand.shift_amount()));
+      temp = AppropriateTempFor(rn, operand.reg());
+      EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
+    } else {
+      ASSERT(operand.IsExtendedRegister());
+      ASSERT(operand.reg().size() <= rn.size());
+      // Add/sub extended support a shift <= 4. We want to support exactly the
+      // same modes.
+      ASSERT(operand.shift_amount() <= 4);
+      ASSERT(operand.reg().Is64Bits() ||
+             ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
+      temp = AppropriateTempFor(rn, operand.reg());
+      EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    }
+    ConditionalCompare(rn, Operand(temp), nzcv, cond, op);
+  }
+}
+
+
+void MacroAssembler::Add(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate() && (operand.immediate() < 0)) {
+    AddSubMacro(rd, rn, -operand.immediate(), S, SUB);
+  } else {
+    AddSubMacro(rd, rn, operand, S, ADD);
+  }
+}
+
+
+void MacroAssembler::Sub(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate() && (operand.immediate() < 0)) {
+    AddSubMacro(rd, rn, -operand.immediate(), S, ADD);
+  } else {
+    AddSubMacro(rd, rn, operand, S, SUB);
+  }
+}
+
+
+void MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  Add(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
+  ASSERT(allow_macro_instructions_);
+  Sub(AppropriateZeroRegFor(rn), rn, operand, SetFlags);
+}
+
+
+void MacroAssembler::Neg(const Register& rd,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  if (operand.IsImmediate()) {
+    Mov(rd, -operand.immediate());
+  } else {
+    Sub(rd, AppropriateZeroRegFor(rd), operand, S);
+  }
+}
+
+
+void MacroAssembler::AddSubMacro(const Register& rd,
+                                 const Register& rn,
+                                 const Operand& operand,
+                                 FlagsUpdate S,
+                                 AddSubOp op) {
+  if ((operand.IsImmediate() && !IsImmAddSub(operand.immediate())) ||
+      (rn.IsZero() && !operand.IsShiftedRegister())                ||
+      (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
+    Register temp = AppropriateTempFor(rn);
+    Mov(temp, operand);
+    AddSub(rd, rn, temp, S, op);
+  } else {
+    AddSub(rd, rn, operand, S, op);
+  }
+}
+
+
+void MacroAssembler::Adc(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  AddSubWithCarryMacro(rd, rn, operand, S, ADC);
+}
+
+
+void MacroAssembler::Sbc(const Register& rd,
+                         const Register& rn,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  AddSubWithCarryMacro(rd, rn, operand, S, SBC);
+}
+
+
+void MacroAssembler::Ngc(const Register& rd,
+                         const Operand& operand,
+                         FlagsUpdate S) {
+  ASSERT(allow_macro_instructions_);
+  Register zr = AppropriateZeroRegFor(rd);
+  Sbc(rd, zr, operand, S);
+}
+
+
+void MacroAssembler::AddSubWithCarryMacro(const Register& rd,
+                                          const Register& rn,
+                                          const Operand& operand,
+                                          FlagsUpdate S,
+                                          AddSubWithCarryOp op) {
+  ASSERT(rd.size() == rn.size());
+
+  if (operand.IsImmediate() ||
+      (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
+    // Add/sub with carry (immediate or ROR shifted register.)
+    Register temp = AppropriateTempFor(rn);
+    Mov(temp, operand);
+    AddSubWithCarry(rd, rn, Operand(temp), S, op);
+  } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
+    // Add/sub with carry (shifted register).
+    ASSERT(operand.reg().size() == rd.size());
+    ASSERT(operand.shift() != ROR);
+    ASSERT(is_uintn(rd.size() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
+                    operand.shift_amount()));
+    Register temp = AppropriateTempFor(rn, operand.reg());
+    EmitShift(temp, operand.reg(), operand.shift(), operand.shift_amount());
+    AddSubWithCarry(rd, rn, Operand(temp), S, op);
+  } else if (operand.IsExtendedRegister()) {
+    // Add/sub with carry (extended register).
+    ASSERT(operand.reg().size() <= rd.size());
+    // Add/sub extended supports a shift <= 4. We want to support exactly the
+    // same modes.
+    ASSERT(operand.shift_amount() <= 4);
+    ASSERT(operand.reg().Is64Bits() ||
+           ((operand.extend() != UXTX) && (operand.extend() != SXTX)));
+    Register temp = AppropriateTempFor(rn, operand.reg());
+    EmitExtendShift(temp, operand.reg(), operand.extend(),
+                    operand.shift_amount());
+    AddSubWithCarry(rd, rn, Operand(temp), S, op);
+  } else {
+    // The addressing mode is directly supported by the instruction.
+    AddSubWithCarry(rd, rn, operand, S, op);
+  }
+}
+
+
+#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                         \
+void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) {  \
+  LoadStoreMacro(REG, addr, OP);                                      \
+}
+LS_MACRO_LIST(DEFINE_FUNCTION)
+#undef DEFINE_FUNCTION
+
+void MacroAssembler::LoadStoreMacro(const CPURegister& rt,
+                                    const MemOperand& addr,
+                                    LoadStoreOp op) {
+  int64_t offset = addr.offset();
+  LSDataSize size = CalcLSDataSize(op);
+
+  // Check if an immediate offset fits in the immediate field of the
+  // appropriate instruction. If not, emit two instructions to perform
+  // the operation.
+  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, size) &&
+      !IsImmLSUnscaled(offset)) {
+    // Immediate offset that can't be encoded using unsigned or unscaled
+    // addressing modes.
+    Register temp = AppropriateTempFor(addr.base());
+    Mov(temp, addr.offset());
+    LoadStore(rt, MemOperand(addr.base(), temp), op);
+  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
+    // Post-index beyond unscaled addressing range.
+    LoadStore(rt, MemOperand(addr.base()), op);
+    Add(addr.base(), addr.base(), Operand(offset));
+  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
+    // Pre-index beyond unscaled addressing range.
+    Add(addr.base(), addr.base(), Operand(offset));
+    LoadStore(rt, MemOperand(addr.base()), op);
+  } else {
+    // Encodable in one load/store instruction.
+    LoadStore(rt, addr, op);
+  }
+}
+
+
+void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1,
+                          const CPURegister& src2, const CPURegister& src3) {
+  ASSERT(allow_macro_instructions_);
+  ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
+  ASSERT(src0.IsValid());
+
+  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
+  int size = src0.SizeInBytes();
+
+  PrepareForPush(count, size);
+  PushHelper(count, size, src0, src1, src2, src3);
+}
+
+
+void MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1,
+                         const CPURegister& dst2, const CPURegister& dst3) {
+  // It is not valid to pop into the same register more than once in one
+  // instruction, not even into the zero register.
+  ASSERT(allow_macro_instructions_);
+  ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
+  ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
+  ASSERT(dst0.IsValid());
+
+  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
+  int size = dst0.SizeInBytes();
+
+  PrepareForPop(count, size);
+  PopHelper(count, size, dst0, dst1, dst2, dst3);
+}
+
+
+void MacroAssembler::PushCPURegList(CPURegList registers) {
+  int size = registers.RegisterSizeInBytes();
+
+  PrepareForPush(registers.Count(), size);
+  // Push up to four registers at a time because if the current stack pointer is
+  // sp and reg_size is 32, registers must be pushed in blocks of four in order
+  // to maintain the 16-byte alignment for sp.
+  ASSERT(allow_macro_instructions_);
+  while (!registers.IsEmpty()) {
+    int count_before = registers.Count();
+    const CPURegister& src0 = registers.PopHighestIndex();
+    const CPURegister& src1 = registers.PopHighestIndex();
+    const CPURegister& src2 = registers.PopHighestIndex();
+    const CPURegister& src3 = registers.PopHighestIndex();
+    int count = count_before - registers.Count();
+    PushHelper(count, size, src0, src1, src2, src3);
+  }
+}
+
+
+void MacroAssembler::PopCPURegList(CPURegList registers) {
+  int size = registers.RegisterSizeInBytes();
+
+  PrepareForPop(registers.Count(), size);
+  // Pop up to four registers at a time because if the current stack pointer is
+  // sp and reg_size is 32, registers must be pushed in blocks of four in order
+  // to maintain the 16-byte alignment for sp.
+  ASSERT(allow_macro_instructions_);
+  while (!registers.IsEmpty()) {
+    int count_before = registers.Count();
+    const CPURegister& dst0 = registers.PopLowestIndex();
+    const CPURegister& dst1 = registers.PopLowestIndex();
+    const CPURegister& dst2 = registers.PopLowestIndex();
+    const CPURegister& dst3 = registers.PopLowestIndex();
+    int count = count_before - registers.Count();
+    PopHelper(count, size, dst0, dst1, dst2, dst3);
+  }
+}
+
+
+void MacroAssembler::PushMultipleTimes(int count, Register src) {
+  ASSERT(allow_macro_instructions_);
+  int size = src.SizeInBytes();
+
+  PrepareForPush(count, size);
+  // Push up to four registers at a time if possible because if the current
+  // stack pointer is sp and the register size is 32, registers must be pushed
+  // in blocks of four in order to maintain the 16-byte alignment for sp.
+  while (count >= 4) {
+    PushHelper(4, size, src, src, src, src);
+    count -= 4;
+  }
+  if (count >= 2) {
+    PushHelper(2, size, src, src, NoReg, NoReg);
+    count -= 2;
+  }
+  if (count == 1) {
+    PushHelper(1, size, src, NoReg, NoReg, NoReg);
+    count -= 1;
+  }
+  ASSERT(count == 0);
+}
+
+
+void MacroAssembler::PushHelper(int count, int size,
+                                const CPURegister& src0,
+                                const CPURegister& src1,
+                                const CPURegister& src2,
+                                const CPURegister& src3) {
+  // Ensure that we don't unintentionally modify scratch or debug registers.
+  InstructionAccurateScope scope(this);
+
+  ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
+  ASSERT(size == src0.SizeInBytes());
+
+  // When pushing multiple registers, the store order is chosen such that
+  // Push(a, b) is equivalent to Push(a) followed by Push(b).
+  switch (count) {
+    case 1:
+      ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
+      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
+      break;
+    case 2:
+      ASSERT(src2.IsNone() && src3.IsNone());
+      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
+      break;
+    case 3:
+      ASSERT(src3.IsNone());
+      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
+      str(src0, MemOperand(StackPointer(), 2 * size));
+      break;
+    case 4:
+      // Skip over 4 * size, then fill in the gap. This allows four W registers
+      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
+      // all times.
+      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
+      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void MacroAssembler::PopHelper(int count, int size,
+                               const CPURegister& dst0,
+                               const CPURegister& dst1,
+                               const CPURegister& dst2,
+                               const CPURegister& dst3) {
+  // Ensure that we don't unintentionally modify scratch or debug registers.
+  InstructionAccurateScope scope(this);
+
+  ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
+  ASSERT(size == dst0.SizeInBytes());
+
+  // When popping multiple registers, the load order is chosen such that
+  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
+  switch (count) {
+    case 1:
+      ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
+      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
+      break;
+    case 2:
+      ASSERT(dst2.IsNone() && dst3.IsNone());
+      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
+      break;
+    case 3:
+      ASSERT(dst3.IsNone());
+      ldr(dst2, MemOperand(StackPointer(), 2 * size));
+      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
+      break;
+    case 4:
+      // Load the higher addresses first, then load the lower addresses and skip
+      // the whole block in the second instruction. This allows four W registers
+      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
+      // all times.
+      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
+      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void MacroAssembler::PrepareForPush(int count, int size) {
+  if (sp.Is(StackPointer())) {
+    // If the current stack pointer is sp, then it must be aligned to 16 bytes
+    // on entry and the total size of the specified registers must also be a
+    // multiple of 16 bytes.
+    ASSERT((count * size) % 16 == 0);
+  } else {
+    // Even if the current stack pointer is not the system stack pointer (sp),
+    // the system stack pointer will still be modified in order to comply with
+    // ABI rules about accessing memory below the system stack pointer.
+    BumpSystemStackPointer(count * size);
+  }
+}
+
+
+void MacroAssembler::PrepareForPop(int count, int size) {
+  USE(count);
+  USE(size);
+  if (sp.Is(StackPointer())) {
+    // If the current stack pointer is sp, then it must be aligned to 16 bytes
+    // on entry and the total size of the specified registers must also be a
+    // multiple of 16 bytes.
+    ASSERT((count * size) % 16 == 0);
+  }
+}
+
+void MacroAssembler::Poke(const Register& src, const Operand& offset) {
+  ASSERT(allow_macro_instructions_);
+  if (offset.IsImmediate()) {
+    ASSERT(offset.immediate() >= 0);
+  }
+
+  Str(src, MemOperand(StackPointer(), offset));
+}
+
+
+void MacroAssembler::Peek(const Register& dst, const Operand& offset) {
+  ASSERT(allow_macro_instructions_);
+  if (offset.IsImmediate()) {
+    ASSERT(offset.immediate() >= 0);
+  }
+
+  Ldr(dst, MemOperand(StackPointer(), offset));
+}
+
+
+void MacroAssembler::Claim(const Operand& size) {
+  ASSERT(allow_macro_instructions_);
+  if (size.IsImmediate()) {
+    ASSERT(size.immediate() >= 0);
+    if (sp.Is(StackPointer())) {
+      ASSERT((size.immediate() % 16) == 0);
+    }
+  }
+
+  if (!sp.Is(StackPointer())) {
+    BumpSystemStackPointer(size);
+  }
+
+  Sub(StackPointer(), StackPointer(), size);
+}
+
+
+void MacroAssembler::Drop(const Operand& size) {
+  ASSERT(allow_macro_instructions_);
+  if (size.IsImmediate()) {
+    ASSERT(size.immediate() >= 0);
+    if (sp.Is(StackPointer())) {
+      ASSERT((size.immediate() % 16) == 0);
+    }
+  }
+
+  Add(StackPointer(), StackPointer(), size);
+}
+
+
+void MacroAssembler::PushCalleeSavedRegisters() {
+  // Ensure that the macro-assembler doesn't use any scratch registers.
+  InstructionAccurateScope scope(this);
+
+  // This method must not be called unless the current stack pointer is sp.
+  ASSERT(sp.Is(StackPointer()));
+
+  MemOperand tos(sp, -2 * kXRegSizeInBytes, PreIndex);
+
+  stp(d14, d15, tos);
+  stp(d12, d13, tos);
+  stp(d10, d11, tos);
+  stp(d8, d9, tos);
+
+  stp(x29, x30, tos);
+  stp(x27, x28, tos);
+  stp(x25, x26, tos);
+  stp(x23, x24, tos);
+  stp(x21, x22, tos);
+  stp(x19, x20, tos);
+}
+
+
+void MacroAssembler::PopCalleeSavedRegisters() {
+  // Ensure that the macro-assembler doesn't use any scratch registers.
+  InstructionAccurateScope scope(this);
+
+  // This method must not be called unless the current stack pointer is sp.
+  ASSERT(sp.Is(StackPointer()));
+
+  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
+
+  ldp(x19, x20, tos);
+  ldp(x21, x22, tos);
+  ldp(x23, x24, tos);
+  ldp(x25, x26, tos);
+  ldp(x27, x28, tos);
+  ldp(x29, x30, tos);
+
+  ldp(d8, d9, tos);
+  ldp(d10, d11, tos);
+  ldp(d12, d13, tos);
+  ldp(d14, d15, tos);
+}
+
+void MacroAssembler::BumpSystemStackPointer(const Operand& space) {
+  ASSERT(!sp.Is(StackPointer()));
+  // TODO: Several callers rely on this not using scratch registers, so we use
+  // the assembler directly here. However, this means that large immediate
+  // values of 'space' cannot be handled.
+  InstructionAccurateScope scope(this);
+  sub(sp, StackPointer(), space);
+}
+
+
+// This is the main Printf implementation. All callee-saved registers are
+// preserved, but NZCV and the caller-saved registers may be clobbered.
+void MacroAssembler::PrintfNoPreserve(const char * format,
+                                      const CPURegister& arg0,
+                                      const CPURegister& arg1,
+                                      const CPURegister& arg2,
+                                      const CPURegister& arg3) {
+  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
+  // in most cases anyway, so this restriction shouldn't be too serious.
+  ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
+
+  // We cannot print Tmp0() or Tmp1() as they're used internally by the macro
+  // assembler. We cannot print the stack pointer because it is typically used
+  // to preserve caller-saved registers (using other Printf variants which
+  // depend on this helper).
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg0));
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg1));
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg2));
+  ASSERT(!AreAliased(Tmp0(), Tmp1(), StackPointer(), arg3));
+
+  static const int kMaxArgCount = 4;
+  // Assume that we have the maximum number of arguments until we know
+  // otherwise.
+  int arg_count = kMaxArgCount;
+
+  // The provided arguments.
+  CPURegister args[kMaxArgCount] = {arg0, arg1, arg2, arg3};
+
+  // The PCS registers where the arguments need to end up.
+  CPURegister pcs[kMaxArgCount];
+
+  // Promote FP arguments to doubles, and integer arguments to X registers.
+  // Note that FP and integer arguments cannot be mixed, but we'll check
+  // AreSameSizeAndType once we've processed these promotions.
+  for (int i = 0; i < kMaxArgCount; i++) {
+    if (args[i].IsRegister()) {
+      // Note that we use x1 onwards, because x0 will hold the format string.
+      pcs[i] = Register::XRegFromCode(i + 1);
+      // For simplicity, we handle all integer arguments as X registers. An X
+      // register argument takes the same space as a W register argument in the
+      // PCS anyway. The only limitation is that we must explicitly clear the
+      // top word for W register arguments as the callee will expect it to be
+      // clear.
+      if (!args[i].Is64Bits()) {
+        const Register& as_x = args[i].X();
+        And(as_x, as_x, 0x00000000ffffffff);
+        args[i] = as_x;
+      }
+    } else if (args[i].IsFPRegister()) {
+      pcs[i] = FPRegister::DRegFromCode(i);
+      // C and C++ varargs functions (such as printf) implicitly promote float
+      // arguments to doubles.
+      if (!args[i].Is64Bits()) {
+        FPRegister s(args[i]);
+        const FPRegister& as_d = args[i].D();
+        Fcvt(as_d, s);
+        args[i] = as_d;
+      }
+    } else {
+      // This is the first empty (NoCPUReg) argument, so use it to set the
+      // argument count and bail out.
+      arg_count = i;
+      break;
+    }
+  }
+  ASSERT((arg_count >= 0) && (arg_count <= kMaxArgCount));
+  // Check that every remaining argument is NoCPUReg.
+  for (int i = arg_count; i < kMaxArgCount; i++) {
+    ASSERT(args[i].IsNone());
+  }
+  ASSERT((arg_count == 0) || AreSameSizeAndType(args[0], args[1],
+                                                args[2], args[3],
+                                                pcs[0], pcs[1],
+                                                pcs[2], pcs[3]));
+
+  // Move the arguments into the appropriate PCS registers.
+  //
+  // Arranging an arbitrary list of registers into x1-x4 (or d0-d3) is
+  // surprisingly complicated.
+  //
+  //  * For even numbers of registers, we push the arguments and then pop them
+  //    into their final registers. This maintains 16-byte stack alignment in
+  //    case sp is the stack pointer, since we're only handling X or D registers
+  //    at this point.
+  //
+  //  * For odd numbers of registers, we push and pop all but one register in
+  //    the same way, but the left-over register is moved directly, since we
+  //    can always safely move one register without clobbering any source.
+  if (arg_count >= 4) {
+    Push(args[3], args[2], args[1], args[0]);
+  } else if (arg_count >= 2) {
+    Push(args[1], args[0]);
+  }
+
+  if ((arg_count % 2) != 0) {
+    // Move the left-over register directly.
+    const CPURegister& leftover_arg = args[arg_count - 1];
+    const CPURegister& leftover_pcs = pcs[arg_count - 1];
+    if (leftover_arg.IsRegister()) {
+      Mov(Register(leftover_pcs), Register(leftover_arg));
+    } else {
+      Fmov(FPRegister(leftover_pcs), FPRegister(leftover_arg));
+    }
+  }
+
+  if (arg_count >= 4) {
+    Pop(pcs[0], pcs[1], pcs[2], pcs[3]);
+  } else if (arg_count >= 2) {
+    Pop(pcs[0], pcs[1]);
+  }
+
+  // Load the format string into x0, as per the procedure-call standard.
+  //
+  // To make the code as portable as possible, the format string is encoded
+  // directly in the instruction stream. It might be cleaner to encode it in a
+  // literal pool, but since Printf is usually used for debugging, it is
+  // beneficial for it to be minimally dependent on other features.
+  Label format_address;
+  Adr(x0, &format_address);
+
+  // Emit the format string directly in the instruction stream.
+  { BlockLiteralPoolScope scope(this);
+    Label after_data;
+    B(&after_data);
+    Bind(&format_address);
+    EmitStringData(format);
+    Unreachable();
+    Bind(&after_data);
+  }
+
+  // We don't pass any arguments on the stack, but we still need to align the C
+  // stack pointer to a 16-byte boundary for PCS compliance.
+  if (!sp.Is(StackPointer())) {
+    Bic(sp, StackPointer(), 0xf);
+  }
+
+  // Actually call printf. This part needs special handling for the simulator,
+  // since the system printf function will use a different instruction set and
+  // the procedure-call standard will not be compatible.
+#ifdef USE_SIMULATOR
+  { InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
+    hlt(kPrintfOpcode);
+    dc32(pcs[0].type());
+  }
+#else
+  Mov(Tmp0(), reinterpret_cast<uintptr_t>(printf));
+  Blr(Tmp0());
+#endif
+}
+
+
+void MacroAssembler::Printf(const char * format,
+                            const CPURegister& arg0,
+                            const CPURegister& arg1,
+                            const CPURegister& arg2,
+                            const CPURegister& arg3) {
+  // Preserve all caller-saved registers as well as NZCV.
+  // If sp is the stack pointer, PushCPURegList asserts that the size of each
+  // list is a multiple of 16 bytes.
+  PushCPURegList(kCallerSaved);
+  PushCPURegList(kCallerSavedFP);
+  // Use Tmp0() as a scratch register. It is not accepted by Printf so it will
+  // never overlap an argument register.
+  Mrs(Tmp0(), NZCV);
+  Push(Tmp0(), xzr);
+
+  PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
+
+  Pop(xzr, Tmp0());
+  Msr(NZCV, Tmp0());
+  PopCPURegList(kCallerSavedFP);
+  PopCPURegList(kCallerSaved);
+}
+
+void MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
+  ASSERT(allow_macro_instructions_);
+
+#ifdef USE_SIMULATOR
+  // The arguments to the trace pseudo instruction need to be contiguous in
+  // memory, so make sure we don't try to emit a literal pool.
+  InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
+
+  Label start;
+  bind(&start);
+
+  // Refer to instructions-a64.h for a description of the marker and its
+  // arguments.
+  hlt(kTraceOpcode);
+
+  ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
+  dc32(parameters);
+
+  ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
+  dc32(command);
+#else
+  // Emit nothing on real hardware.
+  USE(parameters);
+  USE(command);
+#endif
+}
+
+
+void MacroAssembler::Log(TraceParameters parameters) {
+  ASSERT(allow_macro_instructions_);
+
+#ifdef USE_SIMULATOR
+  // The arguments to the log pseudo instruction need to be contiguous in
+  // memory, so make sure we don't try to emit a literal pool.
+  InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
+
+  Label start;
+  bind(&start);
+
+  // Refer to instructions-a64.h for a description of the marker and its
+  // arguments.
+  hlt(kLogOpcode);
+
+  ASSERT(SizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
+  dc32(parameters);
+#else
+  // Emit nothing on real hardware.
+  USE(parameters);
+#endif
+}
+
+
+void MacroAssembler::EnableInstrumentation() {
+  ASSERT(!isprint(InstrumentStateEnable));
+  InstructionAccurateScope scope(this, 1);
+  movn(xzr, InstrumentStateEnable);
+}
+
+
+void MacroAssembler::DisableInstrumentation() {
+  ASSERT(!isprint(InstrumentStateDisable));
+  InstructionAccurateScope scope(this, 1);
+  movn(xzr, InstrumentStateDisable);
+}
+
+
+void MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
+  ASSERT(strlen(marker_name) == 2);
+
+  // We allow only printable characters in the marker names. Unprintable
+  // characters are reserved for controlling features of the instrumentation.
+  ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
+
+  InstructionAccurateScope scope(this, 1);
+  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/macro-assembler-a64.h b/disas/libvixl/src/a64/macro-assembler-a64.h
new file mode 100644
index 0000000..f266063
--- /dev/null
+++ b/disas/libvixl/src/a64/macro-assembler-a64.h
@@ -0,0 +1,1175 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_MACRO_ASSEMBLER_A64_H_
+#define VIXL_A64_MACRO_ASSEMBLER_A64_H_
+
+#include "globals.h"
+#include "a64/assembler-a64.h"
+#include "a64/debugger-a64.h"
+
+
+#define LS_MACRO_LIST(V)                                      \
+  V(Ldrb, Register&, rt, LDRB_w)                              \
+  V(Strb, Register&, rt, STRB_w)                              \
+  V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w)  \
+  V(Ldrh, Register&, rt, LDRH_w)                              \
+  V(Strh, Register&, rt, STRH_w)                              \
+  V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w)  \
+  V(Ldr, CPURegister&, rt, LoadOpFor(rt))                     \
+  V(Str, CPURegister&, rt, StoreOpFor(rt))                    \
+  V(Ldrsw, Register&, rt, LDRSW_x)
+
+namespace vixl {
+
+class MacroAssembler : public Assembler {
+ public:
+  MacroAssembler(byte * buffer, unsigned buffer_size)
+      : Assembler(buffer, buffer_size),
+#ifdef DEBUG
+        allow_macro_instructions_(true),
+#endif
+        sp_(sp), tmp0_(ip0), tmp1_(ip1), fptmp0_(d31) {}
+
+  // Logical macros.
+  void And(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Bic(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Orr(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Orn(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Eor(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Eon(const Register& rd,
+           const Register& rn,
+           const Operand& operand);
+  void Tst(const Register& rn, const Operand& operand);
+  void LogicalMacro(const Register& rd,
+                    const Register& rn,
+                    const Operand& operand,
+                    LogicalOp op);
+
+  // Add and sub macros.
+  void Add(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Sub(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Cmn(const Register& rn, const Operand& operand);
+  void Cmp(const Register& rn, const Operand& operand);
+  void Neg(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void AddSubMacro(const Register& rd,
+                   const Register& rn,
+                   const Operand& operand,
+                   FlagsUpdate S,
+                   AddSubOp op);
+
+  // Add/sub with carry macros.
+  void Adc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Sbc(const Register& rd,
+           const Register& rn,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void Ngc(const Register& rd,
+           const Operand& operand,
+           FlagsUpdate S = LeaveFlags);
+  void AddSubWithCarryMacro(const Register& rd,
+                            const Register& rn,
+                            const Operand& operand,
+                            FlagsUpdate S,
+                            AddSubWithCarryOp op);
+
+  // Move macros.
+  void Mov(const Register& rd, uint64_t imm);
+  void Mov(const Register& rd, const Operand& operand);
+  void Mvn(const Register& rd, uint64_t imm) {
+    Mov(rd, ~imm);
+  };
+  void Mvn(const Register& rd, const Operand& operand);
+  bool IsImmMovn(uint64_t imm, unsigned reg_size);
+  bool IsImmMovz(uint64_t imm, unsigned reg_size);
+
+  // Conditional compare macros.
+  void Ccmp(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+  void Ccmn(const Register& rn,
+            const Operand& operand,
+            StatusFlags nzcv,
+            Condition cond);
+  void ConditionalCompareMacro(const Register& rn,
+                               const Operand& operand,
+                               StatusFlags nzcv,
+                               Condition cond,
+                               ConditionalCompareOp op);
+
+  // Load/store macros.
+#define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
+  void FN(const REGTYPE REG, const MemOperand& addr);
+  LS_MACRO_LIST(DECLARE_FUNCTION)
+#undef DECLARE_FUNCTION
+
+  void LoadStoreMacro(const CPURegister& rt,
+                      const MemOperand& addr,
+                      LoadStoreOp op);
+
+  // Push or pop up to 4 registers of the same width to or from the stack,
+  // using the current stack pointer as set by SetStackPointer.
+  //
+  // If an argument register is 'NoReg', all further arguments are also assumed
+  // to be 'NoReg', and are thus not pushed or popped.
+  //
+  // Arguments are ordered such that "Push(a, b);" is functionally equivalent
+  // to "Push(a); Push(b);".
+  //
+  // It is valid to push the same register more than once, and there is no
+  // restriction on the order in which registers are specified.
+  //
+  // It is not valid to pop into the same register more than once in one
+  // operation, not even into the zero register.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then it
+  // must be aligned to 16 bytes on entry and the total size of the specified
+  // registers must also be a multiple of 16 bytes.
+  //
+  // Even if the current stack pointer is not the system stack pointer (sp),
+  // Push (and derived methods) will still modify the system stack pointer in
+  // order to comply with ABI rules about accessing memory below the system
+  // stack pointer.
+  //
+  // Other than the registers passed into Pop, the stack pointer and (possibly)
+  // the system stack pointer, these methods do not modify any other registers.
+  // Scratch registers such as Tmp0() and Tmp1() are preserved.
+  void Push(const CPURegister& src0, const CPURegister& src1 = NoReg,
+            const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg);
+  void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg,
+           const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg);
+
+  // Alternative forms of Push and Pop, taking a RegList or CPURegList that
+  // specifies the registers that are to be pushed or popped. Higher-numbered
+  // registers are associated with higher memory addresses (as in the A32 push
+  // and pop instructions).
+  //
+  // (Push|Pop)SizeRegList allow you to specify the register size as a
+  // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
+  // supported.
+  //
+  // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
+  void PushCPURegList(CPURegList registers);
+  void PopCPURegList(CPURegList registers);
+
+  void PushSizeRegList(RegList registers, unsigned reg_size,
+      CPURegister::RegisterType type = CPURegister::kRegister) {
+    PushCPURegList(CPURegList(type, reg_size, registers));
+  }
+  void PopSizeRegList(RegList registers, unsigned reg_size,
+      CPURegister::RegisterType type = CPURegister::kRegister) {
+    PopCPURegList(CPURegList(type, reg_size, registers));
+  }
+  void PushXRegList(RegList regs) {
+    PushSizeRegList(regs, kXRegSize);
+  }
+  void PopXRegList(RegList regs) {
+    PopSizeRegList(regs, kXRegSize);
+  }
+  void PushWRegList(RegList regs) {
+    PushSizeRegList(regs, kWRegSize);
+  }
+  void PopWRegList(RegList regs) {
+    PopSizeRegList(regs, kWRegSize);
+  }
+  inline void PushDRegList(RegList regs) {
+    PushSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
+  }
+  inline void PopDRegList(RegList regs) {
+    PopSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
+  }
+  inline void PushSRegList(RegList regs) {
+    PushSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
+  }
+  inline void PopSRegList(RegList regs) {
+    PopSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
+  }
+
+  // Push the specified register 'count' times.
+  void PushMultipleTimes(int count, Register src);
+
+  // Poke 'src' onto the stack. The offset is in bytes.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then sp
+  // must be aligned to 16 bytes.
+  void Poke(const Register& src, const Operand& offset);
+
+  // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then sp
+  // must be aligned to 16 bytes.
+  void Peek(const Register& dst, const Operand& offset);
+
+  // Claim or drop stack space without actually accessing memory.
+  //
+  // If the current stack pointer (as set by SetStackPointer) is sp, then it
+  // must be aligned to 16 bytes and the size claimed or dropped must be a
+  // multiple of 16 bytes.
+  void Claim(const Operand& size);
+  void Drop(const Operand& size);
+
+  // Preserve the callee-saved registers (as defined by AAPCS64).
+  //
+  // Higher-numbered registers are pushed before lower-numbered registers, and
+  // thus get higher addresses.
+  // Floating-point registers are pushed before general-purpose registers, and
+  // thus get higher addresses.
+  //
+  // This method must not be called unless StackPointer() is sp, and it is
+  // aligned to 16 bytes.
+  void PushCalleeSavedRegisters();
+
+  // Restore the callee-saved registers (as defined by AAPCS64).
+  //
+  // Higher-numbered registers are popped after lower-numbered registers, and
+  // thus come from higher addresses.
+  // Floating-point registers are popped after general-purpose registers, and
+  // thus come from higher addresses.
+  //
+  // This method must not be called unless StackPointer() is sp, and it is
+  // aligned to 16 bytes.
+  void PopCalleeSavedRegisters();
+
+  // Remaining instructions are simple pass-through calls to the assembler.
+  void Adr(const Register& rd, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    adr(rd, label);
+  }
+  void Asr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    asr(rd, rn, shift);
+  }
+  void Asr(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    asrv(rd, rn, rm);
+  }
+  void B(Label* label) {
+    b(label);
+  }
+  void B(Label* label, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT((cond != al) && (cond != nv));
+    b(label, cond);
+  }
+  void Bfi(const Register& rd,
+           const Register& rn,
+           unsigned lsb,
+           unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    bfi(rd, rn, lsb, width);
+  }
+  void Bfxil(const Register& rd,
+             const Register& rn,
+             unsigned lsb,
+             unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    bfxil(rd, rn, lsb, width);
+  }
+  void Bind(Label* label) {
+    ASSERT(allow_macro_instructions_);
+    bind(label);
+  }
+  void Bl(Label* label) {
+    ASSERT(allow_macro_instructions_);
+    bl(label);
+  }
+  void Blr(const Register& xn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xn.IsZero());
+    blr(xn);
+  }
+  void Br(const Register& xn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xn.IsZero());
+    br(xn);
+  }
+  void Brk(int code = 0) {
+    ASSERT(allow_macro_instructions_);
+    brk(code);
+  }
+  void Cbnz(const Register& rt, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    cbnz(rt, label);
+  }
+  void Cbz(const Register& rt, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    cbz(rt, label);
+  }
+  void Cinc(const Register& rd, const Register& rn, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cinc(rd, rn, cond);
+  }
+  void Cinv(const Register& rd, const Register& rn, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cinv(rd, rn, cond);
+  }
+  void Cls(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cls(rd, rn);
+  }
+  void Clz(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    clz(rd, rn);
+  }
+  void Cneg(const Register& rd, const Register& rn, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    cneg(rd, rn, cond);
+  }
+  void Csel(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csel(rd, rn, rm, cond);
+  }
+  void Cset(const Register& rd, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    cset(rd, cond);
+  }
+  void Csetm(const Register& rd, Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    csetm(rd, cond);
+  }
+  void Csinc(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csinc(rd, rn, rm, cond);
+  }
+  void Csinv(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csinv(rd, rn, rm, cond);
+  }
+  void Csneg(const Register& rd,
+             const Register& rn,
+             const Register& rm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT((cond != al) && (cond != nv));
+    csneg(rd, rn, rm, cond);
+  }
+  void Extr(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            unsigned lsb) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    extr(rd, rn, rm, lsb);
+  }
+  void Fabs(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fabs(fd, fn);
+  }
+  void Fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fadd(fd, fn, fm);
+  }
+  void Fccmp(const FPRegister& fn,
+             const FPRegister& fm,
+             StatusFlags nzcv,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT((cond != al) && (cond != nv));
+    fccmp(fn, fm, nzcv, cond);
+  }
+  void Fcmp(const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fcmp(fn, fm);
+  }
+  void Fcmp(const FPRegister& fn, double value) {
+    ASSERT(allow_macro_instructions_);
+    if (value != 0.0) {
+      FPRegister tmp = AppropriateTempFor(fn);
+      Fmov(tmp, value);
+      fcmp(fn, tmp);
+    } else {
+      fcmp(fn, value);
+    }
+  }
+  void Fcsel(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             Condition cond) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT((cond != al) && (cond != nv));
+    fcsel(fd, fn, fm, cond);
+  }
+  void Fcvt(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fcvt(fd, fn);
+  }
+  void Fcvtms(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtms(rd, fn);
+  }
+  void Fcvtmu(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtmu(rd, fn);
+  }
+  void Fcvtns(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtns(rd, fn);
+  }
+  void Fcvtnu(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtnu(rd, fn);
+  }
+  void Fcvtzs(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtzs(rd, fn);
+  }
+  void Fcvtzu(const Register& rd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fcvtzu(rd, fn);
+  }
+  void Fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fdiv(fd, fn, fm);
+  }
+  void Fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fmax(fd, fn, fm);
+  }
+  void Fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fmin(fd, fn, fm);
+  }
+  void Fmov(FPRegister fd, FPRegister fn) {
+    ASSERT(allow_macro_instructions_);
+    // Only emit an instruction if fd and fn are different, and they are both D
+    // registers. fmov(s0, s0) is not a no-op because it clears the top word of
+    // d0. Technically, fmov(d0, d0) is not a no-op either because it clears
+    // the top of q0, but FPRegister does not currently support Q registers.
+    if (!fd.Is(fn) || !fd.Is64Bits()) {
+      fmov(fd, fn);
+    }
+  }
+  void Fmov(FPRegister fd, Register rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rn.IsZero());
+    fmov(fd, rn);
+  }
+  void Fmov(FPRegister fd, double imm) {
+    ASSERT(allow_macro_instructions_);
+    fmov(fd, imm);
+  }
+  void Fmov(Register rd, FPRegister fn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    fmov(rd, fn);
+  }
+  void Fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fmul(fd, fn, fm);
+  }
+  void Fmsub(const FPRegister& fd,
+             const FPRegister& fn,
+             const FPRegister& fm,
+             const FPRegister& fa) {
+    ASSERT(allow_macro_instructions_);
+    fmsub(fd, fn, fm, fa);
+  }
+  void Fneg(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fneg(fd, fn);
+  }
+  void Frintn(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    frintn(fd, fn);
+  }
+  void Frintz(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    frintz(fd, fn);
+  }
+  void Fsqrt(const FPRegister& fd, const FPRegister& fn) {
+    ASSERT(allow_macro_instructions_);
+    fsqrt(fd, fn);
+  }
+  void Fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
+    ASSERT(allow_macro_instructions_);
+    fsub(fd, fn, fm);
+  }
+  void Hint(SystemHint code) {
+    ASSERT(allow_macro_instructions_);
+    hint(code);
+  }
+  void Hlt(int code) {
+    ASSERT(allow_macro_instructions_);
+    hlt(code);
+  }
+  void Ldnp(const CPURegister& rt,
+            const CPURegister& rt2,
+            const MemOperand& src) {
+    ASSERT(allow_macro_instructions_);
+    ldnp(rt, rt2, src);
+  }
+  void Ldp(const CPURegister& rt,
+           const CPURegister& rt2,
+           const MemOperand& src) {
+    ASSERT(allow_macro_instructions_);
+    ldp(rt, rt2, src);
+  }
+  void Ldpsw(const Register& rt, const Register& rt2, const MemOperand& src) {
+    ASSERT(allow_macro_instructions_);
+    ldpsw(rt, rt2, src);
+  }
+  void Ldr(const FPRegister& ft, double imm) {
+    ASSERT(allow_macro_instructions_);
+    ldr(ft, imm);
+  }
+  void Ldr(const Register& rt, uint64_t imm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    ldr(rt, imm);
+  }
+  void Lsl(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    lsl(rd, rn, shift);
+  }
+  void Lsl(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    lslv(rd, rn, rm);
+  }
+  void Lsr(const Register& rd, const Register& rn, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    lsr(rd, rn, shift);
+  }
+  void Lsr(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    lsrv(rd, rn, rm);
+  }
+  void Madd(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    madd(rd, rn, rm, ra);
+  }
+  void Mneg(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    mneg(rd, rn, rm);
+  }
+  void Mov(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    mov(rd, rn);
+  }
+  void Mrs(const Register& rt, SystemRegister sysreg) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    mrs(rt, sysreg);
+  }
+  void Msr(SystemRegister sysreg, const Register& rt) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    msr(sysreg, rt);
+  }
+  void Msub(const Register& rd,
+            const Register& rn,
+            const Register& rm,
+            const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    msub(rd, rn, rm, ra);
+  }
+  void Mul(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    mul(rd, rn, rm);
+  }
+  void Nop() {
+    ASSERT(allow_macro_instructions_);
+    nop();
+  }
+  void Rbit(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rbit(rd, rn);
+  }
+  void Ret(const Register& xn = lr) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xn.IsZero());
+    ret(xn);
+  }
+  void Rev(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rev(rd, rn);
+  }
+  void Rev16(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rev16(rd, rn);
+  }
+  void Rev32(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    rev32(rd, rn);
+  }
+  void Ror(const Register& rd, const Register& rs, unsigned shift) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rs.IsZero());
+    ror(rd, rs, shift);
+  }
+  void Ror(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    rorv(rd, rn, rm);
+  }
+  void Sbfiz(const Register& rd,
+             const Register& rn,
+             unsigned lsb,
+             unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sbfiz(rd, rn, lsb, width);
+  }
+  void Sbfx(const Register& rd,
+            const Register& rn,
+            unsigned lsb,
+            unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sbfx(rd, rn, lsb, width);
+  }
+  void Scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rn.IsZero());
+    scvtf(fd, rn, fbits);
+  }
+  void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    sdiv(rd, rn, rm);
+  }
+  void Smaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    smaddl(rd, rn, rm, ra);
+  }
+  void Smsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    smsubl(rd, rn, rm, ra);
+  }
+  void Smull(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    smull(rd, rn, rm);
+  }
+  void Smulh(const Register& xd, const Register& xn, const Register& xm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!xd.IsZero());
+    ASSERT(!xn.IsZero());
+    ASSERT(!xm.IsZero());
+    smulh(xd, xn, xm);
+  }
+  void Stnp(const CPURegister& rt,
+            const CPURegister& rt2,
+            const MemOperand& dst) {
+    ASSERT(allow_macro_instructions_);
+    stnp(rt, rt2, dst);
+  }
+  void Stp(const CPURegister& rt,
+           const CPURegister& rt2,
+           const MemOperand& dst) {
+    ASSERT(allow_macro_instructions_);
+    stp(rt, rt2, dst);
+  }
+  void Sxtb(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sxtb(rd, rn);
+  }
+  void Sxth(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sxth(rd, rn);
+  }
+  void Sxtw(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    sxtw(rd, rn);
+  }
+  void Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    tbnz(rt, bit_pos, label);
+  }
+  void Tbz(const Register& rt, unsigned bit_pos, Label* label) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rt.IsZero());
+    tbz(rt, bit_pos, label);
+  }
+  void Ubfiz(const Register& rd,
+             const Register& rn,
+             unsigned lsb,
+             unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ubfiz(rd, rn, lsb, width);
+  }
+  void Ubfx(const Register& rd,
+            const Register& rn,
+            unsigned lsb,
+            unsigned width) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ubfx(rd, rn, lsb, width);
+  }
+  void Ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rn.IsZero());
+    ucvtf(fd, rn, fbits);
+  }
+  void Udiv(const Register& rd, const Register& rn, const Register& rm) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    udiv(rd, rn, rm);
+  }
+  void Umaddl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    umaddl(rd, rn, rm, ra);
+  }
+  void Umsubl(const Register& rd,
+              const Register& rn,
+              const Register& rm,
+              const Register& ra) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    ASSERT(!rm.IsZero());
+    ASSERT(!ra.IsZero());
+    umsubl(rd, rn, rm, ra);
+  }
+  void Unreachable() {
+    ASSERT(allow_macro_instructions_);
+#ifdef USE_SIMULATOR
+    hlt(kUnreachableOpcode);
+#else
+    // Branch to 0 to generate a segfault.
+    // lr - kInstructionSize is the address of the offending instruction.
+    blr(xzr);
+#endif
+  }
+  void Uxtb(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    uxtb(rd, rn);
+  }
+  void Uxth(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    uxth(rd, rn);
+  }
+  void Uxtw(const Register& rd, const Register& rn) {
+    ASSERT(allow_macro_instructions_);
+    ASSERT(!rd.IsZero());
+    ASSERT(!rn.IsZero());
+    uxtw(rd, rn);
+  }
+
+  // Push the system stack pointer (sp) down to allow the same to be done to
+  // the current stack pointer (according to StackPointer()). This must be
+  // called _before_ accessing the memory.
+  //
+  // This is necessary when pushing or otherwise adding things to the stack, to
+  // satisfy the AAPCS64 constraint that the memory below the system stack
+  // pointer is not accessed.
+  //
+  // This method asserts that StackPointer() is not sp, since the call does
+  // not make sense in that context.
+  //
+  // TODO: This method can only accept values of 'space' that can be encoded in
+  // one instruction. Refer to the implementation for details.
+  void BumpSystemStackPointer(const Operand& space);
+
+#if DEBUG
+  void SetAllowMacroInstructions(bool value) {
+    allow_macro_instructions_ = value;
+  }
+
+  bool AllowMacroInstructions() const {
+    return allow_macro_instructions_;
+  }
+#endif
+
+  // Set the current stack pointer, but don't generate any code.
+  // Note that this does not directly affect LastStackPointer().
+  void SetStackPointer(const Register& stack_pointer) {
+    ASSERT(!AreAliased(stack_pointer, Tmp0(), Tmp1()));
+    sp_ = stack_pointer;
+  }
+
+  // Return the current stack pointer, as set by SetStackPointer.
+  const Register& StackPointer() const {
+    return sp_;
+  }
+
+  // Set the registers used internally by the MacroAssembler as scratch
+  // registers. These registers are used to implement behaviours which are not
+  // directly supported by A64, and where an intermediate result is required.
+  //
+  // Both tmp0 and tmp1 may be set to any X register except for xzr, sp,
+  // and StackPointer(). Also, they must not be the same register (though they
+  // may both be NoReg).
+  //
+  // It is valid to set either or both of these registers to NoReg if you don't
+  // want the MacroAssembler to use any scratch registers. In a debug build, the
+  // Assembler will assert that any registers it uses are valid. Be aware that
+  // this check is not present in release builds. If this is a problem, use the
+  // Assembler directly.
+  void SetScratchRegisters(const Register& tmp0, const Register& tmp1) {
+    ASSERT(!AreAliased(xzr, sp, tmp0, tmp1));
+    ASSERT(!AreAliased(StackPointer(), tmp0, tmp1));
+    tmp0_ = tmp0;
+    tmp1_ = tmp1;
+  }
+
+  const Register& Tmp0() const {
+    return tmp0_;
+  }
+
+  const Register& Tmp1() const {
+    return tmp1_;
+  }
+
+  void SetFPScratchRegister(const FPRegister& fptmp0) {
+    fptmp0_ = fptmp0;
+  }
+
+  const FPRegister& FPTmp0() const {
+    return fptmp0_;
+  }
+
+  const Register AppropriateTempFor(
+      const Register& target,
+      const CPURegister& forbidden = NoCPUReg) const {
+    Register candidate = forbidden.Is(Tmp0()) ? Tmp1() : Tmp0();
+    ASSERT(!candidate.Is(target));
+    return Register(candidate.code(), target.size());
+  }
+
+  const FPRegister AppropriateTempFor(
+      const FPRegister& target,
+      const CPURegister& forbidden = NoCPUReg) const {
+    USE(forbidden);
+    FPRegister candidate = FPTmp0();
+    ASSERT(!candidate.Is(forbidden));
+    ASSERT(!candidate.Is(target));
+    return FPRegister(candidate.code(), target.size());
+  }
+
+  // Like printf, but print at run-time from generated code.
+  //
+  // The caller must ensure that arguments for floating-point placeholders
+  // (such as %e, %f or %g) are FPRegisters, and that arguments for integer
+  // placeholders are Registers.
+  //
+  // A maximum of four arguments may be given to any single Printf call. The
+  // arguments must be of the same type, but they do not need to have the same
+  // size.
+  //
+  // The following registers cannot be printed:
+  //    Tmp0(), Tmp1(), StackPointer(), sp.
+  //
+  // This function automatically preserves caller-saved registers so that
+  // calling code can use Printf at any point without having to worry about
+  // corruption. The preservation mechanism generates a lot of code. If this is
+  // a problem, preserve the important registers manually and then call
+  // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
+  // implicitly preserved.
+  //
+  // This function assumes (and asserts) that the current stack pointer is
+  // callee-saved, not caller-saved. This is most likely the case anyway, as a
+  // caller-saved stack pointer doesn't make a lot of sense.
+  void Printf(const char * format,
+              const CPURegister& arg0 = NoCPUReg,
+              const CPURegister& arg1 = NoCPUReg,
+              const CPURegister& arg2 = NoCPUReg,
+              const CPURegister& arg3 = NoCPUReg);
+
+  // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
+  //
+  // The return code from the system printf call will be returned in x0.
+  void PrintfNoPreserve(const char * format,
+                        const CPURegister& arg0 = NoCPUReg,
+                        const CPURegister& arg1 = NoCPUReg,
+                        const CPURegister& arg2 = NoCPUReg,
+                        const CPURegister& arg3 = NoCPUReg);
+
+  // Trace control when running the debug simulator.
+  //
+  // For example:
+  //
+  // __ Trace(LOG_REGS, TRACE_ENABLE);
+  // Will add registers to the trace if it wasn't already the case.
+  //
+  // __ Trace(LOG_DISASM, TRACE_DISABLE);
+  // Will stop logging disassembly. It has no effect if the disassembly wasn't
+  // already being logged.
+  void Trace(TraceParameters parameters, TraceCommand command);
+
+  // Log the requested data independently of what is being traced.
+  //
+  // For example:
+  //
+  // __ Log(LOG_FLAGS)
+  // Will output the flags.
+  void Log(TraceParameters parameters);
+
+  // Enable or disable instrumentation when an Instrument visitor is attached to
+  // the simulator.
+  void EnableInstrumentation();
+  void DisableInstrumentation();
+
+  // Add a marker to the instrumentation data produced by an Instrument visitor.
+  // The name is a two character string that will be attached to the marker in
+  // the output data.
+  void AnnotateInstrumentation(const char* marker_name);
+
+ private:
+  // The actual Push and Pop implementations. These don't generate any code
+  // other than that required for the push or pop. This allows
+  // (Push|Pop)CPURegList to bundle together setup code for a large block of
+  // registers.
+  //
+  // Note that size is per register, and is specified in bytes.
+  void PushHelper(int count, int size,
+                  const CPURegister& src0, const CPURegister& src1,
+                  const CPURegister& src2, const CPURegister& src3);
+  void PopHelper(int count, int size,
+                 const CPURegister& dst0, const CPURegister& dst1,
+                 const CPURegister& dst2, const CPURegister& dst3);
+
+  // Perform necessary maintenance operations before a push or pop.
+  //
+  // Note that size is per register, and is specified in bytes.
+  void PrepareForPush(int count, int size);
+  void PrepareForPop(int count, int size);
+
+#if DEBUG
+  // Tell whether any of the macro instruction can be used. When false the
+  // MacroAssembler will assert if a method which can emit a variable number
+  // of instructions is called.
+  bool allow_macro_instructions_;
+#endif
+
+  // The register to use as a stack pointer for stack operations.
+  Register sp_;
+
+  // Scratch registers used internally by the MacroAssembler.
+  Register tmp0_;
+  Register tmp1_;
+  FPRegister fptmp0_;
+};
+
+
+// Use this scope when you need a one-to-one mapping between methods and
+// instructions. This scope prevents the MacroAssembler from being called and
+// literal pools from being emitted. It also asserts the number of instructions
+// emitted is what you specified when creating the scope.
+class InstructionAccurateScope {
+ public:
+  explicit InstructionAccurateScope(MacroAssembler* masm)
+      : masm_(masm), size_(0) {
+    masm_->BlockLiteralPool();
+#ifdef DEBUG
+    old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
+    masm_->SetAllowMacroInstructions(false);
+#endif
+  }
+
+  InstructionAccurateScope(MacroAssembler* masm, int count)
+      : masm_(masm), size_(count * kInstructionSize) {
+    masm_->BlockLiteralPool();
+#ifdef DEBUG
+    masm_->bind(&start_);
+    old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
+    masm_->SetAllowMacroInstructions(false);
+#endif
+  }
+
+  ~InstructionAccurateScope() {
+    masm_->ReleaseLiteralPool();
+#ifdef DEBUG
+    if (start_.IsBound()) {
+      ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_);
+    }
+    masm_->SetAllowMacroInstructions(old_allow_macro_instructions_);
+#endif
+  }
+
+ private:
+  MacroAssembler* masm_;
+  uint64_t size_;
+#ifdef DEBUG
+  Label start_;
+  bool old_allow_macro_instructions_;
+#endif
+};
+
+
+}  // namespace vixl
+
+#endif  // VIXL_A64_MACRO_ASSEMBLER_A64_H_
diff --git a/disas/libvixl/src/a64/simulator-a64.cc b/disas/libvixl/src/a64/simulator-a64.cc
new file mode 100644
index 0000000..f08e0ed
--- /dev/null
+++ b/disas/libvixl/src/a64/simulator-a64.cc
@@ -0,0 +1,2077 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <math.h>
+#include "a64/simulator-a64.h"
+
+namespace vixl {
+
+const Instruction* Simulator::kEndOfSimAddress = NULL;
+
+void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
+  int width = msb - lsb + 1;
+  ASSERT(is_uintn(width, bits) || is_intn(width, bits));
+
+  bits <<= lsb;
+  uint32_t mask = ((1 << width) - 1) << lsb;
+  ASSERT((mask & write_ignore_mask_) == 0);
+
+  value_ = (value_ & ~mask) | (bits & mask);
+}
+
+
+SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
+  switch (id) {
+    case NZCV:
+      return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
+    case FPCR:
+      return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
+    default:
+      UNREACHABLE();
+      return SimSystemRegister();
+  }
+}
+
+
+Simulator::Simulator(Decoder* decoder, FILE* stream) {
+  // Ensure shift operations act as the simulator expects.
+  ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
+  ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7FFFFFFF);
+
+  // Setup the decoder.
+  decoder_ = decoder;
+  decoder_->AppendVisitor(this);
+
+  ResetState();
+
+  // Allocate and setup the simulator stack.
+  stack_ = reinterpret_cast<byte*>(malloc(stack_size_));
+  stack_limit_ = stack_ + stack_protection_size_;
+  byte* tos = stack_ + stack_size_ - stack_protection_size_;
+  // The stack pointer must be 16 bytes aligned.
+  set_sp(reinterpret_cast<int64_t>(tos) & ~0xfUL);
+
+  stream_ = stream;
+  print_disasm_ = new PrintDisassembler(stream_);
+  coloured_trace_ = false;
+  disasm_trace_ = false;
+
+  // Set the sample period to 10, as the VIXL examples and tests are short.
+  instrumentation_ = new Instrument("vixl_stats.csv", 10);
+}
+
+
+void Simulator::ResetState() {
+  // Reset the system registers.
+  nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
+  fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
+
+  // Reset registers to 0.
+  pc_ = NULL;
+  pc_modified_ = false;
+  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
+    set_xreg(i, 0xbadbeef);
+  }
+  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
+    // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
+    set_dreg_bits(i, 0x7ff000007f800001UL);
+  }
+  // Returning to address 0 exits the Simulator.
+  set_lr(reinterpret_cast<int64_t>(kEndOfSimAddress));
+}
+
+
+Simulator::~Simulator() {
+  free(stack_);
+  // The decoder may outlive the simulator.
+  decoder_->RemoveVisitor(print_disasm_);
+  delete print_disasm_;
+
+  decoder_->RemoveVisitor(instrumentation_);
+  delete instrumentation_;
+}
+
+
+void Simulator::Run() {
+  while (pc_ != kEndOfSimAddress) {
+    ExecuteInstruction();
+  }
+}
+
+
+void Simulator::RunFrom(Instruction* first) {
+  pc_ = first;
+  pc_modified_ = false;
+  Run();
+}
+
+
+const char* Simulator::xreg_names[] = {
+"x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
+"x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
+"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+"x24", "x25", "x26", "x27", "x28", "x29", "lr",  "xzr", "sp"};
+
+
+const char* Simulator::wreg_names[] = {
+"w0",  "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",
+"w8",  "w9",  "w10", "w11", "w12", "w13", "w14", "w15",
+"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
+"w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr", "wsp"};
+
+const char* Simulator::sreg_names[] = {
+"s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
+"s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
+"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
+
+const char* Simulator::dreg_names[] = {
+"d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
+"d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
+"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
+
+const char* Simulator::vreg_names[] = {
+"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"};
+
+
+
+const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
+  ASSERT(code < kNumberOfRegisters);
+  // If the code represents the stack pointer, index the name after zr.
+  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
+    code = kZeroRegCode + 1;
+  }
+  return wreg_names[code];
+}
+
+
+const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
+  ASSERT(code < kNumberOfRegisters);
+  // If the code represents the stack pointer, index the name after zr.
+  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
+    code = kZeroRegCode + 1;
+  }
+  return xreg_names[code];
+}
+
+
+const char* Simulator::SRegNameForCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return sreg_names[code];
+}
+
+
+const char* Simulator::DRegNameForCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return dreg_names[code];
+}
+
+
+const char* Simulator::VRegNameForCode(unsigned code) {
+  ASSERT(code < kNumberOfFPRegisters);
+  return vreg_names[code];
+}
+
+
+// Helpers ---------------------------------------------------------------------
+int64_t Simulator::AddWithCarry(unsigned reg_size,
+                                bool set_flags,
+                                int64_t src1,
+                                int64_t src2,
+                                int64_t carry_in) {
+  ASSERT((carry_in == 0) || (carry_in == 1));
+  ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
+
+  uint64_t u1, u2;
+  int64_t result;
+  int64_t signed_sum = src1 + src2 + carry_in;
+
+  uint32_t N, Z, C, V;
+
+  if (reg_size == kWRegSize) {
+    u1 = static_cast<uint64_t>(src1) & kWRegMask;
+    u2 = static_cast<uint64_t>(src2) & kWRegMask;
+
+    result = signed_sum & kWRegMask;
+    // Compute the C flag by comparing the sum to the max unsigned integer.
+    C = ((kWMaxUInt - u1) < (u2 + carry_in)) ||
+        ((kWMaxUInt - u1 - carry_in) < u2);
+    // Overflow iff the sign bit is the same for the two inputs and different
+    // for the result.
+    int64_t s_src1 = src1 << (kXRegSize - kWRegSize);
+    int64_t s_src2 = src2 << (kXRegSize - kWRegSize);
+    int64_t s_result = result << (kXRegSize - kWRegSize);
+    V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0);
+
+  } else {
+    u1 = static_cast<uint64_t>(src1);
+    u2 = static_cast<uint64_t>(src2);
+
+    result = signed_sum;
+    // Compute the C flag by comparing the sum to the max unsigned integer.
+    C = ((kXMaxUInt - u1) < (u2 + carry_in)) ||
+        ((kXMaxUInt - u1 - carry_in) < u2);
+    // Overflow iff the sign bit is the same for the two inputs and different
+    // for the result.
+    V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
+  }
+
+  N = CalcNFlag(result, reg_size);
+  Z = CalcZFlag(result);
+
+  if (set_flags) {
+    nzcv().SetN(N);
+    nzcv().SetZ(Z);
+    nzcv().SetC(C);
+    nzcv().SetV(V);
+  }
+  return result;
+}
+
+
+int64_t Simulator::ShiftOperand(unsigned reg_size,
+                                int64_t value,
+                                Shift shift_type,
+                                unsigned amount) {
+  if (amount == 0) {
+    return value;
+  }
+  int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
+  switch (shift_type) {
+    case LSL:
+      return (value << amount) & mask;
+    case LSR:
+      return static_cast<uint64_t>(value) >> amount;
+    case ASR: {
+      // Shift used to restore the sign.
+      unsigned s_shift = kXRegSize - reg_size;
+      // Value with its sign restored.
+      int64_t s_value = (value << s_shift) >> s_shift;
+      return (s_value >> amount) & mask;
+    }
+    case ROR: {
+      if (reg_size == kWRegSize) {
+        value &= kWRegMask;
+      }
+      return (static_cast<uint64_t>(value) >> amount) |
+             ((value & ((1L << amount) - 1L)) << (reg_size - amount));
+    }
+    default:
+      UNIMPLEMENTED();
+      return 0;
+  }
+}
+
+
+int64_t Simulator::ExtendValue(unsigned reg_size,
+                               int64_t value,
+                               Extend extend_type,
+                               unsigned left_shift) {
+  switch (extend_type) {
+    case UXTB:
+      value &= kByteMask;
+      break;
+    case UXTH:
+      value &= kHalfWordMask;
+      break;
+    case UXTW:
+      value &= kWordMask;
+      break;
+    case SXTB:
+      value = (value << 56) >> 56;
+      break;
+    case SXTH:
+      value = (value << 48) >> 48;
+      break;
+    case SXTW:
+      value = (value << 32) >> 32;
+      break;
+    case UXTX:
+    case SXTX:
+      break;
+    default:
+      UNREACHABLE();
+  }
+  int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
+  return (value << left_shift) & mask;
+}
+
+
+void Simulator::FPCompare(double val0, double val1) {
+  AssertSupportedFPCR();
+
+  // TODO: This assumes that the C++ implementation handles comparisons in the
+  // way that we expect (as per AssertSupportedFPCR()).
+  if ((isnan(val0) != 0) || (isnan(val1) != 0)) {
+    nzcv().SetRawValue(FPUnorderedFlag);
+  } else if (val0 < val1) {
+    nzcv().SetRawValue(FPLessThanFlag);
+  } else if (val0 > val1) {
+    nzcv().SetRawValue(FPGreaterThanFlag);
+  } else if (val0 == val1) {
+    nzcv().SetRawValue(FPEqualFlag);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+
+void Simulator::PrintSystemRegisters(bool print_all) {
+  static bool first_run = true;
+
+  // Define some colour codes to use for the register dump.
+  // TODO: Find a more elegant way of defining these.
+  char const * const clr_normal     = (coloured_trace_) ? ("\033[m") : ("");
+  char const * const clr_flag_name  = (coloured_trace_) ? ("\033[1;30m") : ("");
+  char const * const clr_flag_value = (coloured_trace_) ? ("\033[1;37m") : ("");
+
+  static SimSystemRegister last_nzcv;
+  if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) {
+    fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
+            clr_flag_name,
+            clr_flag_value,
+            N(), Z(), C(), V(),
+            clr_normal);
+  }
+  last_nzcv = nzcv();
+
+  static SimSystemRegister last_fpcr;
+  if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) {
+    static const char * rmode[] = {
+      "0b00 (Round to Nearest)",
+      "0b01 (Round towards Plus Infinity)",
+      "0b10 (Round towards Minus Infinity)",
+      "0b11 (Round towards Zero)"
+    };
+    ASSERT(fpcr().RMode() <= (sizeof(rmode) / sizeof(rmode[0])));
+    fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
+            clr_flag_name,
+            clr_flag_value,
+            fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
+            clr_normal);
+  }
+  last_fpcr = fpcr();
+
+  first_run = false;
+}
+
+
+void Simulator::PrintRegisters(bool print_all_regs) {
+  static bool first_run = true;
+  static int64_t last_regs[kNumberOfRegisters];
+
+  // Define some colour codes to use for the register dump.
+  // TODO: Find a more elegant way of defining these.
+  char const * const clr_normal    = (coloured_trace_) ? ("\033[m") : ("");
+  char const * const clr_reg_name  = (coloured_trace_) ? ("\033[1;34m") : ("");
+  char const * const clr_reg_value = (coloured_trace_) ? ("\033[1;36m") : ("");
+
+  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
+    if (print_all_regs || first_run || (last_regs[i] != registers_[i].x)) {
+      fprintf(stream_,
+              "# %s%4s:%s 0x%016" PRIx64 "%s\n",
+              clr_reg_name,
+              XRegNameForCode(i, Reg31IsStackPointer),
+              clr_reg_value,
+              registers_[i].x,
+              clr_normal);
+    }
+    // Cache the new register value so the next run can detect any changes.
+    last_regs[i] = registers_[i].x;
+  }
+  first_run = false;
+}
+
+
+void Simulator::PrintFPRegisters(bool print_all_regs) {
+  static bool first_run = true;
+  static uint64_t last_regs[kNumberOfFPRegisters];
+
+  // Define some colour codes to use for the register dump.
+  // TODO: Find a more elegant way of defining these.
+  char const * const clr_normal    = (coloured_trace_) ? ("\033[m") : ("");
+  char const * const clr_reg_name  = (coloured_trace_) ? ("\033[1;33m") : ("");
+  char const * const clr_reg_value = (coloured_trace_) ? ("\033[1;35m") : ("");
+
+  // Print as many rows of registers as necessary, keeping each individual
+  // register in the same column each time (to make it easy to visually scan
+  // for changes).
+  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
+    if (print_all_regs || first_run ||
+        (last_regs[i] != double_to_rawbits(fpregisters_[i].d))) {
+      fprintf(stream_,
+              "# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
+              clr_reg_name,
+              VRegNameForCode(i),
+              clr_reg_value,
+              double_to_rawbits(fpregisters_[i].d),
+              clr_normal,
+              clr_reg_name,
+              DRegNameForCode(i),
+              clr_reg_value,
+              fpregisters_[i].d,
+              clr_reg_name,
+              SRegNameForCode(i),
+              clr_reg_value,
+              fpregisters_[i].s,
+              clr_normal);
+    }
+    // Cache the new register value so the next run can detect any changes.
+    last_regs[i] = double_to_rawbits(fpregisters_[i].d);
+  }
+  first_run = false;
+}
+
+
+void Simulator::PrintProcessorState() {
+  PrintSystemRegisters();
+  PrintRegisters();
+  PrintFPRegisters();
+}
+
+
+// Visitors---------------------------------------------------------------------
+
+void Simulator::VisitUnimplemented(Instruction* instr) {
+  printf("Unimplemented instruction at 0x%p: 0x%08" PRIx32 "\n",
+         reinterpret_cast<void*>(instr), instr->InstructionBits());
+  UNIMPLEMENTED();
+}
+
+
+void Simulator::VisitUnallocated(Instruction* instr) {
+  printf("Unallocated instruction at 0x%p: 0x%08" PRIx32 "\n",
+         reinterpret_cast<void*>(instr), instr->InstructionBits());
+  UNIMPLEMENTED();
+}
+
+
+void Simulator::VisitPCRelAddressing(Instruction* instr) {
+  switch (instr->Mask(PCRelAddressingMask)) {
+    case ADR:
+      set_reg(kXRegSize,
+              instr->Rd(),
+              reinterpret_cast<int64_t>(instr->ImmPCOffsetTarget()));
+      break;
+    case ADRP:  // Not implemented in the assembler.
+      UNIMPLEMENTED();
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitUnconditionalBranch(Instruction* instr) {
+  switch (instr->Mask(UnconditionalBranchMask)) {
+    case BL:
+      set_lr(reinterpret_cast<int64_t>(instr->NextInstruction()));
+      // Fall through.
+    case B:
+      set_pc(instr->ImmPCOffsetTarget());
+      break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitConditionalBranch(Instruction* instr) {
+  ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
+  if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
+    set_pc(instr->ImmPCOffsetTarget());
+  }
+}
+
+
+void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
+  Instruction* target = Instruction::Cast(xreg(instr->Rn()));
+
+  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
+    case BLR:
+      set_lr(reinterpret_cast<int64_t>(instr->NextInstruction()));
+      // Fall through.
+    case BR:
+    case RET: set_pc(target); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitTestBranch(Instruction* instr) {
+  unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
+                     instr->ImmTestBranchBit40();
+  bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
+  switch (instr->Mask(TestBranchMask)) {
+    case TBZ: break;
+    case TBNZ: take_branch = !take_branch; break;
+    default: UNIMPLEMENTED();
+  }
+  if (take_branch) {
+    set_pc(instr->ImmPCOffsetTarget());
+  }
+}
+
+
+void Simulator::VisitCompareBranch(Instruction* instr) {
+  unsigned rt = instr->Rt();
+  bool take_branch = false;
+  switch (instr->Mask(CompareBranchMask)) {
+    case CBZ_w: take_branch = (wreg(rt) == 0); break;
+    case CBZ_x: take_branch = (xreg(rt) == 0); break;
+    case CBNZ_w: take_branch = (wreg(rt) != 0); break;
+    case CBNZ_x: take_branch = (xreg(rt) != 0); break;
+    default: UNIMPLEMENTED();
+  }
+  if (take_branch) {
+    set_pc(instr->ImmPCOffsetTarget());
+  }
+}
+
+
+void Simulator::AddSubHelper(Instruction* instr, int64_t op2) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  bool set_flags = instr->FlagsUpdate();
+  int64_t new_val = 0;
+  Instr operation = instr->Mask(AddSubOpMask);
+
+  switch (operation) {
+    case ADD:
+    case ADDS: {
+      new_val = AddWithCarry(reg_size,
+                             set_flags,
+                             reg(reg_size, instr->Rn(), instr->RnMode()),
+                             op2);
+      break;
+    }
+    case SUB:
+    case SUBS: {
+      new_val = AddWithCarry(reg_size,
+                             set_flags,
+                             reg(reg_size, instr->Rn(), instr->RnMode()),
+                             ~op2,
+                             1);
+      break;
+    }
+    default: UNREACHABLE();
+  }
+
+  set_reg(reg_size, instr->Rd(), new_val, instr->RdMode());
+}
+
+
+void Simulator::VisitAddSubShifted(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op2 = ShiftOperand(reg_size,
+                             reg(reg_size, instr->Rm()),
+                             static_cast<Shift>(instr->ShiftDP()),
+                             instr->ImmDPShift());
+  AddSubHelper(instr, op2);
+}
+
+
+void Simulator::VisitAddSubImmediate(Instruction* instr) {
+  int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
+  AddSubHelper(instr, op2);
+}
+
+
+void Simulator::VisitAddSubExtended(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op2 = ExtendValue(reg_size,
+                            reg(reg_size, instr->Rm()),
+                            static_cast<Extend>(instr->ExtendMode()),
+                            instr->ImmExtendShift());
+  AddSubHelper(instr, op2);
+}
+
+
+void Simulator::VisitAddSubWithCarry(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op2 = reg(reg_size, instr->Rm());
+  int64_t new_val;
+
+  if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
+    op2 = ~op2;
+  }
+
+  new_val = AddWithCarry(reg_size,
+                         instr->FlagsUpdate(),
+                         reg(reg_size, instr->Rn()),
+                         op2,
+                         C());
+
+  set_reg(reg_size, instr->Rd(), new_val);
+}
+
+
+void Simulator::VisitLogicalShifted(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  Shift shift_type = static_cast<Shift>(instr->ShiftDP());
+  unsigned shift_amount = instr->ImmDPShift();
+  int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
+                             shift_amount);
+  if (instr->Mask(NOT) == NOT) {
+    op2 = ~op2;
+  }
+  LogicalHelper(instr, op2);
+}
+
+
+void Simulator::VisitLogicalImmediate(Instruction* instr) {
+  LogicalHelper(instr, instr->ImmLogical());
+}
+
+
+void Simulator::LogicalHelper(Instruction* instr, int64_t op2) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op1 = reg(reg_size, instr->Rn());
+  int64_t result = 0;
+  bool update_flags = false;
+
+  // Switch on the logical operation, stripping out the NOT bit, as it has a
+  // different meaning for logical immediate instructions.
+  switch (instr->Mask(LogicalOpMask & ~NOT)) {
+    case ANDS: update_flags = true;  // Fall through.
+    case AND: result = op1 & op2; break;
+    case ORR: result = op1 | op2; break;
+    case EOR: result = op1 ^ op2; break;
+    default:
+      UNIMPLEMENTED();
+  }
+
+  if (update_flags) {
+    nzcv().SetN(CalcNFlag(result, reg_size));
+    nzcv().SetZ(CalcZFlag(result));
+    nzcv().SetC(0);
+    nzcv().SetV(0);
+  }
+
+  set_reg(reg_size, instr->Rd(), result, instr->RdMode());
+}
+
+
+void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
+}
+
+
+void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
+  ConditionalCompareHelper(instr, instr->ImmCondCmp());
+}
+
+
+void Simulator::ConditionalCompareHelper(Instruction* instr, int64_t op2) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t op1 = reg(reg_size, instr->Rn());
+
+  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
+    // If the condition passes, set the status flags to the result of comparing
+    // the operands.
+    if (instr->Mask(ConditionalCompareMask) == CCMP) {
+      AddWithCarry(reg_size, true, op1, ~op2, 1);
+    } else {
+      ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
+      AddWithCarry(reg_size, true, op1, op2, 0);
+    }
+  } else {
+    // If the condition fails, set the status flags to the nzcv immediate.
+    nzcv().SetFlags(instr->Nzcv());
+  }
+}
+
+
+void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
+  int offset = instr->ImmLSUnsigned() << instr->SizeLS();
+  LoadStoreHelper(instr, offset, Offset);
+}
+
+
+void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
+  LoadStoreHelper(instr, instr->ImmLS(), Offset);
+}
+
+
+void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
+  LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
+}
+
+
+void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
+  LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
+}
+
+
+void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
+  Extend ext = static_cast<Extend>(instr->ExtendMode());
+  ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
+  unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
+
+  int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
+                               shift_amount);
+  LoadStoreHelper(instr, offset, Offset);
+}
+
+
+void Simulator::LoadStoreHelper(Instruction* instr,
+                                int64_t offset,
+                                AddrMode addrmode) {
+  unsigned srcdst = instr->Rt();
+  uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode);
+  int num_bytes = 1 << instr->SizeLS();
+
+  LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
+  switch (op) {
+    case LDRB_w:
+    case LDRH_w:
+    case LDR_w:
+    case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break;
+    case STRB_w:
+    case STRH_w:
+    case STR_w:
+    case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break;
+    case LDRSB_w: {
+      set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead8(address), SXTB));
+      break;
+    }
+    case LDRSB_x: {
+      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead8(address), SXTB));
+      break;
+    }
+    case LDRSH_w: {
+      set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead16(address), SXTH));
+      break;
+    }
+    case LDRSH_x: {
+      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead16(address), SXTH));
+      break;
+    }
+    case LDRSW_x: {
+      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
+      break;
+    }
+    case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break;
+    case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break;
+    case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break;
+    case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
+  LoadStorePairHelper(instr, Offset);
+}
+
+
+void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
+  LoadStorePairHelper(instr, PreIndex);
+}
+
+
+void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
+  LoadStorePairHelper(instr, PostIndex);
+}
+
+
+void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
+  LoadStorePairHelper(instr, Offset);
+}
+
+
+void Simulator::LoadStorePairHelper(Instruction* instr,
+                                    AddrMode addrmode) {
+  unsigned rt = instr->Rt();
+  unsigned rt2 = instr->Rt2();
+  int offset = instr->ImmLSPair() << instr->SizeLSPair();
+  uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode);
+
+  LoadStorePairOp op =
+    static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
+
+  // 'rt' and 'rt2' can only be aliased for stores.
+  ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
+
+  switch (op) {
+    case LDP_w: {
+      set_wreg(rt, MemoryRead32(address));
+      set_wreg(rt2, MemoryRead32(address + kWRegSizeInBytes));
+      break;
+    }
+    case LDP_s: {
+      set_sreg(rt, MemoryReadFP32(address));
+      set_sreg(rt2, MemoryReadFP32(address + kSRegSizeInBytes));
+      break;
+    }
+    case LDP_x: {
+      set_xreg(rt, MemoryRead64(address));
+      set_xreg(rt2, MemoryRead64(address + kXRegSizeInBytes));
+      break;
+    }
+    case LDP_d: {
+      set_dreg(rt, MemoryReadFP64(address));
+      set_dreg(rt2, MemoryReadFP64(address + kDRegSizeInBytes));
+      break;
+    }
+    case LDPSW_x: {
+      set_xreg(rt, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
+      set_xreg(rt2, ExtendValue(kXRegSize,
+               MemoryRead32(address + kWRegSizeInBytes), SXTW));
+      break;
+    }
+    case STP_w: {
+      MemoryWrite32(address, wreg(rt));
+      MemoryWrite32(address + kWRegSizeInBytes, wreg(rt2));
+      break;
+    }
+    case STP_s: {
+      MemoryWriteFP32(address, sreg(rt));
+      MemoryWriteFP32(address + kSRegSizeInBytes, sreg(rt2));
+      break;
+    }
+    case STP_x: {
+      MemoryWrite64(address, xreg(rt));
+      MemoryWrite64(address + kXRegSizeInBytes, xreg(rt2));
+      break;
+    }
+    case STP_d: {
+      MemoryWriteFP64(address, dreg(rt));
+      MemoryWriteFP64(address + kDRegSizeInBytes, dreg(rt2));
+      break;
+    }
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitLoadLiteral(Instruction* instr) {
+  uint8_t* address = instr->LiteralAddress();
+  unsigned rt = instr->Rt();
+
+  switch (instr->Mask(LoadLiteralMask)) {
+    case LDR_w_lit: set_wreg(rt, MemoryRead32(address));  break;
+    case LDR_x_lit: set_xreg(rt, MemoryRead64(address));  break;
+    case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address));  break;
+    case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address));  break;
+    default: UNREACHABLE();
+  }
+}
+
+
+uint8_t* Simulator::AddressModeHelper(unsigned addr_reg,
+                                      int64_t offset,
+                                      AddrMode addrmode) {
+  uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
+  ASSERT((sizeof(uintptr_t) == kXRegSizeInBytes) ||
+         (address < 0x100000000UL));
+  if ((addr_reg == 31) && ((address % 16) != 0)) {
+    // When the base register is SP the stack pointer is required to be
+    // quadword aligned prior to the address calculation and write-backs.
+    // Misalignment will cause a stack alignment fault.
+    ALIGNMENT_EXCEPTION();
+  }
+  if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
+    ASSERT(offset != 0);
+    set_xreg(addr_reg, address + offset, Reg31IsStackPointer);
+  }
+
+  if ((addrmode == Offset) || (addrmode == PreIndex)) {
+    address += offset;
+  }
+
+  return reinterpret_cast<uint8_t*>(address);
+}
+
+
+uint64_t Simulator::MemoryRead(const uint8_t* address, unsigned num_bytes) {
+  ASSERT(address != NULL);
+  ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
+  uint64_t read = 0;
+  memcpy(&read, address, num_bytes);
+  return read;
+}
+
+
+uint8_t Simulator::MemoryRead8(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint8_t));
+}
+
+
+uint16_t Simulator::MemoryRead16(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint16_t));
+}
+
+
+uint32_t Simulator::MemoryRead32(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint32_t));
+}
+
+
+float Simulator::MemoryReadFP32(uint8_t* address) {
+  return rawbits_to_float(MemoryRead32(address));
+}
+
+
+uint64_t Simulator::MemoryRead64(uint8_t* address) {
+  return MemoryRead(address, sizeof(uint64_t));
+}
+
+
+double Simulator::MemoryReadFP64(uint8_t* address) {
+  return rawbits_to_double(MemoryRead64(address));
+}
+
+
+void Simulator::MemoryWrite(uint8_t* address,
+                            uint64_t value,
+                            unsigned num_bytes) {
+  ASSERT(address != NULL);
+  ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
+  memcpy(address, &value, num_bytes);
+}
+
+
+void Simulator::MemoryWrite32(uint8_t* address, uint32_t value) {
+  MemoryWrite(address, value, sizeof(uint32_t));
+}
+
+
+void Simulator::MemoryWriteFP32(uint8_t* address, float value) {
+  MemoryWrite32(address, float_to_rawbits(value));
+}
+
+
+void Simulator::MemoryWrite64(uint8_t* address, uint64_t value) {
+  MemoryWrite(address, value, sizeof(uint64_t));
+}
+
+
+void Simulator::MemoryWriteFP64(uint8_t* address, double value) {
+  MemoryWrite64(address, double_to_rawbits(value));
+}
+
+
+void Simulator::VisitMoveWideImmediate(Instruction* instr) {
+  MoveWideImmediateOp mov_op =
+    static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
+  int64_t new_xn_val = 0;
+
+  bool is_64_bits = instr->SixtyFourBits() == 1;
+  // Shift is limited for W operations.
+  ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
+
+  // Get the shifted immediate.
+  int64_t shift = instr->ShiftMoveWide() * 16;
+  int64_t shifted_imm16 = instr->ImmMoveWide() << shift;
+
+  // Compute the new value.
+  switch (mov_op) {
+    case MOVN_w:
+    case MOVN_x: {
+        new_xn_val = ~shifted_imm16;
+        if (!is_64_bits) new_xn_val &= kWRegMask;
+      break;
+    }
+    case MOVK_w:
+    case MOVK_x: {
+        unsigned reg_code = instr->Rd();
+        int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
+                                         : wreg(reg_code);
+        new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
+      break;
+    }
+    case MOVZ_w:
+    case MOVZ_x: {
+        new_xn_val = shifted_imm16;
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  // Update the destination register.
+  set_xreg(instr->Rd(), new_xn_val);
+}
+
+
+void Simulator::VisitConditionalSelect(Instruction* instr) {
+  uint64_t new_val = xreg(instr->Rn());
+
+  if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
+    new_val = xreg(instr->Rm());
+    switch (instr->Mask(ConditionalSelectMask)) {
+      case CSEL_w:
+      case CSEL_x: break;
+      case CSINC_w:
+      case CSINC_x: new_val++; break;
+      case CSINV_w:
+      case CSINV_x: new_val = ~new_val; break;
+      case CSNEG_w:
+      case CSNEG_x: new_val = -new_val; break;
+      default: UNIMPLEMENTED();
+    }
+  }
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  set_reg(reg_size, instr->Rd(), new_val);
+}
+
+
+void Simulator::VisitDataProcessing1Source(Instruction* instr) {
+  unsigned dst = instr->Rd();
+  unsigned src = instr->Rn();
+
+  switch (instr->Mask(DataProcessing1SourceMask)) {
+    case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSize)); break;
+    case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSize)); break;
+    case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break;
+    case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break;
+    case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break;
+    case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break;
+    case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break;
+    case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSize)); break;
+    case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSize)); break;
+    case CLS_w: {
+      set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSize));
+      break;
+    }
+    case CLS_x: {
+      set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSize));
+      break;
+    }
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+uint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) {
+  ASSERT((num_bits == kWRegSize) || (num_bits == kXRegSize));
+  uint64_t result = 0;
+  for (unsigned i = 0; i < num_bits; i++) {
+    result = (result << 1) | (value & 1);
+    value >>= 1;
+  }
+  return result;
+}
+
+
+uint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) {
+  // Split the 64-bit value into an 8-bit array, where b[0] is the least
+  // significant byte, and b[7] is the most significant.
+  uint8_t bytes[8];
+  uint64_t mask = 0xff00000000000000UL;
+  for (int i = 7; i >= 0; i--) {
+    bytes[i] = (value & mask) >> (i * 8);
+    mask >>= 8;
+  }
+
+  // Permutation tables for REV instructions.
+  //  permute_table[Reverse16] is used by REV16_x, REV16_w
+  //  permute_table[Reverse32] is used by REV32_x, REV_w
+  //  permute_table[Reverse64] is used by REV_x
+  ASSERT((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2));
+  static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1},
+                                               {4, 5, 6, 7, 0, 1, 2, 3},
+                                               {0, 1, 2, 3, 4, 5, 6, 7} };
+  uint64_t result = 0;
+  for (int i = 0; i < 8; i++) {
+    result <<= 8;
+    result |= bytes[permute_table[mode][i]];
+  }
+  return result;
+}
+
+
+void Simulator::VisitDataProcessing2Source(Instruction* instr) {
+  Shift shift_op = NO_SHIFT;
+  int64_t result = 0;
+  switch (instr->Mask(DataProcessing2SourceMask)) {
+    case SDIV_w: result = wreg(instr->Rn()) / wreg(instr->Rm()); break;
+    case SDIV_x: result = xreg(instr->Rn()) / xreg(instr->Rm()); break;
+    case UDIV_w: {
+      uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
+      uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
+      result = rn / rm;
+      break;
+    }
+    case UDIV_x: {
+      uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
+      uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
+      result = rn / rm;
+      break;
+    }
+    case LSLV_w:
+    case LSLV_x: shift_op = LSL; break;
+    case LSRV_w:
+    case LSRV_x: shift_op = LSR; break;
+    case ASRV_w:
+    case ASRV_x: shift_op = ASR; break;
+    case RORV_w:
+    case RORV_x: shift_op = ROR; break;
+    default: UNIMPLEMENTED();
+  }
+
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  if (shift_op != NO_SHIFT) {
+    // Shift distance encoded in the least-significant five/six bits of the
+    // register.
+    int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
+    unsigned shift = wreg(instr->Rm()) & mask;
+    result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
+                          shift);
+  }
+  set_reg(reg_size, instr->Rd(), result);
+}
+
+
+// The algorithm used is adapted from the one described in section 8.2 of
+//   Hacker's Delight, by Henry S. Warren, Jr.
+// It assumes that a right shift on a signed integer is an arithmetic shift.
+static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
+  uint64_t u0, v0, w0;
+  int64_t u1, v1, w1, w2, t;
+
+  u0 = u & 0xffffffffL;
+  u1 = u >> 32;
+  v0 = v & 0xffffffffL;
+  v1 = v >> 32;
+
+  w0 = u0 * v0;
+  t = u1 * v0 + (w0 >> 32);
+  w1 = t & 0xffffffffL;
+  w2 = t >> 32;
+  w1 = u0 * v1 + w1;
+
+  return u1 * v1 + w2 + (w1 >> 32);
+}
+
+
+void Simulator::VisitDataProcessing3Source(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+
+  int64_t result = 0;
+  uint64_t rn;
+  uint64_t rm;
+  switch (instr->Mask(DataProcessing3SourceMask)) {
+    case MADD_w:
+    case MADD_x:
+      result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
+      break;
+    case MSUB_w:
+    case MSUB_x:
+      result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
+      break;
+    case SMADDL_x:
+      result = xreg(instr->Ra()) + (wreg(instr->Rn()) * wreg(instr->Rm()));
+      break;
+    case SMSUBL_x:
+      result = xreg(instr->Ra()) - (wreg(instr->Rn()) * wreg(instr->Rm()));
+      break;
+    case UMADDL_x:
+      rn = static_cast<uint32_t>(wreg(instr->Rn()));
+      rm = static_cast<uint32_t>(wreg(instr->Rm()));
+      result = xreg(instr->Ra()) + (rn * rm);
+      break;
+    case UMSUBL_x:
+      rn = static_cast<uint32_t>(wreg(instr->Rn()));
+      rm = static_cast<uint32_t>(wreg(instr->Rm()));
+      result = xreg(instr->Ra()) - (rn * rm);
+      break;
+    case SMULH_x:
+      result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
+      break;
+    default: UNIMPLEMENTED();
+  }
+  set_reg(reg_size, instr->Rd(), result);
+}
+
+
+void Simulator::VisitBitfield(Instruction* instr) {
+  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
+  int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
+  int64_t R = instr->ImmR();
+  int64_t S = instr->ImmS();
+  int64_t diff = S - R;
+  int64_t mask;
+  if (diff >= 0) {
+    mask = diff < reg_size - 1 ? (1L << (diff + 1)) - 1
+                               : reg_mask;
+  } else {
+    mask = ((1L << (S + 1)) - 1);
+    mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
+    diff += reg_size;
+  }
+
+  // inzero indicates if the extracted bitfield is inserted into the
+  // destination register value or in zero.
+  // If extend is true, extend the sign of the extracted bitfield.
+  bool inzero = false;
+  bool extend = false;
+  switch (instr->Mask(BitfieldMask)) {
+    case BFM_x:
+    case BFM_w:
+      break;
+    case SBFM_x:
+    case SBFM_w:
+      inzero = true;
+      extend = true;
+      break;
+    case UBFM_x:
+    case UBFM_w:
+      inzero = true;
+      break;
+    default:
+      UNIMPLEMENTED();
+  }
+
+  int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
+  int64_t src = reg(reg_size, instr->Rn());
+  // Rotate source bitfield into place.
+  int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
+  // Determine the sign extension.
+  int64_t topbits = ((1L << (reg_size - diff - 1)) - 1) << (diff + 1);
+  int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
+
+  // Merge sign extension, dest/zero and bitfield.
+  result = signbits | (result & mask) | (dst & ~mask);
+
+  set_reg(reg_size, instr->Rd(), result);
+}
+
+
+void Simulator::VisitExtract(Instruction* instr) {
+  unsigned lsb = instr->ImmS();
+  unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
+                                                    : kWRegSize;
+  set_reg(reg_size,
+          instr->Rd(),
+          (static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb) |
+          (reg(reg_size, instr->Rn()) << (reg_size - lsb)));
+}
+
+
+void Simulator::VisitFPImmediate(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned dest = instr->Rd();
+  switch (instr->Mask(FPImmediateMask)) {
+    case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
+    case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitFPIntegerConvert(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned dst = instr->Rd();
+  unsigned src = instr->Rn();
+
+  FPRounding round = RMode();
+
+  switch (instr->Mask(FPIntegerConvertMask)) {
+    case FCVTMS_ws:
+      set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMS_xs:
+      set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMS_wd:
+      set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMS_xd:
+      set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_ws:
+      set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_xs:
+      set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_wd:
+      set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTMU_xd:
+      set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
+      break;
+    case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
+    case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
+    case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
+    case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
+    case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
+    case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
+    case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
+    case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
+    case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
+    case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
+    case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
+    case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
+    case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
+    case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
+    case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
+    case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
+    case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
+    case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
+    case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
+    case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
+
+    // A 32-bit input can be handled in the same way as a 64-bit input, since
+    // the sign- or zero-extension will not affect the conversion.
+    case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
+    case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
+    case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
+    case UCVTF_dw: {
+      set_dreg(dst, UFixedToDouble(static_cast<uint32_t>(wreg(src)), 0, round));
+      break;
+    }
+    case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
+    case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
+    case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
+    case UCVTF_sw: {
+      set_sreg(dst, UFixedToFloat(static_cast<uint32_t>(wreg(src)), 0, round));
+      break;
+    }
+
+    default: UNREACHABLE();
+  }
+}
+
+
+void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned dst = instr->Rd();
+  unsigned src = instr->Rn();
+  int fbits = 64 - instr->FPScale();
+
+  FPRounding round = RMode();
+
+  switch (instr->Mask(FPFixedPointConvertMask)) {
+    // A 32-bit input can be handled in the same way as a 64-bit input, since
+    // the sign- or zero-extension will not affect the conversion.
+    case SCVTF_dx_fixed:
+      set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
+      break;
+    case SCVTF_dw_fixed:
+      set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
+      break;
+    case UCVTF_dx_fixed:
+      set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
+      break;
+    case UCVTF_dw_fixed: {
+      set_dreg(dst,
+               UFixedToDouble(static_cast<uint32_t>(wreg(src)), fbits, round));
+      break;
+    }
+    case SCVTF_sx_fixed:
+      set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
+      break;
+    case SCVTF_sw_fixed:
+      set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
+      break;
+    case UCVTF_sx_fixed:
+      set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
+      break;
+    case UCVTF_sw_fixed: {
+      set_sreg(dst,
+               UFixedToFloat(static_cast<uint32_t>(wreg(src)), fbits, round));
+      break;
+    }
+    default: UNREACHABLE();
+  }
+}
+
+
+int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kWMaxInt) {
+    return kWMaxInt;
+  } else if (value < kWMinInt) {
+    return kWMinInt;
+  }
+  return isnan(value) ? 0 : static_cast<int32_t>(value);
+}
+
+
+int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kXMaxInt) {
+    return kXMaxInt;
+  } else if (value < kXMinInt) {
+    return kXMinInt;
+  }
+  return isnan(value) ? 0 : static_cast<int64_t>(value);
+}
+
+
+uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kWMaxUInt) {
+    return kWMaxUInt;
+  } else if (value < 0.0) {
+    return 0;
+  }
+  return isnan(value) ? 0 : static_cast<uint32_t>(value);
+}
+
+
+uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
+  value = FPRoundInt(value, rmode);
+  if (value >= kXMaxUInt) {
+    return kXMaxUInt;
+  } else if (value < 0.0) {
+    return 0;
+  }
+  return isnan(value) ? 0 : static_cast<uint64_t>(value);
+}
+
+
+void Simulator::VisitFPCompare(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
+  double fn_val = fpreg(reg_size, instr->Rn());
+
+  switch (instr->Mask(FPCompareMask)) {
+    case FCMP_s:
+    case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
+    case FCMP_s_zero:
+    case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPConditionalCompare(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  switch (instr->Mask(FPConditionalCompareMask)) {
+    case FCCMP_s:
+    case FCCMP_d: {
+      if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
+        // If the condition passes, set the status flags to the result of
+        // comparing the operands.
+        unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
+        FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
+      } else {
+        // If the condition fails, set the status flags to the nzcv immediate.
+        nzcv().SetFlags(instr->Nzcv());
+      }
+      break;
+    }
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPConditionalSelect(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
+
+  double selected_val;
+  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
+    selected_val = fpreg(reg_size, instr->Rn());
+  } else {
+    selected_val = fpreg(reg_size, instr->Rm());
+  }
+
+  switch (instr->Mask(FPConditionalSelectMask)) {
+    case FCSEL_s:
+    case FCSEL_d: set_fpreg(reg_size, instr->Rd(), selected_val); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned fd = instr->Rd();
+  unsigned fn = instr->Rn();
+
+  switch (instr->Mask(FPDataProcessing1SourceMask)) {
+    case FMOV_s: set_sreg(fd, sreg(fn)); break;
+    case FMOV_d: set_dreg(fd, dreg(fn)); break;
+    case FABS_s: set_sreg(fd, fabs(sreg(fn))); break;
+    case FABS_d: set_dreg(fd, fabs(dreg(fn))); break;
+    case FNEG_s: set_sreg(fd, -sreg(fn)); break;
+    case FNEG_d: set_dreg(fd, -dreg(fn)); break;
+    case FSQRT_s: set_sreg(fd, sqrt(sreg(fn))); break;
+    case FSQRT_d: set_dreg(fd, sqrt(dreg(fn))); break;
+    case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
+    case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
+    case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
+    case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
+    case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
+    case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+// Assemble the specified IEEE-754 components into the target type and apply
+// appropriate rounding.
+//  sign:     0 = positive, 1 = negative
+//  exponent: Unbiased IEEE-754 exponent.
+//  mantissa: The mantissa of the input. The top bit (which is not encoded for
+//            normal IEEE-754 values) must not be omitted. This bit has the
+//            value 'pow(2, exponent)'.
+//
+// The input value is assumed to be a normalized value. That is, the input may
+// not be infinity or NaN. If the source value is subnormal, it must be
+// normalized before calling this function such that the highest set bit in the
+// mantissa has the value 'pow(2, exponent)'.
+//
+// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
+// calling a templated FPRound.
+template <class T, int ebits, int mbits>
+static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
+                 FPRounding round_mode) {
+  ASSERT((sign == 0) || (sign == 1));
+
+  // Only the FPTieEven rounding mode is implemented.
+  ASSERT(round_mode == FPTieEven);
+  USE(round_mode);
+
+  // Rounding can promote subnormals to normals, and normals to infinities. For
+  // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
+  // encodable as a float, but rounding based on the low-order mantissa bits
+  // could make it overflow. With ties-to-even rounding, this value would become
+  // an infinity.
+
+  // ---- Rounding Method ----
+  //
+  // The exponent is irrelevant in the rounding operation, so we treat the
+  // lowest-order bit that will fit into the result ('onebit') as having
+  // the value '1'. Similarly, the highest-order bit that won't fit into
+  // the result ('halfbit') has the value '0.5'. The 'point' sits between
+  // 'onebit' and 'halfbit':
+  //
+  //            These bits fit into the result.
+  //               |---------------------|
+  //  mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+  //                                     ||
+  //                                    / |
+  //                                   /  halfbit
+  //                               onebit
+  //
+  // For subnormal outputs, the range of representable bits is smaller and
+  // the position of onebit and halfbit depends on the exponent of the
+  // input, but the method is otherwise similar.
+  //
+  //   onebit(frac)
+  //     |
+  //     | halfbit(frac)          halfbit(adjusted)
+  //     | /                      /
+  //     | |                      |
+  //  0b00.0 (exact)      -> 0b00.0 (exact)                    -> 0b00
+  //  0b00.0...           -> 0b00.0...                         -> 0b00
+  //  0b00.1 (exact)      -> 0b00.0111..111                    -> 0b00
+  //  0b00.1...           -> 0b00.1...                         -> 0b01
+  //  0b01.0 (exact)      -> 0b01.0 (exact)                    -> 0b01
+  //  0b01.0...           -> 0b01.0...                         -> 0b01
+  //  0b01.1 (exact)      -> 0b01.1 (exact)                    -> 0b10
+  //  0b01.1...           -> 0b01.1...                         -> 0b10
+  //  0b10.0 (exact)      -> 0b10.0 (exact)                    -> 0b10
+  //  0b10.0...           -> 0b10.0...                         -> 0b10
+  //  0b10.1 (exact)      -> 0b10.0111..111                    -> 0b10
+  //  0b10.1...           -> 0b10.1...                         -> 0b11
+  //  0b11.0 (exact)      -> 0b11.0 (exact)                    -> 0b11
+  //  ...                   /             |                      /   |
+  //                       /              |                     /    |
+  //                                                           /     |
+  // adjusted = frac - (halfbit(mantissa) & ~onebit(frac));   /      |
+  //
+  //                   mantissa = (mantissa >> shift) + halfbit(adjusted);
+
+  static const int mantissa_offset = 0;
+  static const int exponent_offset = mantissa_offset + mbits;
+  static const int sign_offset = exponent_offset + ebits;
+  ASSERT(sign_offset == (sizeof(T) * 8 - 1));
+
+  // Bail out early for zero inputs.
+  if (mantissa == 0) {
+    return sign << sign_offset;
+  }
+
+  // If all bits in the exponent are set, the value is infinite or NaN.
+  // This is true for all binary IEEE-754 formats.
+  static const int infinite_exponent = (1 << ebits) - 1;
+  static const int max_normal_exponent = infinite_exponent - 1;
+
+  // Apply the exponent bias to encode it for the result. Doing this early makes
+  // it easy to detect values that will be infinite or subnormal.
+  exponent += max_normal_exponent >> 1;
+
+  if (exponent > max_normal_exponent) {
+    // Overflow: The input is too large for the result type to represent. The
+    // FPTieEven rounding mode handles overflows using infinities.
+    exponent = infinite_exponent;
+    mantissa = 0;
+    return (sign << sign_offset) |
+           (exponent << exponent_offset) |
+           (mantissa << mantissa_offset);
+  }
+
+  // Calculate the shift required to move the top mantissa bit to the proper
+  // place in the destination type.
+  const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
+  int shift = highest_significant_bit - mbits;
+
+  if (exponent <= 0) {
+    // The output will be subnormal (before rounding).
+
+    // For subnormal outputs, the shift must be adjusted by the exponent. The +1
+    // is necessary because the exponent of a subnormal value (encoded as 0) is
+    // the same as the exponent of the smallest normal value (encoded as 1).
+    shift += -exponent + 1;
+
+    // Handle inputs that would produce a zero output.
+    //
+    // Shifts higher than highest_significant_bit+1 will always produce a zero
+    // result. A shift of exactly highest_significant_bit+1 might produce a
+    // non-zero result after rounding.
+    if (shift > (highest_significant_bit + 1)) {
+      // The result will always be +/-0.0.
+      return sign << sign_offset;
+    }
+
+    // Properly encode the exponent for a subnormal output.
+    exponent = 0;
+  } else {
+    // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
+    // normal values.
+    mantissa &= ~(1UL << highest_significant_bit);
+  }
+
+  if (shift > 0) {
+    // We have to shift the mantissa to the right. Some precision is lost, so we
+    // need to apply rounding.
+    uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
+    uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
+    uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
+    T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
+
+    T result = (sign << sign_offset) |
+               (exponent << exponent_offset) |
+               ((mantissa >> shift) << mantissa_offset);
+
+    // A very large mantissa can overflow during rounding. If this happens, the
+    // exponent should be incremented and the mantissa set to 1.0 (encoded as
+    // 0). Applying halfbit_adjusted after assembling the float has the nice
+    // side-effect that this case is handled for free.
+    //
+    // This also handles cases where a very large finite value overflows to
+    // infinity, or where a very large subnormal value overflows to become
+    // normal.
+    return result + halfbit_adjusted;
+  } else {
+    // We have to shift the mantissa to the left (or not at all). The input
+    // mantissa is exactly representable in the output mantissa, so apply no
+    // rounding correction.
+    return (sign << sign_offset) |
+           (exponent << exponent_offset) |
+           ((mantissa << -shift) << mantissa_offset);
+  }
+}
+
+
+// See FPRound for a description of this function.
+static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
+                                     uint64_t mantissa, FPRounding round_mode) {
+  int64_t bits =
+      FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
+                                                                 exponent,
+                                                                 mantissa,
+                                                                 round_mode);
+  return rawbits_to_double(bits);
+}
+
+
+// See FPRound for a description of this function.
+static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
+                                   uint64_t mantissa, FPRounding round_mode) {
+  int32_t bits =
+      FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
+                                                               exponent,
+                                                               mantissa,
+                                                               round_mode);
+  return rawbits_to_float(bits);
+}
+
+
+double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
+  if (src >= 0) {
+    return UFixedToDouble(src, fbits, round);
+  } else {
+    // This works for all negative values, including INT64_MIN.
+    return -UFixedToDouble(-src, fbits, round);
+  }
+}
+
+
+double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
+  // An input of 0 is a special case because the result is effectively
+  // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
+  if (src == 0) {
+    return 0.0;
+  }
+
+  // Calculate the exponent. The highest significant bit will have the value
+  // 2^exponent.
+  const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
+  const int64_t exponent = highest_significant_bit - fbits;
+
+  return FPRoundToDouble(0, exponent, src, round);
+}
+
+
+float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
+  if (src >= 0) {
+    return UFixedToFloat(src, fbits, round);
+  } else {
+    // This works for all negative values, including INT64_MIN.
+    return -UFixedToFloat(-src, fbits, round);
+  }
+}
+
+
+float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
+  // An input of 0 is a special case because the result is effectively
+  // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
+  if (src == 0) {
+    return 0.0f;
+  }
+
+  // Calculate the exponent. The highest significant bit will have the value
+  // 2^exponent.
+  const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
+  const int32_t exponent = highest_significant_bit - fbits;
+
+  return FPRoundToFloat(0, exponent, src, round);
+}
+
+
+double Simulator::FPRoundInt(double value, FPRounding round_mode) {
+  if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
+      (value == kFP64NegativeInfinity) || isnan(value)) {
+    return value;
+  }
+
+  double int_result = floor(value);
+  double error = value - int_result;
+  switch (round_mode) {
+    case FPTieEven: {
+      // If the error is greater than 0.5, or is equal to 0.5 and the integer
+      // result is odd, round up.
+      if ((error > 0.5) ||
+          ((error == 0.5) && (fmod(int_result, 2) != 0))) {
+        int_result++;
+      }
+      break;
+    }
+    case FPZero: {
+      // If value>0 then we take floor(value)
+      // otherwise, ceil(value).
+      if (value < 0) {
+         int_result = ceil(value);
+      }
+      break;
+    }
+    case FPNegativeInfinity: {
+      // We always use floor(value).
+      break;
+    }
+    default: UNIMPLEMENTED();
+  }
+  return int_result;
+}
+
+
+double Simulator::FPToDouble(float value) {
+  switch (fpclassify(value)) {
+    case FP_NAN: {
+      // Convert NaNs as the processor would, assuming that FPCR.DN (default
+      // NaN) is not set:
+      //  - The sign is propagated.
+      //  - The payload (mantissa) is transferred entirely, except that the top
+      //    bit is forced to '1', making the result a quiet NaN. The unused
+      //    (low-order) payload bits are set to 0.
+      uint32_t raw = float_to_rawbits(value);
+
+      uint64_t sign = raw >> 31;
+      uint64_t exponent = (1 << 11) - 1;
+      uint64_t payload = unsigned_bitextract_64(21, 0, raw);
+      payload <<= (52 - 23);  // The unused low-order bits should be 0.
+      payload |= (1L << 51);  // Force a quiet NaN.
+
+      return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
+    }
+
+    case FP_ZERO:
+    case FP_NORMAL:
+    case FP_SUBNORMAL:
+    case FP_INFINITE: {
+      // All other inputs are preserved in a standard cast, because every value
+      // representable using an IEEE-754 float is also representable using an
+      // IEEE-754 double.
+      return static_cast<double>(value);
+    }
+  }
+
+  UNREACHABLE();
+  return static_cast<double>(value);
+}
+
+
+float Simulator::FPToFloat(double value, FPRounding round_mode) {
+  // Only the FPTieEven rounding mode is implemented.
+  ASSERT(round_mode == FPTieEven);
+  USE(round_mode);
+
+  switch (fpclassify(value)) {
+    case FP_NAN: {
+      // Convert NaNs as the processor would, assuming that FPCR.DN (default
+      // NaN) is not set:
+      //  - The sign is propagated.
+      //  - The payload (mantissa) is transferred as much as possible, except
+      //    that the top bit is forced to '1', making the result a quiet NaN.
+      uint64_t raw = double_to_rawbits(value);
+
+      uint32_t sign = raw >> 63;
+      uint32_t exponent = (1 << 8) - 1;
+      uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw);
+      payload |= (1 << 22);   // Force a quiet NaN.
+
+      return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
+    }
+
+    case FP_ZERO:
+    case FP_INFINITE: {
+      // In a C++ cast, any value representable in the target type will be
+      // unchanged. This is always the case for +/-0.0 and infinities.
+      return static_cast<float>(value);
+    }
+
+    case FP_NORMAL:
+    case FP_SUBNORMAL: {
+      // Convert double-to-float as the processor would, assuming that FPCR.FZ
+      // (flush-to-zero) is not set.
+      uint64_t raw = double_to_rawbits(value);
+      // Extract the IEEE-754 double components.
+      uint32_t sign = raw >> 63;
+      // Extract the exponent and remove the IEEE-754 encoding bias.
+      int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023;
+      // Extract the mantissa and add the implicit '1' bit.
+      uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
+      if (fpclassify(value) == FP_NORMAL) {
+        mantissa |= (1UL << 52);
+      }
+      return FPRoundToFloat(sign, exponent, mantissa, round_mode);
+    }
+  }
+
+  UNREACHABLE();
+  return value;
+}
+
+
+void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned fd = instr->Rd();
+  unsigned fn = instr->Rn();
+  unsigned fm = instr->Rm();
+
+  switch (instr->Mask(FPDataProcessing2SourceMask)) {
+    case FADD_s: set_sreg(fd, sreg(fn) + sreg(fm)); break;
+    case FADD_d: set_dreg(fd, dreg(fn) + dreg(fm)); break;
+    case FSUB_s: set_sreg(fd, sreg(fn) - sreg(fm)); break;
+    case FSUB_d: set_dreg(fd, dreg(fn) - dreg(fm)); break;
+    case FMUL_s: set_sreg(fd, sreg(fn) * sreg(fm)); break;
+    case FMUL_d: set_dreg(fd, dreg(fn) * dreg(fm)); break;
+    case FDIV_s: set_sreg(fd, sreg(fn) / sreg(fm)); break;
+    case FDIV_d: set_dreg(fd, dreg(fn) / dreg(fm)); break;
+    case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
+    case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
+    case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
+    case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
+  AssertSupportedFPCR();
+
+  unsigned fd = instr->Rd();
+  unsigned fn = instr->Rn();
+  unsigned fm = instr->Rm();
+  unsigned fa = instr->Ra();
+
+  // Note: The FMSUB implementation here is not precisely the same as the
+  // instruction definition. In full implementation rounding of results would
+  // occur once at the end, here rounding will occur after the first multiply
+  // and then after the subsequent addition.  A full implementation here would
+  // be possible but would require an effort isn't immediately justified given
+  // the small differences we expect to see in most cases.
+
+  switch (instr->Mask(FPDataProcessing3SourceMask)) {
+    case FMSUB_s: set_sreg(fd, sreg(fa) + (-sreg(fn))*sreg(fm)); break;
+    case FMSUB_d: set_dreg(fd, dreg(fa) + (-dreg(fn))*dreg(fm)); break;
+    default: UNIMPLEMENTED();
+  }
+}
+
+
+double Simulator::FPMax(double a, double b) {
+  if (isnan(a)) {
+    return a;
+  } else if (isnan(b)) {
+    return b;
+  }
+
+  if ((a == 0.0) && (b == 0.0) &&
+      (copysign(1.0, a) != copysign(1.0, b))) {
+    // a and b are zero, and the sign differs: return +0.0.
+    return 0.0;
+  } else {
+    return (a > b) ? a : b;
+  }
+}
+
+
+double Simulator::FPMin(double a, double b) {
+  if (isnan(a)) {
+    return a;
+  } else if (isnan(b)) {
+    return b;
+  }
+
+  if ((a == 0.0) && (b == 0.0) &&
+      (copysign(1.0, a) != copysign(1.0, b))) {
+    // a and b are zero, and the sign differs: return -0.0.
+    return -0.0;
+  } else {
+    return (a < b) ? a : b;
+  }
+}
+
+
+void Simulator::VisitSystem(Instruction* instr) {
+  // Some system instructions hijack their Op and Cp fields to represent a
+  // range of immediates instead of indicating a different instruction. This
+  // makes the decoding tricky.
+  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
+    switch (instr->Mask(SystemSysRegMask)) {
+      case MRS: {
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
+          case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
+          default: UNIMPLEMENTED();
+        }
+        break;
+      }
+      case MSR: {
+        switch (instr->ImmSystemRegister()) {
+          case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break;
+          case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break;
+          default: UNIMPLEMENTED();
+        }
+        break;
+      }
+    }
+  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
+    ASSERT(instr->Mask(SystemHintMask) == HINT);
+    switch (instr->ImmHint()) {
+      case NOP: break;
+      default: UNIMPLEMENTED();
+    }
+  } else {
+    UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::VisitException(Instruction* instr) {
+  switch (instr->Mask(ExceptionMask)) {
+    case BRK: HostBreakpoint(); break;
+    case HLT:
+      // The Printf pseudo instruction is so useful, we include it in the
+      // default simulator.
+      if (instr->ImmException() == kPrintfOpcode) {
+        DoPrintf(instr);
+      } else {
+        HostBreakpoint();
+      }
+      break;
+    default:
+      UNIMPLEMENTED();
+  }
+}
+
+
+void Simulator::DoPrintf(Instruction* instr) {
+  ASSERT((instr->Mask(ExceptionMask) == HLT) &&
+         (instr->ImmException() == kPrintfOpcode));
+
+  // Read the argument encoded inline in the instruction stream.
+  uint32_t type;
+  ASSERT(sizeof(*instr) == 1);
+  memcpy(&type, instr + kPrintfTypeOffset, sizeof(type));
+
+  const char * format = reinterpret_cast<const char *>(x0());
+  ASSERT(format != NULL);
+
+  // Pass all of the relevant PCS registers onto printf. It doesn't matter
+  // if we pass too many as the extra ones won't be read.
+  int result = 0;
+  if (type == CPURegister::kRegister) {
+    result = printf(format, x1(), x2(), x3(), x4(), x5(), x6(), x7());
+  } else if (type == CPURegister::kFPRegister) {
+    result = printf(format, d0(), d1(), d2(), d3(), d4(), d5(), d6(), d7());
+  } else {
+    ASSERT(type == CPURegister::kNoRegister);
+    result = printf("%s", format);
+  }
+  set_x0(result);
+
+  // TODO: Clobber all caller-saved registers here, to ensure no assumptions
+  // are made about preserved state.
+
+  // The printf parameters are inlined in the code, so skip them.
+  set_pc(instr->InstructionAtOffset(kPrintfLength));
+
+  // Set LR as if we'd just called a native printf function.
+  set_lr(reinterpret_cast<uint64_t>(pc()));
+}
+
+}  // namespace vixl
diff --git a/disas/libvixl/src/a64/simulator-a64.h b/disas/libvixl/src/a64/simulator-a64.h
new file mode 100644
index 0000000..0c22f9e
--- /dev/null
+++ b/disas/libvixl/src/a64/simulator-a64.h
@@ -0,0 +1,576 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_A64_SIMULATOR_A64_H_
+#define VIXL_A64_SIMULATOR_A64_H_
+
+#include "globals.h"
+#include "utils.h"
+#include "a64/instructions-a64.h"
+#include "a64/assembler-a64.h"
+#include "a64/disasm-a64.h"
+#include "a64/instrument-a64.h"
+
+namespace vixl {
+
+enum ReverseByteMode {
+  Reverse16 = 0,
+  Reverse32 = 1,
+  Reverse64 = 2
+};
+
+// Printf. See debugger-a64.h for more informations on pseudo instructions.
+//  - type: CPURegister::RegisterType stored as a uint32_t.
+//
+// Simulate a call to printf.
+//
+// Floating-point and integer arguments are passed in separate sets of
+// registers in AAPCS64 (even for varargs functions), so it is not possible to
+// determine the type of location of each argument without some information
+// about the values that were passed in. This information could be retrieved
+// from the printf format string, but the format string is not trivial to
+// parse so we encode the relevant information with the HLT instruction under
+// the type argument. Therefore the interface is:
+//    x0: The format string
+// x1-x7: Optional arguments, if type == CPURegister::kRegister
+// d0-d7: Optional arguments, if type == CPURegister::kFPRegister
+const Instr kPrintfOpcode = 0xdeb1;
+const unsigned kPrintfTypeOffset = 1 * kInstructionSize;
+const unsigned kPrintfLength = 2 * kInstructionSize;
+
+
+// The proper way to initialize a simulated system register (such as NZCV) is as
+// follows:
+//  SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
+class SimSystemRegister {
+ public:
+  // The default constructor represents a register which has no writable bits.
+  // It is not possible to set its value to anything other than 0.
+  SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
+
+  inline uint32_t RawValue() const {
+    return value_;
+  }
+
+  inline void SetRawValue(uint32_t new_value) {
+    value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
+  }
+
+  inline uint32_t Bits(int msb, int lsb) const {
+    return unsigned_bitextract_32(msb, lsb, value_);
+  }
+
+  inline int32_t SignedBits(int msb, int lsb) const {
+    return signed_bitextract_32(msb, lsb, value_);
+  }
+
+  void SetBits(int msb, int lsb, uint32_t bits);
+
+  // Default system register values.
+  static SimSystemRegister DefaultValueFor(SystemRegister id);
+
+#define DEFINE_GETTER(Name, HighBit, LowBit, Func)                            \
+  inline uint32_t Name() const { return Func(HighBit, LowBit); }              \
+  inline void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
+#define DEFINE_WRITE_IGNORE_MASK(Name, Mask)                                  \
+  static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
+
+  SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
+
+#undef DEFINE_ZERO_BITS
+#undef DEFINE_GETTER
+
+ protected:
+  // Most system registers only implement a few of the bits in the word. Other
+  // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
+  // describes the bits which are not modifiable.
+  SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
+      : value_(value), write_ignore_mask_(write_ignore_mask) { }
+
+  uint32_t value_;
+  uint32_t write_ignore_mask_;
+};
+
+
+class Simulator : public DecoderVisitor {
+ public:
+  explicit Simulator(Decoder* decoder, FILE* stream = stdout);
+  ~Simulator();
+
+  void ResetState();
+
+  // TODO: We assume little endianness, and the way in which the members of this
+  // union overlay. Add tests to ensure this, or fix accessors to no longer
+  // require this assumption.
+  union SimRegister {
+    int64_t x;
+    int32_t w;
+  };
+
+  union SimFPRegister {
+    double d;
+    float s;
+  };
+
+  // Run the simulator.
+  virtual void Run();
+  void RunFrom(Instruction* first);
+
+  // Simulation helpers.
+  inline Instruction* pc() { return pc_; }
+  inline void set_pc(Instruction* new_pc) {
+    pc_ = new_pc;
+    pc_modified_ = true;
+  }
+
+  inline void increment_pc() {
+    if (!pc_modified_) {
+      pc_ = pc_->NextInstruction();
+    }
+
+    pc_modified_ = false;
+  }
+
+  inline void ExecuteInstruction() {
+    // The program counter should always be aligned.
+    ASSERT(IsWordAligned(pc_));
+    decoder_->Decode(pc_);
+    increment_pc();
+  }
+
+  // Declare all Visitor functions.
+  #define DECLARE(A)  void Visit##A(Instruction* instr);
+  VISITOR_LIST(DECLARE)
+  #undef DECLARE
+
+  // Register accessors.
+  inline int32_t wreg(unsigned code,
+                      Reg31Mode r31mode = Reg31IsZeroRegister) const {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
+      return 0;
+    }
+    return registers_[code].w;
+  }
+
+  inline int64_t xreg(unsigned code,
+                      Reg31Mode r31mode = Reg31IsZeroRegister) const {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
+      return 0;
+    }
+    return registers_[code].x;
+  }
+
+  inline int64_t reg(unsigned size,
+                     unsigned code,
+                     Reg31Mode r31mode = Reg31IsZeroRegister) const {
+    switch (size) {
+      case kWRegSize: return wreg(code, r31mode) & kWRegMask;
+      case kXRegSize: return xreg(code, r31mode);
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+  }
+
+  inline void set_wreg(unsigned code, int32_t value,
+                       Reg31Mode r31mode = Reg31IsZeroRegister) {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
+      return;
+    }
+    registers_[code].x = 0;  // First clear the register top bits.
+    registers_[code].w = value;
+  }
+
+  inline void set_xreg(unsigned code, int64_t value,
+                       Reg31Mode r31mode = Reg31IsZeroRegister) {
+    ASSERT(code < kNumberOfRegisters);
+    if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
+      return;
+    }
+    registers_[code].x = value;
+  }
+
+  inline void set_reg(unsigned size, unsigned code, int64_t value,
+                      Reg31Mode r31mode = Reg31IsZeroRegister) {
+    switch (size) {
+      case kWRegSize:
+        return set_wreg(code, static_cast<int32_t>(value & 0xffffffff),
+                        r31mode);
+      case kXRegSize:
+        return set_xreg(code, value, r31mode);
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+
+  #define REG_ACCESSORS(N)                                 \
+  inline int32_t w##N() { return wreg(N); }                \
+  inline int64_t x##N() { return xreg(N); }                \
+  inline void set_w##N(int32_t val) { set_wreg(N, val); }  \
+  inline void set_x##N(int64_t val) { set_xreg(N, val); }
+  REGISTER_CODE_LIST(REG_ACCESSORS)
+  #undef REG_ACCESSORS
+
+  // Aliases.
+  #define REG_ALIAS_ACCESSORS(N, wname, xname)                \
+  inline int32_t wname() { return wreg(N); }                  \
+  inline int64_t xname() { return xreg(N); }                  \
+  inline void set_##wname(int32_t val) { set_wreg(N, val); }  \
+  inline void set_##xname(int64_t val) { set_xreg(N, val); }
+  REG_ALIAS_ACCESSORS(30, wlr, lr);
+  #undef REG_ALIAS_ACCESSORS
+
+  // The stack is a special case in aarch64.
+  inline int32_t wsp() { return wreg(31, Reg31IsStackPointer); }
+  inline int64_t sp() { return xreg(31, Reg31IsStackPointer); }
+  inline void set_wsp(int32_t val) {
+    set_wreg(31, val, Reg31IsStackPointer);
+  }
+  inline void set_sp(int64_t val) {
+    set_xreg(31, val, Reg31IsStackPointer);
+  }
+
+  // FPRegister accessors.
+  inline float sreg(unsigned code) const {
+    ASSERT(code < kNumberOfFPRegisters);
+    return fpregisters_[code].s;
+  }
+
+  inline uint32_t sreg_bits(unsigned code) const {
+    return float_to_rawbits(sreg(code));
+  }
+
+  inline double dreg(unsigned code) const {
+    ASSERT(code < kNumberOfFPRegisters);
+    return fpregisters_[code].d;
+  }
+
+  inline uint64_t dreg_bits(unsigned code) const {
+    return double_to_rawbits(dreg(code));
+  }
+
+  inline double fpreg(unsigned size, unsigned code) const {
+    switch (size) {
+      case kSRegSize: return sreg(code);
+      case kDRegSize: return dreg(code);
+      default: {
+        UNREACHABLE();
+        return 0.0;
+      }
+    }
+  }
+
+  inline void set_sreg(unsigned code, float val) {
+    ASSERT(code < kNumberOfFPRegisters);
+    // Ensure that the upper word is set to 0.
+    set_dreg_bits(code, 0);
+
+    fpregisters_[code].s = val;
+  }
+
+  inline void set_sreg_bits(unsigned code, uint32_t rawbits) {
+    ASSERT(code < kNumberOfFPRegisters);
+    // Ensure that the upper word is set to 0.
+    set_dreg_bits(code, 0);
+
+    set_sreg(code, rawbits_to_float(rawbits));
+  }
+
+  inline void set_dreg(unsigned code, double val) {
+    ASSERT(code < kNumberOfFPRegisters);
+    fpregisters_[code].d = val;
+  }
+
+  inline void set_dreg_bits(unsigned code, uint64_t rawbits) {
+    ASSERT(code < kNumberOfFPRegisters);
+    set_dreg(code, rawbits_to_double(rawbits));
+  }
+
+  inline void set_fpreg(unsigned size, unsigned code, double value) {
+    switch (size) {
+      case kSRegSize:
+        return set_sreg(code, value);
+      case kDRegSize:
+        return set_dreg(code, value);
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+
+  #define FPREG_ACCESSORS(N)                             \
+  inline float s##N() { return sreg(N); }                \
+  inline double d##N() { return dreg(N); }               \
+  inline void set_s##N(float val) { set_sreg(N, val); }  \
+  inline void set_d##N(double val) { set_dreg(N, val); }
+  REGISTER_CODE_LIST(FPREG_ACCESSORS)
+  #undef FPREG_ACCESSORS
+
+  bool N() { return nzcv_.N() != 0; }
+  bool Z() { return nzcv_.Z() != 0; }
+  bool C() { return nzcv_.C() != 0; }
+  bool V() { return nzcv_.V() != 0; }
+  SimSystemRegister& nzcv() { return nzcv_; }
+
+  // TODO(jbramley): Find a way to make the fpcr_ members return the proper
+  // types, so this accessor is not necessary.
+  FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
+  SimSystemRegister& fpcr() { return fpcr_; }
+
+  // Debug helpers
+  void PrintSystemRegisters(bool print_all = false);
+  void PrintRegisters(bool print_all_regs = false);
+  void PrintFPRegisters(bool print_all_regs = false);
+  void PrintProcessorState();
+
+  static const char* WRegNameForCode(unsigned code,
+                                     Reg31Mode mode = Reg31IsZeroRegister);
+  static const char* XRegNameForCode(unsigned code,
+                                     Reg31Mode mode = Reg31IsZeroRegister);
+  static const char* SRegNameForCode(unsigned code);
+  static const char* DRegNameForCode(unsigned code);
+  static const char* VRegNameForCode(unsigned code);
+
+  inline bool coloured_trace() { return coloured_trace_; }
+  inline void set_coloured_trace(bool value) { coloured_trace_ = value; }
+
+  inline bool disasm_trace() { return disasm_trace_; }
+  inline void set_disasm_trace(bool value) {
+    if (value != disasm_trace_) {
+      if (value) {
+        decoder_->InsertVisitorBefore(print_disasm_, this);
+      } else {
+        decoder_->RemoveVisitor(print_disasm_);
+      }
+      disasm_trace_ = value;
+    }
+  }
+  inline void set_instruction_stats(bool value) {
+    if (value != instruction_stats_) {
+      if (value) {
+        decoder_->AppendVisitor(instrumentation_);
+      } else {
+        decoder_->RemoveVisitor(instrumentation_);
+      }
+      instruction_stats_ = value;
+    }
+  }
+
+ protected:
+  // Simulation helpers ------------------------------------
+  bool ConditionPassed(Condition cond) {
+    switch (cond) {
+      case eq:
+        return Z();
+      case ne:
+        return !Z();
+      case hs:
+        return C();
+      case lo:
+        return !C();
+      case mi:
+        return N();
+      case pl:
+        return !N();
+      case vs:
+        return V();
+      case vc:
+        return !V();
+      case hi:
+        return C() && !Z();
+      case ls:
+        return !(C() && !Z());
+      case ge:
+        return N() == V();
+      case lt:
+        return N() != V();
+      case gt:
+        return !Z() && (N() == V());
+      case le:
+        return !(!Z() && (N() == V()));
+      case nv:  // Fall through.
+      case al:
+        return true;
+      default:
+        UNREACHABLE();
+        return false;
+    }
+  }
+
+  bool ConditionFailed(Condition cond) {
+    return !ConditionPassed(cond);
+  }
+
+  void AddSubHelper(Instruction* instr, int64_t op2);
+  int64_t AddWithCarry(unsigned reg_size,
+                       bool set_flags,
+                       int64_t src1,
+                       int64_t src2,
+                       int64_t carry_in = 0);
+  void LogicalHelper(Instruction* instr, int64_t op2);
+  void ConditionalCompareHelper(Instruction* instr, int64_t op2);
+  void LoadStoreHelper(Instruction* instr,
+                       int64_t offset,
+                       AddrMode addrmode);
+  void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
+  uint8_t* AddressModeHelper(unsigned addr_reg,
+                             int64_t offset,
+                             AddrMode addrmode);
+
+  uint64_t MemoryRead(const uint8_t* address, unsigned num_bytes);
+  uint8_t MemoryRead8(uint8_t* address);
+  uint16_t MemoryRead16(uint8_t* address);
+  uint32_t MemoryRead32(uint8_t* address);
+  float MemoryReadFP32(uint8_t* address);
+  uint64_t MemoryRead64(uint8_t* address);
+  double MemoryReadFP64(uint8_t* address);
+
+  void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
+  void MemoryWrite32(uint8_t* address, uint32_t value);
+  void MemoryWriteFP32(uint8_t* address, float value);
+  void MemoryWrite64(uint8_t* address, uint64_t value);
+  void MemoryWriteFP64(uint8_t* address, double value);
+
+  int64_t ShiftOperand(unsigned reg_size,
+                       int64_t value,
+                       Shift shift_type,
+                       unsigned amount);
+  int64_t Rotate(unsigned reg_width,
+                 int64_t value,
+                 Shift shift_type,
+                 unsigned amount);
+  int64_t ExtendValue(unsigned reg_width,
+                      int64_t value,
+                      Extend extend_type,
+                      unsigned left_shift = 0);
+
+  uint64_t ReverseBits(uint64_t value, unsigned num_bits);
+  uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
+
+  void FPCompare(double val0, double val1);
+  double FPRoundInt(double value, FPRounding round_mode);
+  double FPToDouble(float value);
+  float FPToFloat(double value, FPRounding round_mode);
+  double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
+  double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
+  float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
+  float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
+  int32_t FPToInt32(double value, FPRounding rmode);
+  int64_t FPToInt64(double value, FPRounding rmode);
+  uint32_t FPToUInt32(double value, FPRounding rmode);
+  uint64_t FPToUInt64(double value, FPRounding rmode);
+  double FPMax(double a, double b);
+  double FPMin(double a, double b);
+
+  // Pseudo Printf instruction
+  void DoPrintf(Instruction* instr);
+
+  // Processor state ---------------------------------------
+
+  // Output stream.
+  FILE* stream_;
+  PrintDisassembler* print_disasm_;
+
+  // Instruction statistics instrumentation.
+  Instrument* instrumentation_;
+
+  // General purpose registers. Register 31 is the stack pointer.
+  SimRegister registers_[kNumberOfRegisters];
+
+  // Floating point registers
+  SimFPRegister fpregisters_[kNumberOfFPRegisters];
+
+  // Program Status Register.
+  // bits[31, 27]: Condition flags N, Z, C, and V.
+  //               (Negative, Zero, Carry, Overflow)
+  SimSystemRegister nzcv_;
+
+  // Floating-Point Control Register
+  SimSystemRegister fpcr_;
+
+  // Only a subset of FPCR features are supported by the simulator. This helper
+  // checks that the FPCR settings are supported.
+  //
+  // This is checked when floating-point instructions are executed, not when
+  // FPCR is set. This allows generated code to modify FPCR for external
+  // functions, or to save and restore it when entering and leaving generated
+  // code.
+  void AssertSupportedFPCR() {
+    ASSERT(fpcr().DN() == 0);             // No default-NaN support.
+    ASSERT(fpcr().FZ() == 0);             // No flush-to-zero support.
+    ASSERT(fpcr().RMode() == FPTieEven);  // Ties-to-even rounding only.
+
+    // The simulator does not support half-precision operations so fpcr().AHP()
+    // is irrelevant, and is not checked here.
+  }
+
+  static inline int CalcNFlag(uint64_t result, unsigned reg_size) {
+    return (result >> (reg_size - 1)) & 1;
+  }
+
+  static inline int CalcZFlag(uint64_t result) {
+    return result == 0;
+  }
+
+  static const uint32_t kConditionFlagsMask = 0xf0000000;
+
+  // Stack
+  byte* stack_;
+  static const int stack_protection_size_ = 256;
+  // 2 KB stack.
+  static const int stack_size_ = 2 * 1024 + 2 * stack_protection_size_;
+  byte* stack_limit_;
+
+  Decoder* decoder_;
+  // Indicates if the pc has been modified by the instruction and should not be
+  // automatically incremented.
+  bool pc_modified_;
+  Instruction* pc_;
+
+  static const char* xreg_names[];
+  static const char* wreg_names[];
+  static const char* sreg_names[];
+  static const char* dreg_names[];
+  static const char* vreg_names[];
+
+  static const Instruction* kEndOfSimAddress;
+
+ private:
+  bool coloured_trace_;
+
+  // Indicates whether the disassembly trace is active.
+  bool disasm_trace_;
+
+  // Indicates whether the instruction instrumentation is active.
+  bool instruction_stats_;
+};
+}  // namespace vixl
+
+#endif  // VIXL_A64_SIMULATOR_A64_H_
diff --git a/disas/libvixl/src/globals.h b/disas/libvixl/src/globals.h
new file mode 100644
index 0000000..859ea69
--- /dev/null
+++ b/disas/libvixl/src/globals.h
@@ -0,0 +1,66 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_GLOBALS_H
+#define VIXL_GLOBALS_H
+
+// Get the standard printf format macros for C99 stdint types.
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "platform.h"
+
+
+typedef uint8_t byte;
+
+const int KBytes = 1024;
+const int MBytes = 1024 * KBytes;
+const int GBytes = 1024 * MBytes;
+
+  #define ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort()
+#ifdef DEBUG
+  #define ASSERT(condition) assert(condition)
+  #define CHECK(condition) ASSERT(condition)
+  #define UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); ABORT()
+  #define UNREACHABLE() printf("UNREACHABLE\t"); ABORT()
+#else
+  #define ASSERT(condition) ((void) 0)
+  #define CHECK(condition) assert(condition)
+  #define UNIMPLEMENTED() ((void) 0)
+  #define UNREACHABLE() ((void) 0)
+#endif
+
+template <typename T> inline void USE(T) {}
+
+#define ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); ABORT()
+
+#endif  // VIXL_GLOBALS_H
diff --git a/disas/libvixl/src/platform.h b/disas/libvixl/src/platform.h
new file mode 100644
index 0000000..a2600f3
--- /dev/null
+++ b/disas/libvixl/src/platform.h
@@ -0,0 +1,43 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+// Define platform specific functionalities.
+
+namespace vixl {
+#ifdef USE_SIMULATOR
+// Currently we assume running the simulator implies running on x86 hardware.
+inline void HostBreakpoint() { asm("int3"); }
+#else
+inline void HostBreakpoint() {
+  // TODO: Implement HostBreakpoint on a64.
+}
+#endif
+}  // namespace vixl
+
+#endif
diff --git a/disas/libvixl/src/utils.cc b/disas/libvixl/src/utils.cc
new file mode 100644
index 0000000..6f85e61
--- /dev/null
+++ b/disas/libvixl/src/utils.cc
@@ -0,0 +1,120 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utils.h"
+#include <stdio.h>
+
+namespace vixl {
+
+uint32_t float_to_rawbits(float value) {
+  uint32_t bits = 0;
+  memcpy(&bits, &value, 4);
+  return bits;
+}
+
+
+uint64_t double_to_rawbits(double value) {
+  uint64_t bits = 0;
+  memcpy(&bits, &value, 8);
+  return bits;
+}
+
+
+float rawbits_to_float(uint32_t bits) {
+  float value = 0.0;
+  memcpy(&value, &bits, 4);
+  return value;
+}
+
+
+double rawbits_to_double(uint64_t bits) {
+  double value = 0.0;
+  memcpy(&value, &bits, 8);
+  return value;
+}
+
+
+int CountLeadingZeros(uint64_t value, int width) {
+  ASSERT((width == 32) || (width == 64));
+  int count = 0;
+  uint64_t bit_test = 1UL << (width - 1);
+  while ((count < width) && ((bit_test & value) == 0)) {
+    count++;
+    bit_test >>= 1;
+  }
+  return count;
+}
+
+
+int CountLeadingSignBits(int64_t value, int width) {
+  ASSERT((width == 32) || (width == 64));
+  if (value >= 0) {
+    return CountLeadingZeros(value, width) - 1;
+  } else {
+    return CountLeadingZeros(~value, width) - 1;
+  }
+}
+
+
+int CountTrailingZeros(uint64_t value, int width) {
+  ASSERT((width == 32) || (width == 64));
+  int count = 0;
+  while ((count < width) && (((value >> count) & 1) == 0)) {
+    count++;
+  }
+  return count;
+}
+
+
+int CountSetBits(uint64_t value, int width) {
+  // TODO: Other widths could be added here, as the implementation already
+  // supports them.
+  ASSERT((width == 32) || (width == 64));
+
+  // Mask out unused bits to ensure that they are not counted.
+  value &= (0xffffffffffffffffUL >> (64-width));
+
+  // Add up the set bits.
+  // The algorithm works by adding pairs of bit fields together iteratively,
+  // where the size of each bit field doubles each time.
+  // An example for an 8-bit value:
+  // Bits:  h  g  f  e  d  c  b  a
+  //         \ |   \ |   \ |   \ |
+  // value = h+g   f+e   d+c   b+a
+  //            \    |      \    |
+  // value =   h+g+f+e     d+c+b+a
+  //                  \          |
+  // value =       h+g+f+e+d+c+b+a
+  value = ((value >> 1) & 0x5555555555555555) + (value & 0x5555555555555555);
+  value = ((value >> 2) & 0x3333333333333333) + (value & 0x3333333333333333);
+  value = ((value >> 4) & 0x0f0f0f0f0f0f0f0f) + (value & 0x0f0f0f0f0f0f0f0f);
+  value = ((value >> 8) & 0x00ff00ff00ff00ff) + (value & 0x00ff00ff00ff00ff);
+  value = ((value >> 16) & 0x0000ffff0000ffff) + (value & 0x0000ffff0000ffff);
+  value = ((value >> 32) & 0x00000000ffffffff) + (value & 0x00000000ffffffff);
+
+  return value;
+}
+}  // namespace vixl
diff --git a/disas/libvixl/src/utils.h b/disas/libvixl/src/utils.h
new file mode 100644
index 0000000..4e0b367
--- /dev/null
+++ b/disas/libvixl/src/utils.h
@@ -0,0 +1,126 @@
+// Copyright 2013, ARM Limited
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of ARM Limited nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef VIXL_UTILS_H
+#define VIXL_UTILS_H
+
+
+#include <string.h>
+#include "globals.h"
+
+namespace vixl {
+
+// Check number width.
+inline bool is_intn(unsigned n, int64_t x) {
+  ASSERT((0 < n) && (n < 64));
+  int64_t limit = 1L << (n - 1);
+  return (-limit <= x) && (x < limit);
+}
+
+inline bool is_uintn(unsigned n, int64_t x) {
+  ASSERT((0 < n) && (n < 64));
+  return !(x >> n);
+}
+
+inline unsigned truncate_to_intn(unsigned n, int64_t x) {
+  ASSERT((0 < n) && (n < 64));
+  return (x & ((1L << n) - 1));
+}
+
+#define INT_1_TO_63_LIST(V)                                                    \
+V(1)  V(2)  V(3)  V(4)  V(5)  V(6)  V(7)  V(8)                                 \
+V(9)  V(10) V(11) V(12) V(13) V(14) V(15) V(16)                                \
+V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24)                                \
+V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32)                                \
+V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40)                                \
+V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48)                                \
+V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56)                                \
+V(57) V(58) V(59) V(60) V(61) V(62) V(63)
+
+#define DECLARE_IS_INT_N(N)                                                    \
+inline bool is_int##N(int64_t x) { return is_intn(N, x); }
+#define DECLARE_IS_UINT_N(N)                                                   \
+inline bool is_uint##N(int64_t x) { return is_uintn(N, x); }
+#define DECLARE_TRUNCATE_TO_INT_N(N)                                           \
+inline int truncate_to_int##N(int x) { return truncate_to_intn(N, x); }
+INT_1_TO_63_LIST(DECLARE_IS_INT_N)
+INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
+INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
+#undef DECLARE_IS_INT_N
+#undef DECLARE_IS_UINT_N
+#undef DECLARE_TRUNCATE_TO_INT_N
+
+// Bit field extraction.
+inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
+  return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
+}
+
+inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
+  return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
+}
+
+inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
+  return (x << (31 - msb)) >> (lsb + 31 - msb);
+}
+
+inline int64_t signed_bitextract_64(int msb, int lsb, int64_t x) {
+  return (x << (63 - msb)) >> (lsb + 63 - msb);
+}
+
+// floating point representation
+uint32_t float_to_rawbits(float value);
+uint64_t double_to_rawbits(double value);
+float rawbits_to_float(uint32_t bits);
+double rawbits_to_double(uint64_t bits);
+
+// Bits counting.
+int CountLeadingZeros(uint64_t value, int width);
+int CountLeadingSignBits(int64_t value, int width);
+int CountTrailingZeros(uint64_t value, int width);
+int CountSetBits(uint64_t value, int width);
+
+// Pointer alignment
+// TODO: rename/refactor to make it specific to instructions.
+template<typename T>
+bool IsWordAligned(T pointer) {
+  ASSERT(sizeof(pointer) == sizeof(intptr_t));   // NOLINT(runtime/sizeof)
+  return (reinterpret_cast<intptr_t>(pointer) & 3) == 0;
+}
+
+// Increment a pointer until it has the specified alignment.
+template<class T>
+T AlignUp(T pointer, size_t alignment) {
+  ASSERT(sizeof(pointer) == sizeof(uintptr_t));
+  uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
+  size_t align_step = (alignment - pointer_raw) % alignment;
+  ASSERT((pointer_raw + align_step) % alignment == 0);
+  return reinterpret_cast<T>(pointer_raw + align_step);
+}
+
+
+}  // namespace vixl
+
+#endif  // VIXL_UTILS_H
-- 
1.8.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
  2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
                   ` (6 preceding siblings ...)
  2013-09-11 14:35 ` [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64 Claudio Fontana
@ 2013-09-15 16:41 ` Rob Landley
  2013-09-15 17:27   ` Peter Maydell
  7 siblings, 1 reply; 14+ messages in thread
From: Rob Landley @ 2013-09-15 16:41 UTC (permalink / raw)
  To: Claudio Fontana; +Cc: Peter Maydell, qemu-devel

On 09/11/2013 07:54:32 AM, Claudio Fontana wrote:
> 
> This is the aarch64 libvixl support patchset in the current state.
> It provides (limited) support for disassembly output on aarch64.
> Only host disassembly is enabled, since target for aarch64 is not in  
> yet.
> 
> An external objdump solution as exemplified before by R.H. seems  
> preferable
> to me, even if it means giving up the monitor support.
> I'd rather have correct output from -d.
> The run time need for debugging assembly is already fulfilled by gdb  
> better
> than the monitor.
> 
> libvixl does not support many opcodes right now, is C++, and it is  
> documented
> as working only for a 64bit host with a LP64 memory model.

Wait, incorporating C++ code into qemu was considered the _good_  
solution?

What was the bad solution?

Rob

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
  2013-09-15 16:41 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Rob Landley
@ 2013-09-15 17:27   ` Peter Maydell
  2013-09-15 20:04     ` Laurent Desnogues
  0 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2013-09-15 17:27 UTC (permalink / raw)
  To: Rob Landley; +Cc: Claudio Fontana, qemu-devel

On 15 September 2013 17:41, Rob Landley <rob@landley.net> wrote:
> Wait, incorporating C++ code into qemu was considered the _good_ solution?
>
> What was the bad solution?

Not supporting disassembly at all, and/or having a runtime
dependency on finding an objdump that works for the target.

-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support
  2013-09-15 17:27   ` Peter Maydell
@ 2013-09-15 20:04     ` Laurent Desnogues
  0 siblings, 0 replies; 14+ messages in thread
From: Laurent Desnogues @ 2013-09-15 20:04 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Claudio Fontana, qemu-devel

On Sun, Sep 15, 2013 at 7:27 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 15 September 2013 17:41, Rob Landley <rob@landley.net> wrote:
>> Wait, incorporating C++ code into qemu was considered the _good_ solution?
>>
>> What was the bad solution?
>
> Not supporting disassembly at all, and/or having a runtime
> dependency on finding an objdump that works for the target.

Now that documentation is out, perhaps someone will write
a disassembler in C with an acceptable license?  I would
happily review it.


Laurent

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 4/4] disas: implement host disassembly output for aarch64
  2013-09-11 13:08 ` [Qemu-devel] [RFC 4/4] disas: implement host disassembly output " Claudio Fontana
@ 2013-09-16  6:53   ` Andreas Färber
  2013-09-16 10:43     ` Claudio Fontana
  0 siblings, 1 reply; 14+ messages in thread
From: Andreas Färber @ 2013-09-16  6:53 UTC (permalink / raw)
  To: Claudio Fontana; +Cc: Peter Maydell, qemu-devel

Am 11.09.2013 15:08, schrieb Claudio Fontana:
> use C++ libvixl to implement output, for now only enabled for the host output
> disasm, since we don't have the aarch64 target yet.
> 
> Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
> ---
>  configure                   |  6 +++++
>  disas.c                     |  2 ++
>  disas/Makefile.objs         |  7 ++++++
>  disas/aarch64-cxx.cc        | 53 +++++++++++++++++++++++++++++++++++++++++++++
>  disas/aarch64.c             | 45 ++++++++++++++++++++++++++++++++++++++
>  disas/libvixl/Makefile.objs |  6 +++++
>  include/disas/bfd.h         |  1 +
>  7 files changed, 120 insertions(+)
>  create mode 100644 disas/aarch64-cxx.cc
>  create mode 100644 disas/aarch64.c
>  create mode 100644 disas/libvixl/Makefile.objs
> 
> diff --git a/configure b/configure
> index 6b73d99..1a2648a 100755
> --- a/configure
> +++ b/configure
> @@ -4443,6 +4443,12 @@ ldflags=""
>  
>  for i in $ARCH $TARGET_BASE_ARCH ; do
>    case "$i" in
> +  aarch64)
> +    if test "x${cxx}" != "x"; then
> +      echo "CONFIG_AARCH64_DIS=y"  >> $config_target_mak
> +      echo "CONFIG_AARCH64_DIS=y"  >> config-all-disas.mak
> +    fi
> +  ;;
>    alpha)
>      echo "CONFIG_ALPHA_DIS=y"  >> $config_target_mak
>      echo "CONFIG_ALPHA_DIS=y"  >> config-all-disas.mak
> diff --git a/disas.c b/disas.c
> index 0203ef2..cc20c4a 100644
> --- a/disas.c
> +++ b/disas.c
> @@ -356,6 +356,8 @@ void disas(FILE *out, void *code, unsigned long size)
>  #elif defined(_ARCH_PPC)
>      s.info.disassembler_options = (char *)"any";
>      print_insn = print_insn_ppc;
> +#elif defined(__aarch64__)
> +    print_insn = print_insn_aarch64;
>  #elif defined(__alpha__)
>      print_insn = print_insn_alpha;
>  #elif defined(__sparc__)
> diff --git a/disas/Makefile.objs b/disas/Makefile.objs
> index 3b1e77a..f468c22 100644
> --- a/disas/Makefile.objs
> +++ b/disas/Makefile.objs
> @@ -1,3 +1,10 @@
> +ifeq ($(CONFIG_AARCH64_DIS),y)
> +libvixldir = $(SRC_PATH)/disas/libvixl/src
> +QEMU_CFLAGS += -I$(libvixldir) -Wno-undef
> +common-obj-$(CONFIG_AARCH64_DIS) += libvixl/
> +common-obj-$(CONFIG_AARCH64_DIS) += aarch64.o aarch64-cxx.o
> +endif
> +
>  common-obj-$(CONFIG_ALPHA_DIS) += alpha.o
>  common-obj-$(CONFIG_ARM_DIS) += arm.o
>  common-obj-$(CONFIG_CRIS_DIS) += cris.o
> diff --git a/disas/aarch64-cxx.cc b/disas/aarch64-cxx.cc
> new file mode 100644
> index 0000000..524f5ae
> --- /dev/null
> +++ b/disas/aarch64-cxx.cc
> @@ -0,0 +1,53 @@
> +/*
> + * Aarch64 disassembly output wrapper to libvixl - C++ part
> + * Copyright (c) 2013 Linaro Limited
> + * Written by Claudio Fontana
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program 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 for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "a64/simulator-a64.h"
> +#include "a64/macro-assembler-a64.h"
> +
> +extern "C" {
> +    int vixl_is_initialized(int);
> +    int vixl_init(FILE *f);
> +    int vixl_decode_insn(uint8_t *bytes);
> +}
> +
> +using namespace vixl;
> +
> +static Decoder *vixl_decoder = NULL;
> +static Disassembler *vixl_disasm = NULL;
> +
> +int vixl_is_initialized(int unused)
> +{
> +    return vixl_decoder != NULL;
> +}
> +
> +/* Disassemble Aarch64 bytecode - wrappers */
> +int vixl_init(FILE *f) {
> +    vixl_decoder = new Decoder();
> +    vixl_disasm = new PrintDisassembler(f);
> +    vixl_decoder->AppendVisitor(vixl_disasm);
> +    return 1;
> +}
> +
> +int vixl_decode_insn(uint8_t *bytes)
> +{
> +    Instr instr;
> +    instr = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24;
> +    vixl_decoder->Decode(reinterpret_cast<Instruction*>(&instr));
> +    return 1;
> +}
> diff --git a/disas/aarch64.c b/disas/aarch64.c
> new file mode 100644
> index 0000000..7e44837
> --- /dev/null
> +++ b/disas/aarch64.c
> @@ -0,0 +1,45 @@
> +/*
> + * Aarch64 disassembly output wrapper to libvixl - C part
> + * Copyright (c) 2013 Linaro Limited
> + * Written by Claudio Fontana
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program 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 for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "disas/bfd.h"
> +#define INSN_SIZE 4
> +
> +extern int vixl_is_initialized(int);
> +extern int vixl_init(FILE *);
> +extern int vixl_decode_insn(uint8_t *);
> +
> +/* Disassemble Aarch64 bytecode. */
> +int print_insn_aarch64(uint64_t addr, disassemble_info *info)
> +{
> +    uint8_t bytes[INSN_SIZE];
> +    int status;
> +
> +    if (!vixl_is_initialized(0)) {
> +        vixl_init(info->stream);
> +    }
> +
> +    status = info->read_memory_func(addr, bytes, INSN_SIZE, info);
> +    if (status != 0) {
> +        info->memory_error_func(status, addr, info);
> +        return -1;
> +    }
> +
> +    vixl_decode_insn(bytes);
> +    return INSN_SIZE;
> +}

Why split this into two mini files? You're already using extern "C" {
... } in the C++ file for the prototypes anyway.

Apart from that the library integration looks surprisingly clean. :)

Cheers,
Andreas

> diff --git a/disas/libvixl/Makefile.objs b/disas/libvixl/Makefile.objs
> new file mode 100644
> index 0000000..43ba29c
> --- /dev/null
> +++ b/disas/libvixl/Makefile.objs
> @@ -0,0 +1,6 @@
> +libvixl_OBJS = src/utils.o \
> +               src/a64/instructions-a64.o \
> +               src/a64/decoder-a64.o \
> +               src/a64/disasm-a64.o
> +
> +common-obj-$(CONFIG_AARCH64_DIS) += $(libvixl_OBJS)
> diff --git a/include/disas/bfd.h b/include/disas/bfd.h
> index 803b6ef..73017da 100644
> --- a/include/disas/bfd.h
> +++ b/include/disas/bfd.h
> @@ -379,6 +379,7 @@ int print_insn_h8300            (bfd_vma, disassemble_info*);
>  int print_insn_h8300h           (bfd_vma, disassemble_info*);
>  int print_insn_h8300s           (bfd_vma, disassemble_info*);
>  int print_insn_h8500            (bfd_vma, disassemble_info*);
> +int print_insn_aarch64          (bfd_vma, disassemble_info*);
>  int print_insn_alpha            (bfd_vma, disassemble_info*);
>  disassembler_ftype arc_get_disassembler (int, int);
>  int print_insn_arm              (bfd_vma, disassemble_info*);
> 


-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [RFC 4/4] disas: implement host disassembly output for aarch64
  2013-09-16  6:53   ` Andreas Färber
@ 2013-09-16 10:43     ` Claudio Fontana
  0 siblings, 0 replies; 14+ messages in thread
From: Claudio Fontana @ 2013-09-16 10:43 UTC (permalink / raw)
  To: Andreas Färber; +Cc: Peter Maydell, qemu-devel

Hallo Andreas,

On 16.09.2013 08:53, Andreas Färber wrote:
> Am 11.09.2013 15:08, schrieb Claudio Fontana:
>> use C++ libvixl to implement output, for now only enabled for the host output
>> disasm, since we don't have the aarch64 target yet.
>>
>> Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
>> ---
>>  configure                   |  6 +++++
>>  disas.c                     |  2 ++
>>  disas/Makefile.objs         |  7 ++++++
>>  disas/aarch64-cxx.cc        | 53 +++++++++++++++++++++++++++++++++++++++++++++
>>  disas/aarch64.c             | 45 ++++++++++++++++++++++++++++++++++++++
>>  disas/libvixl/Makefile.objs |  6 +++++
>>  include/disas/bfd.h         |  1 +
>>  7 files changed, 120 insertions(+)
>>  create mode 100644 disas/aarch64-cxx.cc
>>  create mode 100644 disas/aarch64.c
>>  create mode 100644 disas/libvixl/Makefile.objs
>>
>> diff --git a/configure b/configure
>> index 6b73d99..1a2648a 100755
>> --- a/configure
>> +++ b/configure
>> @@ -4443,6 +4443,12 @@ ldflags=""
>>  
>>  for i in $ARCH $TARGET_BASE_ARCH ; do
>>    case "$i" in
>> +  aarch64)
>> +    if test "x${cxx}" != "x"; then
>> +      echo "CONFIG_AARCH64_DIS=y"  >> $config_target_mak
>> +      echo "CONFIG_AARCH64_DIS=y"  >> config-all-disas.mak
>> +    fi
>> +  ;;
>>    alpha)
>>      echo "CONFIG_ALPHA_DIS=y"  >> $config_target_mak
>>      echo "CONFIG_ALPHA_DIS=y"  >> config-all-disas.mak
>> diff --git a/disas.c b/disas.c
>> index 0203ef2..cc20c4a 100644
>> --- a/disas.c
>> +++ b/disas.c
>> @@ -356,6 +356,8 @@ void disas(FILE *out, void *code, unsigned long size)
>>  #elif defined(_ARCH_PPC)
>>      s.info.disassembler_options = (char *)"any";
>>      print_insn = print_insn_ppc;
>> +#elif defined(__aarch64__)
>> +    print_insn = print_insn_aarch64;
>>  #elif defined(__alpha__)
>>      print_insn = print_insn_alpha;
>>  #elif defined(__sparc__)
>> diff --git a/disas/Makefile.objs b/disas/Makefile.objs
>> index 3b1e77a..f468c22 100644
>> --- a/disas/Makefile.objs
>> +++ b/disas/Makefile.objs
>> @@ -1,3 +1,10 @@
>> +ifeq ($(CONFIG_AARCH64_DIS),y)
>> +libvixldir = $(SRC_PATH)/disas/libvixl/src
>> +QEMU_CFLAGS += -I$(libvixldir) -Wno-undef
>> +common-obj-$(CONFIG_AARCH64_DIS) += libvixl/
>> +common-obj-$(CONFIG_AARCH64_DIS) += aarch64.o aarch64-cxx.o
>> +endif
>> +
>>  common-obj-$(CONFIG_ALPHA_DIS) += alpha.o
>>  common-obj-$(CONFIG_ARM_DIS) += arm.o
>>  common-obj-$(CONFIG_CRIS_DIS) += cris.o
>> diff --git a/disas/aarch64-cxx.cc b/disas/aarch64-cxx.cc
>> new file mode 100644
>> index 0000000..524f5ae
>> --- /dev/null
>> +++ b/disas/aarch64-cxx.cc
>> @@ -0,0 +1,53 @@
>> +/*
>> + * Aarch64 disassembly output wrapper to libvixl - C++ part
>> + * Copyright (c) 2013 Linaro Limited
>> + * Written by Claudio Fontana
>> + *
>> + * This program is free software: you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program 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 for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "a64/simulator-a64.h"
>> +#include "a64/macro-assembler-a64.h"
>> +
>> +extern "C" {
>> +    int vixl_is_initialized(int);
>> +    int vixl_init(FILE *f);
>> +    int vixl_decode_insn(uint8_t *bytes);
>> +}
>> +
>> +using namespace vixl;
>> +
>> +static Decoder *vixl_decoder = NULL;
>> +static Disassembler *vixl_disasm = NULL;
>> +
>> +int vixl_is_initialized(int unused)
>> +{
>> +    return vixl_decoder != NULL;
>> +}
>> +
>> +/* Disassemble Aarch64 bytecode - wrappers */
>> +int vixl_init(FILE *f) {
>> +    vixl_decoder = new Decoder();
>> +    vixl_disasm = new PrintDisassembler(f);
>> +    vixl_decoder->AppendVisitor(vixl_disasm);
>> +    return 1;
>> +}
>> +
>> +int vixl_decode_insn(uint8_t *bytes)
>> +{
>> +    Instr instr;
>> +    instr = bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24;
>> +    vixl_decoder->Decode(reinterpret_cast<Instruction*>(&instr));
>> +    return 1;
>> +}
>> diff --git a/disas/aarch64.c b/disas/aarch64.c
>> new file mode 100644
>> index 0000000..7e44837
>> --- /dev/null
>> +++ b/disas/aarch64.c
>> @@ -0,0 +1,45 @@
>> +/*
>> + * Aarch64 disassembly output wrapper to libvixl - C part
>> + * Copyright (c) 2013 Linaro Limited
>> + * Written by Claudio Fontana
>> + *
>> + * This program is free software: you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program 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 for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "disas/bfd.h"
>> +#define INSN_SIZE 4
>> +
>> +extern int vixl_is_initialized(int);
>> +extern int vixl_init(FILE *);
>> +extern int vixl_decode_insn(uint8_t *);
>> +
>> +/* Disassemble Aarch64 bytecode. */
>> +int print_insn_aarch64(uint64_t addr, disassemble_info *info)
>> +{
>> +    uint8_t bytes[INSN_SIZE];
>> +    int status;
>> +
>> +    if (!vixl_is_initialized(0)) {
>> +        vixl_init(info->stream);
>> +    }
>> +
>> +    status = info->read_memory_func(addr, bytes, INSN_SIZE, info);
>> +    if (status != 0) {
>> +        info->memory_error_func(status, addr, info);
>> +        return -1;
>> +    }
>> +
>> +    vixl_decode_insn(bytes);
>> +    return INSN_SIZE;
>> +}
> 
> Why split this into two mini files? You're already using extern "C" {
> ... } in the C++ file for the prototypes anyway.
> 
> Apart from that the library integration looks surprisingly clean. :)
> 
> Cheers,
> Andreas

The reason I split this into two files is that the c++ compiler did not digest the bfd.h include.

So I thought to have a .cc file which does not actually need anything from QEMU at all,
and a .c file which deals with the QEMU dependencies and provides the final symbol.

Ciao,

Claudio

>> diff --git a/disas/libvixl/Makefile.objs b/disas/libvixl/Makefile.objs
>> new file mode 100644
>> index 0000000..43ba29c
>> --- /dev/null
>> +++ b/disas/libvixl/Makefile.objs
>> @@ -0,0 +1,6 @@
>> +libvixl_OBJS = src/utils.o \
>> +               src/a64/instructions-a64.o \
>> +               src/a64/decoder-a64.o \
>> +               src/a64/disasm-a64.o
>> +
>> +common-obj-$(CONFIG_AARCH64_DIS) += $(libvixl_OBJS)
>> diff --git a/include/disas/bfd.h b/include/disas/bfd.h
>> index 803b6ef..73017da 100644
>> --- a/include/disas/bfd.h
>> +++ b/include/disas/bfd.h
>> @@ -379,6 +379,7 @@ int print_insn_h8300            (bfd_vma, disassemble_info*);
>>  int print_insn_h8300h           (bfd_vma, disassemble_info*);
>>  int print_insn_h8300s           (bfd_vma, disassemble_info*);
>>  int print_insn_h8500            (bfd_vma, disassemble_info*);
>> +int print_insn_aarch64          (bfd_vma, disassemble_info*);
>>  int print_insn_alpha            (bfd_vma, disassemble_info*);
>>  disassembler_ftype arc_get_disassembler (int, int);
>>  int print_insn_arm              (bfd_vma, disassemble_info*);
>>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-09-16 10:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-11 12:54 [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Claudio Fontana
2013-09-11 12:59 ` [Qemu-devel] [RFC 1/4] configure: add c++ compiler support Claudio Fontana
2013-09-11 13:02 ` [Qemu-devel] [RFC 2/4] rules.mak: support C++ compiling and linking Claudio Fontana
2013-09-11 13:05 ` [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64 Claudio Fontana
2013-09-11 13:08 ` [Qemu-devel] [RFC 4/4] disas: implement host disassembly output " Claudio Fontana
2013-09-16  6:53   ` Andreas Färber
2013-09-16 10:43     ` Claudio Fontana
2013-09-11 13:14 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Andreas Färber
2013-09-11 13:29   ` Peter Maydell
2013-09-11 13:37 ` Peter Maydell
2013-09-11 14:35 ` [Qemu-devel] [RFC 3/4] disas: add libvixl source code for aarch64 Claudio Fontana
2013-09-15 16:41 ` [Qemu-devel] [RFC 0/4] ARM aarch64 disas output libvixl support Rob Landley
2013-09-15 17:27   ` Peter Maydell
2013-09-15 20:04     ` Laurent Desnogues

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.