summaryrefslogtreecommitdiffstats
path: root/compiler/trampolines/trampoline_compiler.cc
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-08-07 22:54:13 -0700
committerIan Rogers <irogers@google.com>2013-08-12 06:12:42 +0000
commit659efe783f45f46b9940aecf07be981057102ca7 (patch)
tree96199d682e35868bb5287371ad4415144c5f3b5a /compiler/trampolines/trampoline_compiler.cc
parent468532ea115657709bc32ee498e701a4c71762d4 (diff)
downloadart-659efe783f45f46b9940aecf07be981057102ca7.zip
art-659efe783f45f46b9940aecf07be981057102ca7.tar.gz
art-659efe783f45f46b9940aecf07be981057102ca7.tar.bz2
Fix missing files.
Build fix. Change-Id: I06ae40611ab1631be8ebea912430a824a086c98f (cherry picked from commit d8de72f54f6076218373af4abf76dd2a548f13e3)
Diffstat (limited to 'compiler/trampolines/trampoline_compiler.cc')
-rw-r--r--compiler/trampolines/trampoline_compiler.cc119
1 files changed, 119 insertions, 0 deletions
diff --git a/compiler/trampolines/trampoline_compiler.cc b/compiler/trampolines/trampoline_compiler.cc
new file mode 100644
index 0000000..32ae558
--- /dev/null
+++ b/compiler/trampolines/trampoline_compiler.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trampoline_compiler.h"
+
+#include "jni_internal.h"
+#include "utils/arm/assembler_arm.h"
+#include "utils/mips/assembler_mips.h"
+#include "utils/x86/assembler_x86.h"
+
+#define __ assembler->
+
+namespace art {
+
+namespace arm {
+static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi,
+ ThreadOffset offset) {
+ UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
+
+ switch (abi) {
+ case kInterpreterAbi: // Thread* is first argument (R0) in interpreter ABI.
+ __ LoadFromOffset(kLoadWord, PC, R0, offset.Int32Value());
+ break;
+ case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (R0).
+ __ LoadFromOffset(kLoadWord, IP, R0, JNIEnvExt::SelfOffset().Int32Value());
+ __ LoadFromOffset(kLoadWord, PC, IP, offset.Int32Value());
+ break;
+ case kPortableAbi: // R9 holds Thread*.
+ case kQuickAbi: // Fall-through.
+ __ LoadFromOffset(kLoadWord, PC, R9, offset.Int32Value());
+ }
+ __ bkpt(0);
+
+ size_t cs = assembler->CodeSize();
+ UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
+ MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
+ assembler->FinalizeInstructions(code);
+
+ return entry_stub.release();
+}
+} // namespace arm
+
+namespace mips {
+static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi,
+ ThreadOffset offset) {
+ UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
+
+ switch (abi) {
+ case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI.
+ __ LoadFromOffset(kLoadWord, T9, A0, offset.Int32Value());
+ break;
+ case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0).
+ __ LoadFromOffset(kLoadWord, T9, A0, JNIEnvExt::SelfOffset().Int32Value());
+ __ LoadFromOffset(kLoadWord, T9, T9, offset.Int32Value());
+ break;
+ case kPortableAbi: // S1 holds Thread*.
+ case kQuickAbi: // Fall-through.
+ __ LoadFromOffset(kLoadWord, T9, S1, offset.Int32Value());
+ }
+ __ Jr(T9);
+ __ Nop();
+ __ Break();
+
+ size_t cs = assembler->CodeSize();
+ UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
+ MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
+ assembler->FinalizeInstructions(code);
+
+ return entry_stub.release();
+}
+} // namespace mips
+
+namespace x86 {
+static const std::vector<uint8_t>* CreateTrampoline(ThreadOffset offset) {
+ UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
+
+ // All x86 trampolines call via the Thread* held in fs.
+ __ fs()->jmp(Address::Absolute(offset));
+ __ int3();
+
+ size_t cs = assembler->CodeSize();
+ UniquePtr<std::vector<uint8_t> > entry_stub(new std::vector<uint8_t>(cs));
+ MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
+ assembler->FinalizeInstructions(code);
+
+ return entry_stub.release();
+}
+} // namespace x86
+
+const std::vector<uint8_t>* CreateTrampoline(InstructionSet isa, EntryPointCallingConvention abi,
+ ThreadOffset offset) {
+ switch (isa) {
+ case kArm:
+ case kThumb2:
+ return arm::CreateTrampoline(abi, offset);
+ case kMips:
+ return mips::CreateTrampoline(abi, offset);
+ case kX86:
+ return x86::CreateTrampoline(offset);
+ default:
+ LOG(FATAL) << "Unknown InstructionSet: " << isa;
+ return NULL;
+ }
+}
+
+} // namespace art