Add basic assembler interface and an x86 backend.

Change-Id: Ia8136bad88f1194c8a247e2af80e486ab88c1e8c
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