x86 JNI compiler and unit tests.

Change-Id: I4c2e10328961a2e8e27c90777fe2a93737b21143
diff --git a/src/thread_x86.cc b/src/thread_x86.cc
new file mode 100644
index 0000000..14cb2b2
--- /dev/null
+++ b/src/thread_x86.cc
@@ -0,0 +1,60 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/thread.h"
+#include <asm/ldt.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include "src/macros.h"
+
+namespace art {
+
+void Thread::InitCpu() {
+  // Read LDT
+  CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
+  uint64_t ldt_[LDT_ENTRIES];
+  syscall(SYS_modify_ldt, 0, ldt_, sizeof(ldt_));
+  // Create empty slot to point at current Thread*
+  struct user_desc ldt_entry;
+  ldt_entry.entry_number = -1;
+  ldt_entry.base_addr = (unsigned int)this;
+  ldt_entry.limit = 4096;
+  ldt_entry.seg_32bit = 1;
+  ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
+  ldt_entry.read_exec_only = 0;
+  ldt_entry.limit_in_pages = 0;
+  ldt_entry.seg_not_present = 0;
+  ldt_entry.useable = 1;
+  for (int i = 0; i < LDT_ENTRIES; i++) {
+    if (ldt_[i] == 0) {
+      ldt_entry.entry_number = i;
+      break;
+    }
+  }
+  if (ldt_entry.entry_number >= LDT_ENTRIES) {
+    LOG(FATAL) << "Failed to find available LDT slot";
+  }
+  // Update LDT
+  CHECK_EQ(0, syscall(SYS_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
+  // Change FS to be new LDT entry
+  uint16_t table_indicator = 1 << 2;  // LDT
+  uint16_t rpl = 3;  // Requested privilege level
+  uint16_t selector = (ldt_entry.entry_number << 3) | table_indicator | rpl;
+  // TODO: use our assembler to generate code
+  asm("movw %w0, %%fs"
+      :    // output
+      : "q"(selector)  // input
+      :);  // clobber
+  // Allow easy indirection back to Thread*
+  self_ = this;
+  // Sanity check reads from FS goes to this Thread*
+  CHECK_EQ(0, OFFSETOF_MEMBER(Thread, self_));
+  Thread* self_check;
+  // TODO: use our assembler to generate code
+  asm("movl %%fs:0, %0"
+      : "=r"(self_check)  // output
+      :    // input
+      :);  // clobber
+  CHECK_EQ(self_check, this);
+}
+
+}  // namespace art