Add basic assembler interface and an x86 backend.

Change-Id: Ia8136bad88f1194c8a247e2af80e486ab88c1e8c
diff --git a/Android.common.mk b/Android.common.mk
index 94a5ac8..69ea22c 100644
--- a/Android.common.mk
+++ b/Android.common.mk
@@ -20,4 +20,16 @@
 	src/main.cc
 
 LIBART_LOCAL_SRC_FILES := \
-	src/art.cc
+	src/art.cc \
+	src/assembler.cc \
+	src/memory_region.cc
+
+ifeq ($(LIBART_TARGET_ARCH),arm)
+LIBART_LOCAL_SRC_FILES += \
+	src/assembler_arm.cc
+endif
+
+ifeq ($(LIBART_TARGET_ARCH),x86)
+LIBART_LOCAL_SRC_FILES += \
+	src/assembler_x86.cc
+endif
diff --git a/Android.libart.host.mk b/Android.libart.host.mk
index a2b62ac..d0d3c8f 100644
--- a/Android.libart.host.mk
+++ b/Android.libart.host.mk
@@ -20,6 +20,7 @@
 LOCAL_MODULE := libart
 LOCAL_MODULE_TAGS := optional
 
+LIBART_TARGET_ARCH := $(HOST_ARCH)
 include $(LOCAL_PATH)/Android.common.mk
 LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES)
 
diff --git a/Android.libart.mk b/Android.libart.mk
index 3992cf0..c54a6fe 100644
--- a/Android.libart.mk
+++ b/Android.libart.mk
@@ -20,6 +20,7 @@
 LOCAL_MODULE := libart
 LOCAL_MODULE_TAGS := optional
 
+LIBART_TARGET_ARCH := $(TARGET_ARCH)
 include $(LOCAL_PATH)/Android.common.mk
 LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES)
 
diff --git a/src/assembler.cc b/src/assembler.cc
new file mode 100644
index 0000000..f6ca690
--- /dev/null
+++ b/src/assembler.cc
@@ -0,0 +1,137 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include <algorithm>
+#include <vector>
+#include "src/assembler.h"
+#include "src/globals.h"
+#include "src/memory_region.h"
+
+namespace android {
+namespace runtime {
+
+static byte* NewContents(size_t capacity) {
+  byte* result = new byte[capacity];
+#if defined(DEBUG)
+  // Initialize the buffer with kBreakPointInstruction to force a break
+  // point if we ever execute an uninitialized part of the code buffer.
+  Assembler::InitializeMemoryWithBreakpoints(result, capacity);
+#endif
+  return result;
+}
+
+
+#if defined(DEBUG)
+AssemblerBuffer::EnsureCapacity::EnsureCapacity(AssemblerBuffer* buffer) {
+  if (buffer->cursor() >= buffer->limit()) buffer->ExtendCapacity();
+  // In debug mode, we save the assembler buffer along with the gap
+  // size before we start emitting to the buffer. This allows us to
+  // check that any single generated instruction doesn't overflow the
+  // limit implied by the minimum gap size.
+  buffer_ = buffer;
+  gap_ = ComputeGap();
+  // Make sure that extending the capacity leaves a big enough gap
+  // for any kind of instruction.
+  CHECK(gap_ >= kMinimumGap);
+  // Mark the buffer as having ensured the capacity.
+  CHECK(!buffer->HasEnsuredCapacity());  // Cannot nest.
+  buffer->has_ensured_capacity_ = true;
+}
+
+
+AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
+  // Unmark the buffer, so we cannot emit after this.
+  buffer_->has_ensured_capacity_ = false;
+  // Make sure the generated instruction doesn't take up more
+  // space than the minimum gap.
+  int delta = gap_ - ComputeGap();
+  CHECK(delta <= kMinimumGap);
+}
+#endif
+
+
+AssemblerBuffer::AssemblerBuffer() {
+  static const size_t kInitialBufferCapacity = 4 * KB;
+  contents_ = NewContents(kInitialBufferCapacity);
+  cursor_ = contents_;
+  limit_ = ComputeLimit(contents_, kInitialBufferCapacity);
+  fixup_ = NULL;
+#if defined(DEBUG)
+  has_ensured_capacity_ = false;
+  fixups_processed_ = false;
+#endif
+
+  // Verify internal state.
+  CHECK_EQ(Capacity(), kInitialBufferCapacity);
+  CHECK_EQ(Size(), 0);
+}
+
+
+AssemblerBuffer::~AssemblerBuffer() {
+}
+
+
+void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) {
+  AssemblerFixup* fixup = fixup_;
+  while (fixup != NULL) {
+    fixup->Process(region, fixup->position());
+    fixup = fixup->previous();
+  }
+}
+
+
+void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) {
+  // Copy the instructions from the buffer.
+  MemoryRegion from(reinterpret_cast<void*>(contents()), Size());
+  instructions.CopyFrom(0, from);
+
+  // Process fixups in the instructions.
+  ProcessFixups(instructions);
+#if defined(DEBUG)
+  fixups_processed_ = true;
+#endif
+}
+
+
+void AssemblerBuffer::ExtendCapacity() {
+  size_t old_size = Size();
+  size_t old_capacity = Capacity();
+  size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB);
+
+  // Allocate the new data area and copy contents of the old one to it.
+  byte* new_contents = NewContents(new_capacity);
+  memmove(reinterpret_cast<void*>(new_contents),
+          reinterpret_cast<void*>(contents_),
+          old_size);
+
+  // Compute the relocation delta and switch to the new contents area.
+  ptrdiff_t delta = new_contents - contents_;
+  contents_ = new_contents;
+
+  // Update the cursor and recompute the limit.
+  cursor_ += delta;
+  limit_ = ComputeLimit(new_contents, new_capacity);
+
+  // Verify internal state.
+  CHECK_EQ(Capacity(), new_capacity);
+  CHECK_EQ(Size(), old_size);
+}
+
+
+#if 0
+// Shared macros are implemented here.
+void Assembler::Unimplemented(const char* message) {
+  Stop("unimplemented");
+}
+
+
+void Assembler::Untested(const char* message) {
+  Stop("untested");
+}
+
+
+void Assembler::Unreachable(const char* message) {
+  Stop("unreachable");
+}
+#endif
+
+} }  // namespace android::runtime
diff --git a/src/assembler.h b/src/assembler.h
new file mode 100644
index 0000000..d211b6f
--- /dev/null
+++ b/src/assembler.h
@@ -0,0 +1,238 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_ASSEMBLER_H_
+#define ART_SRC_ASSEMBLER_H_
+
+#include "src/logging.h"
+#include "src/macros.h"
+#include "src/memory_region.h"
+
+namespace android {
+namespace runtime {
+
+class Assembler;
+class AssemblerBuffer;
+class AssemblerFixup;
+
+
+class Label {
+ public:
+  Label() : position_(0) {}
+
+  ~Label() {
+    // Assert if label is being destroyed with unresolved branches pending.
+    CHECK(!IsLinked());
+  }
+
+  // Returns the position for bound and linked labels. Cannot be used
+  // for unused labels.
+  int Position() const {
+    CHECK(!IsUnused());
+    return IsBound() ? -position_ - kPointerSize : position_ - kPointerSize;
+  }
+
+  int LinkPosition() const {
+    CHECK(IsLinked());
+    return position_ - kWordSize;
+  }
+
+  bool IsBound() const { return position_ < 0; }
+  bool IsUnused() const { return position_ == 0; }
+  bool IsLinked() const { return position_ > 0; }
+
+ private:
+  int position_;
+
+  void Reinitialize() {
+    position_ = 0;
+  }
+
+  void BindTo(int position) {
+    CHECK(!IsBound());
+    position_ = -position - kPointerSize;
+    CHECK(IsBound());
+  }
+
+  void LinkTo(int position) {
+    CHECK(!IsBound());
+    position_ = position + kPointerSize;
+    CHECK(IsLinked());
+  }
+
+  friend class Assembler;
+  DISALLOW_COPY_AND_ASSIGN(Label);
+};
+
+
+// Assembler fixups are positions in generated code that require processing
+// after the code has been copied to executable memory. This includes building
+// relocation information.
+class AssemblerFixup {
+ public:
+  virtual void Process(const MemoryRegion& region, int position) = 0;
+  virtual ~AssemblerFixup() {}
+
+ private:
+  AssemblerFixup* previous_;
+  int position_;
+
+  AssemblerFixup* previous() const { return previous_; }
+  void set_previous(AssemblerFixup* previous) { previous_ = previous; }
+
+  int position() const { return position_; }
+  void set_position(int position) { position_ = position; }
+
+  friend class AssemblerBuffer;
+};
+
+
+class AssemblerBuffer {
+ public:
+  AssemblerBuffer();
+  ~AssemblerBuffer();
+
+  // Basic support for emitting, loading, and storing.
+  template<typename T> void Emit(T value) {
+    CHECK(HasEnsuredCapacity());
+    *reinterpret_cast<T*>(cursor_) = value;
+    cursor_ += sizeof(T);
+  }
+
+  template<typename T> T Load(size_t position) {
+    CHECK_LE(position, Size() - static_cast<int>(sizeof(T)));
+    return *reinterpret_cast<T*>(contents_ + position);
+  }
+
+  template<typename T> void Store(size_t position, T value) {
+    CHECK_LE(position, Size() - static_cast<int>(sizeof(T)));
+    *reinterpret_cast<T*>(contents_ + position) = value;
+  }
+
+  // Emit a fixup at the current location.
+  void EmitFixup(AssemblerFixup* fixup) {
+    fixup->set_previous(fixup_);
+    fixup->set_position(Size());
+    fixup_ = fixup;
+  }
+
+  // Get the size of the emitted code.
+  size_t Size() const {
+    CHECK_GE(cursor_, contents_);
+    return cursor_ - contents_;
+  }
+
+  byte* contents() const { return contents_; }
+
+  // Copy the assembled instructions into the specified memory block
+  // and apply all fixups.
+  void FinalizeInstructions(const MemoryRegion& region);
+
+  // To emit an instruction to the assembler buffer, the EnsureCapacity helper
+  // must be used to guarantee that the underlying data area is big enough to
+  // hold the emitted instruction. Usage:
+  //
+  //     AssemblerBuffer buffer;
+  //     AssemblerBuffer::EnsureCapacity ensured(&buffer);
+  //     ... emit bytes for single instruction ...
+
+#ifdef DEBUG
+
+  class EnsureCapacity {
+   public:
+    explicit EnsureCapacity(AssemblerBuffer* buffer) {
+      if (buffer->cursor() >= buffer->limit()) buffer->ExtendCapacity();
+      // In debug mode, we save the assembler buffer along with the gap
+      // size before we start emitting to the buffer. This allows us to
+      // check that any single generated instruction doesn't overflow the
+      // limit implied by the minimum gap size.
+      buffer_ = buffer;
+      gap_ = ComputeGap();
+      // Make sure that extending the capacity leaves a big enough gap
+      // for any kind of instruction.
+      CHECK_GE(gap_, kMinimumGap);
+      // Mark the buffer as having ensured the capacity.
+      CHECK(!buffer->HasEnsuredCapacity());  // Cannot nest.
+      buffer->has_ensured_capacity_ = true;
+    }
+
+    ~EnsureCapacity() {
+      // Unmark the buffer, so we cannot emit after this.
+      buffer_->has_ensured_capacity_ = false;
+      // Make sure the generated instruction doesn't take up more
+      // space than the minimum gap.
+      int delta = gap_ - ComputeGap();
+      CHECK(delta <= kMinimumGap);
+    }
+
+   private:
+    AssemblerBuffer* buffer_;
+    int gap_;
+
+    int ComputeGap() { return buffer_->Capacity() - buffer_->Size(); }
+  };
+
+  bool has_ensured_capacity_;
+  bool HasEnsuredCapacity() const { return has_ensured_capacity_; }
+
+#else
+
+  class EnsureCapacity {
+   public:
+    explicit EnsureCapacity(AssemblerBuffer* buffer) {
+      if (buffer->cursor() >= buffer->limit()) buffer->ExtendCapacity();
+    }
+  };
+
+  // When building the C++ tests, assertion code is enabled. To allow
+  // asserting that the user of the assembler buffer has ensured the
+  // capacity needed for emitting, we add a dummy method in non-debug mode.
+  bool HasEnsuredCapacity() const { return true; }
+
+#endif
+
+  // Returns the position in the instruction stream.
+  int GetPosition() { return  cursor_ - contents_; }
+
+ private:
+  // The limit is set to kMinimumGap bytes before the end of the data area.
+  // This leaves enough space for the longest possible instruction and allows
+  // for a single, fast space check per instruction.
+  static const int kMinimumGap = 32;
+
+  byte* contents_;
+  byte* cursor_;
+  byte* limit_;
+  AssemblerFixup* fixup_;
+  bool fixups_processed_;
+
+  byte* cursor() const { return cursor_; }
+  byte* limit() const { return limit_; }
+  size_t Capacity() const {
+    CHECK_GE(limit_, contents_);
+    return (limit_ - contents_) + kMinimumGap;
+  }
+
+  // Process the fixup chain starting at the given fixup. The offset is
+  // non-zero for fixups in the body if the preamble is non-empty.
+  void ProcessFixups(const MemoryRegion& region);
+
+  // Compute the limit based on the data area and the capacity. See
+  // description of kMinimumGap for the reasoning behind the value.
+  static byte* ComputeLimit(byte* data, size_t capacity) {
+    return data + capacity - kMinimumGap;
+  }
+
+  void ExtendCapacity();
+
+  friend class AssemblerFixup;
+};
+
+} }  // namespace android::runtime
+
+#if defined(__i386__)
+#include "src/assembler_x86.h"
+#elif defined(__arm__)
+#include "src/assembler_arm.h"
+#endif
+
+#endif  // ART_SRC_ASSEMBLER_H_
diff --git a/src/assembler_arm.cc b/src/assembler_arm.cc
new file mode 100644
index 0000000..79b89c3
--- /dev/null
+++ b/src/assembler_arm.cc
@@ -0,0 +1,8 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/assembler.h"
+
+namespace android {
+namespace runtime {
+
+} }  // namespace android::runtime
diff --git a/src/assembler_arm.h b/src/assembler_arm.h
new file mode 100644
index 0000000..1ac5a82
--- /dev/null
+++ b/src/assembler_arm.h
@@ -0,0 +1,14 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_ASSEMBLER_ARM_H_
+#define ART_SRC_ASSEMBLER_ARM_H_
+
+namespace android {
+namespace runtime {
+
+class Assembler {
+};
+
+} }  // namespace android::runtime
+
+#endif  // ART_SRC_ASSEMBLER_ARM_H_
diff --git a/src/assembler_x86.cc b/src/assembler_x86.cc
new file mode 100644
index 0000000..de2219c
--- /dev/null
+++ b/src/assembler_x86.cc
@@ -0,0 +1,1350 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include <string.h>
+#include "src/assembler.h"
+#include "src/casts.h"
+#include "src/globals.h"
+#include "src/assembler.h"
+#include "src/memory_region.h"
+
+namespace android {
+namespace runtime {
+
+class DirectCallRelocation : public AssemblerFixup {
+ public:
+  void Process(const MemoryRegion& region, int position) {
+    // Direct calls are relative to the following instruction on x86.
+    int32_t pointer = region.Load<int32_t>(position);
+    int32_t start = reinterpret_cast<int32_t>(region.start());
+    int32_t delta = start + position + sizeof(int32_t);
+    region.Store<int32_t>(position, pointer - delta);
+  }
+};
+
+
+void Assembler::InitializeMemoryWithBreakpoints(byte* data, size_t length) {
+  memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
+}
+
+
+void Assembler::call(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitRegisterOperand(2, reg);
+}
+
+
+void Assembler::call(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitOperand(2, address);
+}
+
+
+void Assembler::call(Label* label) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xE8);
+  static const int kSize = 5;
+  EmitLabel(label, kSize);
+}
+
+
+void Assembler::pushl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x50 + reg);
+}
+
+
+void Assembler::pushl(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitOperand(6, address);
+}
+
+
+void Assembler::pushl(const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x68);
+  EmitImmediate(imm);
+}
+
+
+void Assembler::popl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x58 + reg);
+}
+
+
+void Assembler::popl(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x8F);
+  EmitOperand(0, address);
+}
+
+
+void Assembler::movl(Register dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xB8 + dst);
+  EmitImmediate(imm);
+}
+
+
+void Assembler::movl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x89);
+  EmitRegisterOperand(src, dst);
+}
+
+
+void Assembler::movl(Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x8B);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movl(const Address& dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x89);
+  EmitOperand(src, dst);
+}
+
+
+void Assembler::movl(const Address& dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xC7);
+  EmitOperand(0, dst);
+  EmitImmediate(imm);
+}
+
+
+void Assembler::movzxb(Register dst, ByteRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xB6);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::movzxb(Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xB6);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movsxb(Register dst, ByteRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xBE);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::movsxb(Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xBE);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movb(Register dst, const Address& src) {
+  LOG(FATAL) << "Use movzxb or movsxb instead.";
+}
+
+
+void Assembler::movb(const Address& dst, ByteRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x88);
+  EmitOperand(src, dst);
+}
+
+
+void Assembler::movb(const Address& dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xC6);
+  EmitOperand(EAX, dst);
+  CHECK(imm.is_int8());
+  EmitUint8(imm.value() & 0xFF);
+}
+
+
+void Assembler::movzxw(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xB7);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::movzxw(Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xB7);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movsxw(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xBF);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::movsxw(Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xBF);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movw(Register dst, const Address& src) {
+  LOG(FATAL) << "Use movzxw or movsxw instead.";
+}
+
+
+void Assembler::movw(const Address& dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x89);
+  EmitOperand(src, dst);
+}
+
+
+void Assembler::leal(Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x8D);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::cmovs(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x48);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::cmovns(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x49);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::movss(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x10);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movss(const Address& dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x11);
+  EmitOperand(src, dst);
+}
+
+
+void Assembler::movss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x11);
+  EmitXmmRegisterOperand(src, dst);
+}
+
+
+void Assembler::movd(XmmRegister dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0x0F);
+  EmitUint8(0x6E);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::movd(Register dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0x0F);
+  EmitUint8(0x7E);
+  EmitOperand(src, Operand(dst));
+}
+
+
+void Assembler::addss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x58);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::addss(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x58);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::subss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x5C);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::subss(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x5C);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::mulss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x59);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::mulss(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x59);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::divss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x5E);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::divss(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x5E);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::flds(const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitOperand(0, src);
+}
+
+
+void Assembler::fstps(const Address& dst) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitOperand(3, dst);
+}
+
+
+void Assembler::movsd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x10);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::movsd(const Address& dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x11);
+  EmitOperand(src, dst);
+}
+
+
+void Assembler::movsd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x11);
+  EmitXmmRegisterOperand(src, dst);
+}
+
+
+void Assembler::addsd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x58);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::addsd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x58);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::subsd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x5C);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::subsd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x5C);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::mulsd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x59);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::mulsd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x59);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::divsd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x5E);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::divsd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x5E);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::cvtsi2ss(XmmRegister dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x2A);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::cvtsi2sd(XmmRegister dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x2A);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::cvtss2si(Register dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x2D);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::cvtss2sd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x5A);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::cvtsd2si(Register dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x2D);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::cvttss2si(Register dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x2C);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::cvttsd2si(Register dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x2C);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::cvtsd2ss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x5A);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::cvtdq2pd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0xE6);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::comiss(XmmRegister a, XmmRegister b) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x2F);
+  EmitXmmRegisterOperand(a, b);
+}
+
+
+void Assembler::comisd(XmmRegister a, XmmRegister b) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0x0F);
+  EmitUint8(0x2F);
+  EmitXmmRegisterOperand(a, b);
+}
+
+
+void Assembler::sqrtsd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0x0F);
+  EmitUint8(0x51);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::sqrtss(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0x51);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::xorpd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0x0F);
+  EmitUint8(0x57);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::xorpd(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0x0F);
+  EmitUint8(0x57);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::xorps(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x57);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::xorps(XmmRegister dst, XmmRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x57);
+  EmitXmmRegisterOperand(dst, src);
+}
+
+
+void Assembler::andpd(XmmRegister dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0x0F);
+  EmitUint8(0x54);
+  EmitOperand(dst, src);
+}
+
+
+void Assembler::fldl(const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDD);
+  EmitOperand(0, src);
+}
+
+
+void Assembler::fstpl(const Address& dst) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDD);
+  EmitOperand(3, dst);
+}
+
+
+void Assembler::fnstcw(const Address& dst) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitOperand(7, dst);
+}
+
+
+void Assembler::fldcw(const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitOperand(5, src);
+}
+
+
+void Assembler::fistpl(const Address& dst) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDF);
+  EmitOperand(7, dst);
+}
+
+
+void Assembler::fistps(const Address& dst) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDB);
+  EmitOperand(3, dst);
+}
+
+
+void Assembler::fildl(const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDF);
+  EmitOperand(5, src);
+}
+
+
+void Assembler::fincstp() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitUint8(0xF7);
+}
+
+
+void Assembler::ffree(const Immediate& index) {
+  CHECK_LT(index.value(), 7);
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDD);
+  EmitUint8(0xC0 + index.value());
+}
+
+
+void Assembler::fsin() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitUint8(0xFE);
+}
+
+
+void Assembler::fcos() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitUint8(0xFF);
+}
+
+
+void Assembler::fptan() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xD9);
+  EmitUint8(0xF2);
+}
+
+
+void Assembler::xchgl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x87);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::cmpl(Register reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(7, Operand(reg), imm);
+}
+
+
+void Assembler::cmpl(Register reg0, Register reg1) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x3B);
+  EmitOperand(reg0, Operand(reg1));
+}
+
+
+void Assembler::cmpl(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x3B);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::addl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x03);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::addl(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x03);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::cmpl(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x39);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::cmpl(const Address& address, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(7, address, imm);
+}
+
+
+void Assembler::testl(Register reg1, Register reg2) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x85);
+  EmitRegisterOperand(reg1, reg2);
+}
+
+
+void Assembler::testl(Register reg, const Immediate& immediate) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  // For registers that have a byte variant (EAX, EBX, ECX, and EDX)
+  // we only test the byte register to keep the encoding short.
+  if (immediate.is_uint8() && reg < 4) {
+    // Use zero-extended 8-bit immediate.
+    if (reg == EAX) {
+      EmitUint8(0xA8);
+    } else {
+      EmitUint8(0xF6);
+      EmitUint8(0xC0 + reg);
+    }
+    EmitUint8(immediate.value() & 0xFF);
+  } else if (reg == EAX) {
+    // Use short form if the destination is EAX.
+    EmitUint8(0xA9);
+    EmitImmediate(immediate);
+  } else {
+    EmitUint8(0xF7);
+    EmitOperand(0, Operand(reg));
+    EmitImmediate(immediate);
+  }
+}
+
+
+void Assembler::andl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x23);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::andl(Register dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(4, Operand(dst), imm);
+}
+
+
+void Assembler::orl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0B);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::orl(Register dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(1, Operand(dst), imm);
+}
+
+
+void Assembler::xorl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x33);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::addl(Register reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(0, Operand(reg), imm);
+}
+
+
+void Assembler::addl(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x01);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::addl(const Address& address, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(0, address, imm);
+}
+
+
+void Assembler::adcl(Register reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(2, Operand(reg), imm);
+}
+
+
+void Assembler::adcl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x13);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::adcl(Register dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x13);
+  EmitOperand(dst, address);
+}
+
+
+void Assembler::subl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x2B);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::subl(Register reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(5, Operand(reg), imm);
+}
+
+
+void Assembler::subl(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x2B);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::cdq() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x99);
+}
+
+
+void Assembler::idivl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitUint8(0xF8 | reg);
+}
+
+
+void Assembler::imull(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xAF);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::imull(Register reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x69);
+  EmitOperand(reg, Operand(reg));
+  EmitImmediate(imm);
+}
+
+
+void Assembler::imull(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xAF);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::imull(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitOperand(5, Operand(reg));
+}
+
+
+void Assembler::imull(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitOperand(5, address);
+}
+
+
+void Assembler::mull(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitOperand(4, Operand(reg));
+}
+
+
+void Assembler::mull(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitOperand(4, address);
+}
+
+
+void Assembler::sbbl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x1B);
+  EmitOperand(dst, Operand(src));
+}
+
+
+void Assembler::sbbl(Register reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitComplex(3, Operand(reg), imm);
+}
+
+
+void Assembler::sbbl(Register dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x1B);
+  EmitOperand(dst, address);
+}
+
+
+void Assembler::incl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x40 + reg);
+}
+
+
+void Assembler::incl(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitOperand(0, address);
+}
+
+
+void Assembler::decl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x48 + reg);
+}
+
+
+void Assembler::decl(const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitOperand(1, address);
+}
+
+
+void Assembler::shll(Register reg, const Immediate& imm) {
+  EmitGenericShift(4, reg, imm);
+}
+
+
+void Assembler::shll(Register operand, Register shifter) {
+  EmitGenericShift(4, operand, shifter);
+}
+
+
+void Assembler::shrl(Register reg, const Immediate& imm) {
+  EmitGenericShift(5, reg, imm);
+}
+
+
+void Assembler::shrl(Register operand, Register shifter) {
+  EmitGenericShift(5, operand, shifter);
+}
+
+
+void Assembler::sarl(Register reg, const Immediate& imm) {
+  EmitGenericShift(7, reg, imm);
+}
+
+
+void Assembler::sarl(Register operand, Register shifter) {
+  EmitGenericShift(7, operand, shifter);
+}
+
+
+void Assembler::shld(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xA5);
+  EmitRegisterOperand(src, dst);
+}
+
+
+void Assembler::negl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitOperand(3, Operand(reg));
+}
+
+
+void Assembler::notl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF7);
+  EmitUint8(0xD0 | reg);
+}
+
+
+void Assembler::enter(const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xC8);
+  CHECK(imm.is_uint16());
+  EmitUint8(imm.value() & 0xFF);
+  EmitUint8((imm.value() >> 8) & 0xFF);
+  EmitUint8(0x00);
+}
+
+
+void Assembler::leave() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xC9);
+}
+
+
+void Assembler::ret() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xC3);
+}
+
+
+void Assembler::ret(const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xC2);
+  CHECK(imm.is_uint16());
+  EmitUint8(imm.value() & 0xFF);
+  EmitUint8((imm.value() >> 8) & 0xFF);
+}
+
+
+
+void Assembler::nop() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x90);
+}
+
+
+void Assembler::int3() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xCC);
+}
+
+
+void Assembler::hlt() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF4);
+}
+
+
+void Assembler::j(Condition condition, Label* label) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  if (label->IsBound()) {
+    static const int kShortSize = 2;
+    static const int kLongSize = 6;
+    int offset = label->Position() - buffer_.Size();
+    CHECK_LE(offset, 0);
+    if (IsInt(8, offset - kShortSize)) {
+      EmitUint8(0x70 + condition);
+      EmitUint8((offset - kShortSize) & 0xFF);
+    } else {
+      EmitUint8(0x0F);
+      EmitUint8(0x80 + condition);
+      EmitInt32(offset - kLongSize);
+    }
+  } else {
+    EmitUint8(0x0F);
+    EmitUint8(0x80 + condition);
+    EmitLabelLink(label);
+  }
+}
+
+
+void Assembler::jmp(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xFF);
+  EmitRegisterOperand(4, reg);
+}
+
+
+void Assembler::jmp(Label* label) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  if (label->IsBound()) {
+    static const int kShortSize = 2;
+    static const int kLongSize = 5;
+    int offset = label->Position() - buffer_.Size();
+    CHECK_LE(offset, 0);
+    if (IsInt(8, offset - kShortSize)) {
+      EmitUint8(0xEB);
+      EmitUint8((offset - kShortSize) & 0xFF);
+    } else {
+      EmitUint8(0xE9);
+      EmitInt32(offset - kLongSize);
+    }
+  } else {
+    EmitUint8(0xE9);
+    EmitLabelLink(label);
+  }
+}
+
+
+void Assembler::lock() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF0);
+}
+
+
+void Assembler::cmpxchgl(const Address& address, Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xB1);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::AddImmediate(Register reg, const Immediate& imm) {
+  int value = imm.value();
+  if (value > 0) {
+    if (value == 1) {
+      incl(reg);
+    } else if (value != 0) {
+      addl(reg, imm);
+    }
+  } else if (value < 0) {
+    value = -value;
+    if (value == 1) {
+      decl(reg);
+    } else if (value != 0) {
+      subl(reg, Immediate(value));
+    }
+  }
+}
+
+
+void Assembler::LoadDoubleConstant(XmmRegister dst, double value) {
+  // TODO: Need to have a code constants table.
+  int64_t constant = bit_cast<int64_t, double>(value);
+  pushl(Immediate(High32Bits(constant)));
+  pushl(Immediate(Low32Bits(constant)));
+  movsd(dst, Address(ESP, 0));
+  addl(ESP, Immediate(2 * kWordSize));
+}
+
+
+void Assembler::FloatNegate(XmmRegister f) {
+  static const struct {
+    uint32_t a;
+    uint32_t b;
+    uint32_t c;
+    uint32_t d;
+  } float_negate_constant __attribute__((aligned(16))) =
+      { 0x80000000, 0x00000000, 0x80000000, 0x00000000 };
+  xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant)));
+}
+
+
+void Assembler::DoubleNegate(XmmRegister d) {
+  static const struct {
+    uint64_t a;
+    uint64_t b;
+  } double_negate_constant __attribute__((aligned(16))) =
+      {0x8000000000000000LL, 0x8000000000000000LL};
+  xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant)));
+}
+
+
+void Assembler::DoubleAbs(XmmRegister reg) {
+  static const struct {
+    uint64_t a;
+    uint64_t b;
+  } double_abs_constant __attribute__((aligned(16))) =
+      {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
+  andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant)));
+}
+
+
+void Assembler::Align(int alignment, int offset) {
+  CHECK(IsPowerOfTwo(alignment));
+  // Emit nop instruction until the real position is aligned.
+  while (((offset + buffer_.GetPosition()) & (alignment-1)) != 0) {
+    nop();
+  }
+}
+
+
+void Assembler::Bind(Label* label) {
+  int bound = buffer_.Size();
+  CHECK(!label->IsBound());  // Labels can only be bound once.
+  while (label->IsLinked()) {
+    int position = label->LinkPosition();
+    int next = buffer_.Load<int32_t>(position);
+    buffer_.Store<int32_t>(position, bound - (position + 4));
+    label->position_ = next;
+  }
+  label->BindTo(bound);
+}
+
+
+void Assembler::Stop(const char* message) {
+  // Emit the message address as immediate operand in the test rax instruction,
+  // followed by the int3 instruction.
+  // Execution can be resumed with the 'cont' command in gdb.
+  testl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
+  int3();
+}
+
+
+void Assembler::EmitOperand(int rm, const Operand& operand) {
+  CHECK_GE(rm, 0);
+  CHECK_LT(rm, 8);
+  const int length = operand.length_;
+  CHECK_GT(length, 0);
+  // Emit the ModRM byte updated with the given RM value.
+  CHECK_EQ(operand.encoding_[0] & 0x38, 0);
+  EmitUint8(operand.encoding_[0] + (rm << 3));
+  // Emit the rest of the encoded operand.
+  for (int i = 1; i < length; i++) {
+    EmitUint8(operand.encoding_[i]);
+  }
+}
+
+
+void Assembler::EmitImmediate(const Immediate& imm) {
+  EmitInt32(imm.value());
+}
+
+
+void Assembler::EmitComplex(int rm,
+                            const Operand& operand,
+                            const Immediate& immediate) {
+  CHECK_GE(rm, 0);
+  CHECK_LT(rm, 8);
+  if (immediate.is_int8()) {
+    // Use sign-extended 8-bit immediate.
+    EmitUint8(0x83);
+    EmitOperand(rm, operand);
+    EmitUint8(immediate.value() & 0xFF);
+  } else if (operand.IsRegister(EAX)) {
+    // Use short form if the destination is eax.
+    EmitUint8(0x05 + (rm << 3));
+    EmitImmediate(immediate);
+  } else {
+    EmitUint8(0x81);
+    EmitOperand(rm, operand);
+    EmitImmediate(immediate);
+  }
+}
+
+
+void Assembler::EmitLabel(Label* label, int instruction_size) {
+  if (label->IsBound()) {
+    int offset = label->Position() - buffer_.Size();
+    CHECK_LE(offset, 0);
+    EmitInt32(offset - instruction_size);
+  } else {
+    EmitLabelLink(label);
+  }
+}
+
+
+void Assembler::EmitLabelLink(Label* label) {
+  CHECK(!label->IsBound());
+  int position = buffer_.Size();
+  EmitInt32(label->position_);
+  label->LinkTo(position);
+}
+
+
+void Assembler::EmitGenericShift(int rm,
+                                 Register reg,
+                                 const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  CHECK(imm.is_int8());
+  if (imm.value() == 1) {
+    EmitUint8(0xD1);
+    EmitOperand(rm, Operand(reg));
+  } else {
+    EmitUint8(0xC1);
+    EmitOperand(rm, Operand(reg));
+    EmitUint8(imm.value() & 0xFF);
+  }
+}
+
+
+void Assembler::EmitGenericShift(int rm,
+                                 Register operand,
+                                 Register shifter) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  CHECK_EQ(shifter, ECX);
+  EmitUint8(0xD3);
+  EmitOperand(rm, Operand(operand));
+}
+
+} }  // namespace android::runtime
diff --git a/src/assembler_x86.h b/src/assembler_x86.h
new file mode 100644
index 0000000..05dfe31
--- /dev/null
+++ b/src/assembler_x86.h
@@ -0,0 +1,479 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_ASSEMBLER_X86_H_
+#define ART_SRC_ASSEMBLER_X86_H_
+
+#include <stdint.h>
+#include <string.h>
+#include "src/constants_x86.h"
+#include "src/macros.h"
+#include "src/utils.h"
+
+namespace android {
+namespace runtime {
+
+class Immediate {
+ public:
+  explicit Immediate(int32_t value) : value_(value) {}
+
+  int32_t value() const { return value_; }
+
+  bool is_int8() const { return IsInt(8, value_); }
+  bool is_uint8() const { return IsUint(8, value_); }
+  bool is_uint16() const { return IsUint(16, value_); }
+
+ private:
+  const int32_t value_;
+
+  DISALLOW_COPY_AND_ASSIGN(Immediate);
+};
+
+
+class Operand {
+ public:
+  uint8_t mod() const {
+    return (encoding_at(0) >> 6) & 3;
+  }
+
+  Register rm() const {
+    return static_cast<Register>(encoding_at(0) & 7);
+  }
+
+  ScaleFactor scale() const {
+    return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
+  }
+
+  Register index() const {
+    return static_cast<Register>((encoding_at(1) >> 3) & 7);
+  }
+
+  Register base() const {
+    return static_cast<Register>(encoding_at(1) & 7);
+  }
+
+  int8_t disp8() const {
+    CHECK_GE(length_, 2);
+    return static_cast<int8_t>(encoding_[length_ - 1]);
+  }
+
+  int32_t disp32() const {
+    CHECK_GE(length_, 5);
+    int32_t value;
+    memcpy(&value, &encoding_[length_ - 4], sizeof(value));
+    return value;
+  }
+
+  bool IsRegister(Register reg) const {
+    return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
+        && ((encoding_[0] & 0x07) == reg);  // Register codes match.
+  }
+
+ protected:
+  // Operand can be sub classed (e.g: Address).
+  Operand() : length_(0) { }
+
+  void SetModRM(int mod, Register rm) {
+    CHECK_EQ(mod & ~3, 0);
+    encoding_[0] = (mod << 6) | rm;
+    length_ = 1;
+  }
+
+  void SetSIB(ScaleFactor scale, Register index, Register base) {
+    CHECK_EQ(length_, 1);
+    CHECK_EQ(scale & ~3, 0);
+    encoding_[1] = (scale << 6) | (index << 3) | base;
+    length_ = 2;
+  }
+
+  void SetDisp8(int8_t disp) {
+    CHECK(length_ == 1 || length_ == 2);
+    encoding_[length_++] = static_cast<uint8_t>(disp);
+  }
+
+  void SetDisp32(int32_t disp) {
+    CHECK(length_ == 1 || length_ == 2);
+    int disp_size = sizeof(disp);
+    memmove(&encoding_[length_], &disp, disp_size);
+    length_ += disp_size;
+  }
+
+ private:
+  byte length_;
+  byte encoding_[6];
+  byte padding_;
+
+  explicit Operand(Register reg) { SetModRM(3, reg); }
+
+  // Get the operand encoding byte at the given index.
+  uint8_t encoding_at(int index) const {
+    CHECK_GE(index, 0);
+    CHECK_LT(index, length_);
+    return encoding_[index];
+  }
+
+  friend class Assembler;
+
+  DISALLOW_COPY_AND_ASSIGN(Operand);
+};
+
+
+class Address : public Operand {
+ public:
+  Address(Register base, int32_t disp) {
+    if (disp == 0 && base != EBP) {
+      SetModRM(0, base);
+      if (base == ESP) SetSIB(TIMES_1, ESP, base);
+    } else if (disp >= -128 && disp <= 127) {
+      SetModRM(1, base);
+      if (base == ESP) SetSIB(TIMES_1, ESP, base);
+      SetDisp8(disp);
+    } else {
+      SetModRM(2, base);
+      if (base == ESP) SetSIB(TIMES_1, ESP, base);
+      SetDisp32(disp);
+    }
+  }
+
+  Address(Register index, ScaleFactor scale, int32_t disp) {
+    CHECK_NE(index, ESP);  // Illegal addressing mode.
+    SetModRM(0, ESP);
+    SetSIB(scale, index, EBP);
+    SetDisp32(disp);
+  }
+
+  Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
+    CHECK_NE(index, ESP);  // Illegal addressing mode.
+    if (disp == 0 && base != EBP) {
+      SetModRM(0, ESP);
+      SetSIB(scale, index, base);
+    } else if (disp >= -128 && disp <= 127) {
+      SetModRM(1, ESP);
+      SetSIB(scale, index, base);
+      SetDisp8(disp);
+    } else {
+      SetModRM(2, ESP);
+      SetSIB(scale, index, base);
+      SetDisp32(disp);
+    }
+  }
+
+  static Address Absolute(const uword addr) {
+    Address result;
+    result.SetModRM(0, EBP);
+    result.SetDisp32(addr);
+    return result;
+  }
+
+ private:
+  Address() {}
+
+  DISALLOW_COPY_AND_ASSIGN(Address);
+};
+
+
+class Assembler {
+ public:
+  Assembler() : buffer_() {}
+  ~Assembler() {}
+
+  /*
+   * Emit Machine Instructions.
+   */
+  void call(Register reg);
+  void call(const Address& address);
+  void call(Label* label);
+
+  void pushl(Register reg);
+  void pushl(const Address& address);
+  void pushl(const Immediate& imm);
+
+  void popl(Register reg);
+  void popl(const Address& address);
+
+  void movl(Register dst, const Immediate& src);
+  void movl(Register dst, Register src);
+
+  void movl(Register dst, const Address& src);
+  void movl(const Address& dst, Register src);
+  void movl(const Address& dst, const Immediate& imm);
+
+  void movzxb(Register dst, ByteRegister src);
+  void movzxb(Register dst, const Address& src);
+  void movsxb(Register dst, ByteRegister src);
+  void movsxb(Register dst, const Address& src);
+  void movb(Register dst, const Address& src);
+  void movb(const Address& dst, ByteRegister src);
+  void movb(const Address& dst, const Immediate& imm);
+
+  void movzxw(Register dst, Register src);
+  void movzxw(Register dst, const Address& src);
+  void movsxw(Register dst, Register src);
+  void movsxw(Register dst, const Address& src);
+  void movw(Register dst, const Address& src);
+  void movw(const Address& dst, Register src);
+
+  void leal(Register dst, const Address& src);
+
+  void cmovs(Register dst, Register src);
+  void cmovns(Register dst, Register src);
+
+  void movss(XmmRegister dst, const Address& src);
+  void movss(const Address& dst, XmmRegister src);
+  void movss(XmmRegister dst, XmmRegister src);
+
+  void movd(XmmRegister dst, Register src);
+  void movd(Register dst, XmmRegister src);
+
+  void addss(XmmRegister dst, XmmRegister src);
+  void addss(XmmRegister dst, const Address& src);
+  void subss(XmmRegister dst, XmmRegister src);
+  void subss(XmmRegister dst, const Address& src);
+  void mulss(XmmRegister dst, XmmRegister src);
+  void mulss(XmmRegister dst, const Address& src);
+  void divss(XmmRegister dst, XmmRegister src);
+  void divss(XmmRegister dst, const Address& src);
+
+  void movsd(XmmRegister dst, const Address& src);
+  void movsd(const Address& dst, XmmRegister src);
+  void movsd(XmmRegister dst, XmmRegister src);
+
+  void addsd(XmmRegister dst, XmmRegister src);
+  void addsd(XmmRegister dst, const Address& src);
+  void subsd(XmmRegister dst, XmmRegister src);
+  void subsd(XmmRegister dst, const Address& src);
+  void mulsd(XmmRegister dst, XmmRegister src);
+  void mulsd(XmmRegister dst, const Address& src);
+  void divsd(XmmRegister dst, XmmRegister src);
+  void divsd(XmmRegister dst, const Address& src);
+
+  void cvtsi2ss(XmmRegister dst, Register src);
+  void cvtsi2sd(XmmRegister dst, Register src);
+
+  void cvtss2si(Register dst, XmmRegister src);
+  void cvtss2sd(XmmRegister dst, XmmRegister src);
+
+  void cvtsd2si(Register dst, XmmRegister src);
+  void cvtsd2ss(XmmRegister dst, XmmRegister src);
+
+  void cvttss2si(Register dst, XmmRegister src);
+  void cvttsd2si(Register dst, XmmRegister src);
+
+  void cvtdq2pd(XmmRegister dst, XmmRegister src);
+
+  void comiss(XmmRegister a, XmmRegister b);
+  void comisd(XmmRegister a, XmmRegister b);
+
+  void sqrtsd(XmmRegister dst, XmmRegister src);
+  void sqrtss(XmmRegister dst, XmmRegister src);
+
+  void xorpd(XmmRegister dst, const Address& src);
+  void xorpd(XmmRegister dst, XmmRegister src);
+  void xorps(XmmRegister dst, const Address& src);
+  void xorps(XmmRegister dst, XmmRegister src);
+
+  void andpd(XmmRegister dst, const Address& src);
+
+  void flds(const Address& src);
+  void fstps(const Address& dst);
+
+  void fldl(const Address& src);
+  void fstpl(const Address& dst);
+
+  void fnstcw(const Address& dst);
+  void fldcw(const Address& src);
+
+  void fistpl(const Address& dst);
+  void fistps(const Address& dst);
+  void fildl(const Address& src);
+
+  void fincstp();
+  void ffree(const Immediate& index);
+
+  void fsin();
+  void fcos();
+  void fptan();
+
+  void xchgl(Register dst, Register src);
+
+  void cmpl(Register reg, const Immediate& imm);
+  void cmpl(Register reg0, Register reg1);
+  void cmpl(Register reg, const Address& address);
+
+  void cmpl(const Address& address, Register reg);
+  void cmpl(const Address& address, const Immediate& imm);
+
+  void testl(Register reg1, Register reg2);
+  void testl(Register reg, const Immediate& imm);
+
+  void andl(Register dst, const Immediate& imm);
+  void andl(Register dst, Register src);
+
+  void orl(Register dst, const Immediate& imm);
+  void orl(Register dst, Register src);
+
+  void xorl(Register dst, Register src);
+
+  void addl(Register dst, Register src);
+  void addl(Register reg, const Immediate& imm);
+  void addl(Register reg, const Address& address);
+
+  void addl(const Address& address, Register reg);
+  void addl(const Address& address, const Immediate& imm);
+
+  void adcl(Register dst, Register src);
+  void adcl(Register reg, const Immediate& imm);
+  void adcl(Register dst, const Address& address);
+
+  void subl(Register dst, Register src);
+  void subl(Register reg, const Immediate& imm);
+  void subl(Register reg, const Address& address);
+
+  void cdq();
+
+  void idivl(Register reg);
+
+  void imull(Register dst, Register src);
+  void imull(Register reg, const Immediate& imm);
+  void imull(Register reg, const Address& address);
+
+  void imull(Register reg);
+  void imull(const Address& address);
+
+  void mull(Register reg);
+  void mull(const Address& address);
+
+  void sbbl(Register dst, Register src);
+  void sbbl(Register reg, const Immediate& imm);
+  void sbbl(Register reg, const Address& address);
+
+  void incl(Register reg);
+  void incl(const Address& address);
+
+  void decl(Register reg);
+  void decl(const Address& address);
+
+  void shll(Register reg, const Immediate& imm);
+  void shll(Register operand, Register shifter);
+  void shrl(Register reg, const Immediate& imm);
+  void shrl(Register operand, Register shifter);
+  void sarl(Register reg, const Immediate& imm);
+  void sarl(Register operand, Register shifter);
+  void shld(Register dst, Register src);
+
+  void negl(Register reg);
+  void notl(Register reg);
+
+  void enter(const Immediate& imm);
+  void leave();
+
+  void ret();
+  void ret(const Immediate& imm);
+
+  void nop();
+  void int3();
+  void hlt();
+
+  void j(Condition condition, Label* label);
+
+  void jmp(Register reg);
+  void jmp(Label* label);
+
+  void lock();
+  void cmpxchgl(const Address& address, Register reg);
+
+  /*
+   * Macros for High-level operations.
+   */
+  void AddImmediate(Register reg, const Immediate& imm);
+
+  void LoadDoubleConstant(XmmRegister dst, double value);
+
+  void DoubleNegate(XmmRegister d);
+  void FloatNegate(XmmRegister f);
+
+  void DoubleAbs(XmmRegister reg);
+
+  void LockCmpxchgl(const Address& address, Register reg) {
+    lock();
+    cmpxchgl(address, reg);
+  }
+
+  /*
+   * Misc. functionality
+   */
+  int PreferredLoopAlignment() { return 16; }
+  void Align(int alignment, int offset);
+  void Bind(Label* label);
+
+  int CodeSize() const { return buffer_.Size(); }
+
+  void FinalizeInstructions(const MemoryRegion& region) {
+    buffer_.FinalizeInstructions(region);
+  }
+
+  // Debugging and bringup support.
+  void Stop(const char* message);
+  void Unimplemented(const char* message);
+  void Untested(const char* message);
+  void Unreachable(const char* message);
+
+  static void InitializeMemoryWithBreakpoints(byte* data, size_t length);
+
+ private:
+  AssemblerBuffer buffer_;
+
+  inline void EmitUint8(uint8_t value);
+  inline void EmitInt32(int32_t value);
+  inline void EmitRegisterOperand(int rm, int reg);
+  inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
+  inline void EmitFixup(AssemblerFixup* fixup);
+  inline void EmitOperandSizeOverride();
+
+  void EmitOperand(int rm, const Operand& operand);
+  void EmitImmediate(const Immediate& imm);
+  void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
+  void EmitLabel(Label* label, int instruction_size);
+  void EmitLabelLink(Label* label);
+  void EmitNearLabelLink(Label* label);
+
+  void EmitGenericShift(int rm, Register reg, const Immediate& imm);
+  void EmitGenericShift(int rm, Register operand, Register shifter);
+
+  DISALLOW_COPY_AND_ASSIGN(Assembler);
+};
+
+
+inline void Assembler::EmitUint8(uint8_t value) {
+  buffer_.Emit<uint8_t>(value);
+}
+
+
+inline void Assembler::EmitInt32(int32_t value) {
+  buffer_.Emit<int32_t>(value);
+}
+
+
+inline void Assembler::EmitRegisterOperand(int rm, int reg) {
+  CHECK_GE(rm, 0);
+  CHECK_LT(rm, 8);
+  buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
+}
+
+
+inline void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
+  EmitRegisterOperand(rm, static_cast<Register>(reg));
+}
+
+
+inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
+  buffer_.EmitFixup(fixup);
+}
+
+
+inline void Assembler::EmitOperandSizeOverride() {
+  EmitUint8(0x66);
+}
+
+} }  // namespace android::runtime
+
+#endif  // ART_SRC_ASSEMBLER_X86_H_
diff --git a/src/casts.h b/src/casts.h
new file mode 100644
index 0000000..f9f3c6b
--- /dev/null
+++ b/src/casts.h
@@ -0,0 +1,24 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_CASTS_H_
+#define ART_SRC_CASTS_H_
+
+#include <string.h>
+#include "src/macros.h"
+
+namespace android {
+namespace runtime {
+
+template <class Dest, class Source>
+inline Dest bit_cast(const Source& source) {
+  // Compile time assertion: sizeof(Dest) == sizeof(Source)
+  // A compile error here means your Dest and Source have different sizes.
+  COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), verify_sizes_are_equal);
+  Dest dest;
+  memcpy(&dest, &source, sizeof(dest));
+  return dest;
+}
+
+} }  // namespace android::runtime
+
+#endif  // ART_SRC_CASTS_H_
diff --git a/src/constants_x86.h b/src/constants_x86.h
new file mode 100644
index 0000000..477bef8
--- /dev/null
+++ b/src/constants_x86.h
@@ -0,0 +1,112 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_CONSTANTS_X86_H_
+#define ART_SRC_CONSTANTS_X86_H_
+
+#include "src/globals.h"
+#include "src/logging.h"
+#include "src/macros.h"
+
+namespace android {
+namespace runtime {
+
+enum Register {
+  EAX = 0,
+  ECX = 1,
+  EDX = 2,
+  EBX = 3,
+  ESP = 4,
+  EBP = 5,
+  ESI = 6,
+  EDI = 7,
+  kNumberOfCpuRegisters = 8,
+  kFirstByteUnsafeRegister = 4,
+  kNoRegister = -1  // Signals an illegal register.
+};
+
+
+enum ByteRegister {
+  AL = 0,
+  CL = 1,
+  DL = 2,
+  BL = 3,
+  AH = 4,
+  CH = 5,
+  DH = 6,
+  BH = 7,
+  kNoByteRegister = -1  // Signals an illegal register.
+};
+
+
+enum XmmRegister {
+  XMM0 = 0,
+  XMM1 = 1,
+  XMM2 = 2,
+  XMM3 = 3,
+  XMM4 = 4,
+  XMM5 = 5,
+  XMM6 = 6,
+  XMM7 = 7,
+  kNumberOfXmmRegisters = 8,
+  kNoXmmRegister = -1  // Signals an illegal register.
+};
+
+
+enum ScaleFactor {
+  TIMES_1 = 0,
+  TIMES_2 = 1,
+  TIMES_4 = 2,
+  TIMES_8 = 3
+};
+
+
+enum Condition {
+  OVERFLOW      =  0,
+  NO_OVERFLOW   =  1,
+  BELOW         =  2,
+  ABOVE_EQUAL   =  3,
+  EQUAL         =  4,
+  NOT_EQUAL     =  5,
+  BELOW_EQUAL   =  6,
+  ABOVE         =  7,
+  SIGN          =  8,
+  NOT_SIGN      =  9,
+  PARITY_EVEN   = 10,
+  PARITY_ODD    = 11,
+  LESS          = 12,
+  GREATER_EQUAL = 13,
+  LESS_EQUAL    = 14,
+  GREATER       = 15,
+
+  ZERO          = EQUAL,
+  NOT_ZERO      = NOT_EQUAL,
+  NEGATIVE      = SIGN,
+  POSITIVE      = NOT_SIGN
+};
+
+
+class Instr {
+ public:
+  static const uint8_t kHltInstruction = 0xF4;
+  // We prefer not to use the int3 instruction since it conflicts with gdb.
+  static const uint8_t kBreakPointInstruction = kHltInstruction;
+  static const int kBreakPointInstructionSize = 1;
+
+  bool IsBreakPoint() {
+    CHECK_EQ(kBreakPointInstructionSize, 1);
+    return (*reinterpret_cast<const uint8_t*>(this)) == kBreakPointInstruction;
+  }
+
+  // Instructions are read out of a code stream. The only way to get a
+  // reference to an instruction is to convert a pointer. There is no way
+  // to allocate or create instances of class Instr.
+  // Use the At(pc) function to create references to Instr.
+  static Instr* At(uintptr_t pc) { return reinterpret_cast<Instr*>(pc); }
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
+};
+
+} }  // namespace android::runtime
+
+#endif  // ART_CONSTANTS_IA32_H_
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 0000000..2f85270
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,37 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_GLOBALS_H_
+#define ART_SRC_GLOBALS_H_
+
+#include <stdint.h>
+
+namespace android {
+namespace runtime {
+
+typedef uint8_t byte;
+typedef intptr_t word;
+typedef uintptr_t uword;
+
+const int KB = 1024;
+const int MB = KB * KB;
+const int GB = KB * KB * KB;
+const int kMaxInt = 0x7FFFFFFF;
+const int kMinInt = -kMaxInt - 1;
+
+const int kCharSize = sizeof(char);
+const int kShortSize = sizeof(short);
+const int kIntSize = sizeof(int);
+const int kDoubleSize = sizeof(double);
+const int kIntptrSize = sizeof(intptr_t);
+const int kWordSize = sizeof(word);
+const int kPointerSize = sizeof(void*);
+
+const int kBitsPerByte = 8;
+const int kBitsPerByteLog2 = 3;
+const int kBitsPerPointer = kPointerSize * kBitsPerByte;
+const int kBitsPerWord = kWordSize * kBitsPerWord;
+const int kBitsPerInt = kIntSize * kBitsPerByte;
+
+} }  // namespace android::runtime
+
+#endif  // ART_SRC_GLOBALS_H_
diff --git a/src/logging.h b/src/logging.h
index 2c05382..c1896e9 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -74,6 +74,7 @@
 #endif
 
 #define LOG_INFO LogMessage(__FILE__, __LINE__)
+#define LOG_FATAL LogMessageFatal(__FILE__, __LINE__)
 #define LOG(severity) LOG_ ## severity.stream()
 #define LG LOG(INFO)
 
diff --git a/src/macros.h b/src/macros.h
index 95c2590..c2a474e 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -14,6 +14,28 @@
 #ifndef ART_MACROS_H_
 #define ART_MACROS_H_
 
+// The COMPILE_ASSERT macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                  content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define COMPILE_ASSERT(expr, msg) \
+  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
 // DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
 // It goes in the private: declarations in a class.
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
diff --git a/src/memory_region.cc b/src/memory_region.cc
new file mode 100644
index 0000000..1fa5d1f
--- /dev/null
+++ b/src/memory_region.cc
@@ -0,0 +1,21 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include <stdint.h>
+#include <string.h>
+#include "src/globals.h"
+#include "src/logging.h"
+#include "src/memory_region.h"
+
+namespace android {
+namespace runtime {
+
+void MemoryRegion::CopyFrom(size_t offset, const MemoryRegion& from) const {
+  CHECK_NE(from.pointer(), NULL);
+  CHECK_GT(from.size(), 0);
+  CHECK_GE(this->size(), from.size());
+  CHECK_LE(offset, this->size() - from.size());
+  memmove(reinterpret_cast<void*>(start() + offset),
+          from.pointer(), from.size());
+}
+
+} }  // namespace android::runtime
diff --git a/src/memory_region.h b/src/memory_region.h
new file mode 100644
index 0000000..da79fbd
--- /dev/null
+++ b/src/memory_region.h
@@ -0,0 +1,86 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_MEMORY_REGION_H_
+#define ART_SRC_MEMORY_REGION_H_
+
+#include <stdint.h>
+#include "src/globals.h"
+#include "src/logging.h"
+#include "src/macros.h"
+#include "src/memory_region.h"
+
+namespace android {
+namespace runtime {
+
+// Memory regions are useful for accessing memory with bounds check in
+// debug mode. They can be safely passed by value and do not assume ownership
+// of the region.
+class MemoryRegion {
+ public:
+  MemoryRegion() : pointer_(NULL), size_(0) {}
+  MemoryRegion(void* pointer, uword size) : pointer_(pointer), size_(size) {}
+
+  void* pointer() const { return pointer_; }
+  size_t size() const { return size_; }
+  size_t size_in_bits() const { return size_ * kBitsPerByte; }
+
+  static size_t pointer_offset() {
+    return OFFSETOF_MEMBER(MemoryRegion, pointer_);
+  }
+
+  byte* start() const { return reinterpret_cast<byte*>(pointer_); }
+  byte* end() const { return start() + size_; }
+
+  template<typename T> T Load(uintptr_t offset) const {
+    return *ComputeInternalPointer<T>(offset);
+  }
+
+  template<typename T> void Store(uintptr_t offset, T value) const {
+    *ComputeInternalPointer<T>(offset) = value;
+  }
+
+  template<typename T> T* PointerTo(uintptr_t offset) const {
+    return ComputeInternalPointer<T>(offset);
+  }
+
+  void CopyFrom(size_t offset, const MemoryRegion& from) const;
+
+  // Compute a sub memory region based on an existing one.
+  void Subregion(const MemoryRegion& from, uintptr_t offset, uintptr_t size) {
+    CHECK_GE(from.size(), size);
+    CHECK_LE(offset,  from.size() - size);
+    pointer_ = reinterpret_cast<void*>(from.start() + offset);
+    size_ = size;
+  }
+
+  // Compute an extended memory region based on an existing one.
+  void Extend(const MemoryRegion& region, uintptr_t extra) {
+    pointer_ = region.pointer();
+    size_ = (region.size() + extra);
+  }
+
+ private:
+  template<typename T> T* ComputeInternalPointer(size_t offset) const {
+    CHECK_GE(size(), sizeof(T));
+    CHECK_LE(offset, size() - sizeof(T));
+    return reinterpret_cast<T*>(start() + offset);
+  }
+
+  // Locate the bit with the given offset. Returns a pointer to the byte
+  // containing the bit, and sets bit_mask to the bit within that byte.
+  byte* ComputeBitPointer(uintptr_t bit_offset, byte* bit_mask) const {
+    uintptr_t bit_remainder = (bit_offset & (kBitsPerByte - 1));
+    *bit_mask = (1U << bit_remainder);
+    uintptr_t byte_offset = (bit_offset >> kBitsPerByteLog2);
+    return ComputeInternalPointer<byte>(byte_offset);
+  }
+
+  void* pointer_;
+  size_t size_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryRegion);
+};
+
+} }  // namespace android::runtime
+
+#endif  // ART_MEMORY_REGION_H_
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..6f38e7f
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,45 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_UTILS_H_
+#define ART_SRC_UTILS_H_
+
+#include "src/globals.h"
+
+namespace android {
+namespace runtime {
+
+// Check whether an N-bit two's-complement representation can hold value.
+static inline bool IsInt(int N, word value) {
+  CHECK_LT(0, N);
+  CHECK_LT(N, kBitsPerWord);
+  word limit = static_cast<word>(1) << (N - 1);
+  return (-limit <= value) && (value < limit);
+}
+
+
+template<typename T>
+static inline bool IsPowerOfTwo(T x) {
+  return (x & (x - 1)) == 0;
+}
+
+
+static inline bool IsUint(int N, word value) {
+  CHECK_LT(0, N);
+  CHECK_LT(N, kBitsPerWord);
+  word limit = static_cast<word>(1) << N;
+  return (0 <= value) && (value < limit);
+}
+
+
+static inline int32_t Low32Bits(int64_t value) {
+  return static_cast<int32_t>(value);
+}
+
+
+static inline int32_t High32Bits(int64_t value) {
+  return static_cast<int32_t>(value >> 32);
+}
+
+} }  // namespace android::runtime
+
+#endif  // ART_SRC_UTILS_H_