1659efe783f45f46b9940aecf07be981057102ca7Ian Rogers/* 2659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * Copyright (C) 2013 The Android Open Source Project 3659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * 4659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 5659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * you may not use this file except in compliance with the License. 6659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * You may obtain a copy of the License at 7659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * 8659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * http://www.apache.org/licenses/LICENSE-2.0 9659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * 10659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * Unless required by applicable law or agreed to in writing, software 11659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS, 12659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * See the License for the specific language governing permissions and 14659efe783f45f46b9940aecf07be981057102ca7Ian Rogers * limitations under the License. 15659efe783f45f46b9940aecf07be981057102ca7Ian Rogers */ 16659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 17659efe783f45f46b9940aecf07be981057102ca7Ian Rogers#include "trampoline_compiler.h" 18659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 1968d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "jni_env_ext.h" 20659efe783f45f46b9940aecf07be981057102ca7Ian Rogers#include "utils/arm/assembler_arm.h" 21b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include "utils/arm64/assembler_arm64.h" 22659efe783f45f46b9940aecf07be981057102ca7Ian Rogers#include "utils/mips/assembler_mips.h" 2357b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe#include "utils/mips64/assembler_mips64.h" 24659efe783f45f46b9940aecf07be981057102ca7Ian Rogers#include "utils/x86/assembler_x86.h" 25dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers#include "utils/x86_64/assembler_x86_64.h" 26659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 27659efe783f45f46b9940aecf07be981057102ca7Ian Rogers#define __ assembler-> 28659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 29659efe783f45f46b9940aecf07be981057102ca7Ian Rogersnamespace art { 30659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 31659efe783f45f46b9940aecf07be981057102ca7Ian Rogersnamespace arm { 32659efe783f45f46b9940aecf07be981057102ca7Ian Rogersstatic const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi, 33dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ThreadOffset<4> offset) { 3450abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison std::unique_ptr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kThumb2))); 35659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 36659efe783f45f46b9940aecf07be981057102ca7Ian Rogers switch (abi) { 37659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kInterpreterAbi: // Thread* is first argument (R0) in interpreter ABI. 38659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, PC, R0, offset.Int32Value()); 39659efe783f45f46b9940aecf07be981057102ca7Ian Rogers break; 40659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (R0). 41659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, IP, R0, JNIEnvExt::SelfOffset().Int32Value()); 42659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, PC, IP, offset.Int32Value()); 43659efe783f45f46b9940aecf07be981057102ca7Ian Rogers break; 44956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes case kQuickAbi: // R9 holds Thread*. 45659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, PC, R9, offset.Int32Value()); 46659efe783f45f46b9940aecf07be981057102ca7Ian Rogers } 47659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ bkpt(0); 48659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 49659efe783f45f46b9940aecf07be981057102ca7Ian Rogers size_t cs = assembler->CodeSize(); 50700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs)); 51659efe783f45f46b9940aecf07be981057102ca7Ian Rogers MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 52659efe783f45f46b9940aecf07be981057102ca7Ian Rogers assembler->FinalizeInstructions(code); 53659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 54659efe783f45f46b9940aecf07be981057102ca7Ian Rogers return entry_stub.release(); 55659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} 56659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} // namespace arm 57659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 58b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithnamespace arm64 { 59b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteithstatic const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi, 60dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ThreadOffset<8> offset) { 61700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<Arm64Assembler> assembler(static_cast<Arm64Assembler*>(Assembler::Create(kArm64))); 62b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 63b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith switch (abi) { 64b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith case kInterpreterAbi: // Thread* is first argument (X0) in interpreter ABI. 6537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames __ JumpTo(Arm64ManagedRegister::FromXRegister(X0), Offset(offset.Int32Value()), 6637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames Arm64ManagedRegister::FromXRegister(IP1)); 67b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 68b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith break; 69b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (X0). 7037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames __ LoadRawPtr(Arm64ManagedRegister::FromXRegister(IP1), 7137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames Arm64ManagedRegister::FromXRegister(X0), 72b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith Offset(JNIEnvExt::SelfOffset().Int32Value())); 73b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 7437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames __ JumpTo(Arm64ManagedRegister::FromXRegister(IP1), Offset(offset.Int32Value()), 7537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames Arm64ManagedRegister::FromXRegister(IP0)); 76b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 77b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith break; 78956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes case kQuickAbi: // X18 holds Thread*. 7937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames __ JumpTo(Arm64ManagedRegister::FromXRegister(TR), Offset(offset.Int32Value()), 8037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames Arm64ManagedRegister::FromXRegister(IP0)); 81b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 82b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith break; 83b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith } 84b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 8532f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu assembler->EmitSlowPaths(); 86b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith size_t cs = assembler->CodeSize(); 87700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs)); 88b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 89b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith assembler->FinalizeInstructions(code); 90b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 91b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith return entry_stub.release(); 92b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith} 93b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith} // namespace arm64 94b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 95659efe783f45f46b9940aecf07be981057102ca7Ian Rogersnamespace mips { 96659efe783f45f46b9940aecf07be981057102ca7Ian Rogersstatic const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi, 97dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ThreadOffset<4> offset) { 98700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips))); 99659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 100659efe783f45f46b9940aecf07be981057102ca7Ian Rogers switch (abi) { 101659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI. 102659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, T9, A0, offset.Int32Value()); 103659efe783f45f46b9940aecf07be981057102ca7Ian Rogers break; 104659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0). 105659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, T9, A0, JNIEnvExt::SelfOffset().Int32Value()); 106659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, T9, T9, offset.Int32Value()); 107659efe783f45f46b9940aecf07be981057102ca7Ian Rogers break; 108956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes case kQuickAbi: // S1 holds Thread*. 109659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ LoadFromOffset(kLoadWord, T9, S1, offset.Int32Value()); 110659efe783f45f46b9940aecf07be981057102ca7Ian Rogers } 111659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ Jr(T9); 112659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ Nop(); 113659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ Break(); 114659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 115659efe783f45f46b9940aecf07be981057102ca7Ian Rogers size_t cs = assembler->CodeSize(); 116700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs)); 117659efe783f45f46b9940aecf07be981057102ca7Ian Rogers MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 118659efe783f45f46b9940aecf07be981057102ca7Ian Rogers assembler->FinalizeInstructions(code); 119659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 120659efe783f45f46b9940aecf07be981057102ca7Ian Rogers return entry_stub.release(); 121659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} 122659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} // namespace mips 123659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 12457b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampenamespace mips64 { 12557b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampestatic const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi, 12657b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe ThreadOffset<8> offset) { 12757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe std::unique_ptr<Mips64Assembler> assembler(static_cast<Mips64Assembler*>(Assembler::Create(kMips64))); 12857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe 12957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe switch (abi) { 13057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI. 13157b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ LoadFromOffset(kLoadDoubleword, T9, A0, offset.Int32Value()); 13257b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe break; 13357b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0). 13457b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ LoadFromOffset(kLoadDoubleword, T9, A0, JNIEnvExt::SelfOffset().Int32Value()); 13557b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ LoadFromOffset(kLoadDoubleword, T9, T9, offset.Int32Value()); 13657b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe break; 13757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe case kQuickAbi: // Fall-through. 13857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ LoadFromOffset(kLoadDoubleword, T9, S1, offset.Int32Value()); 13957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe } 14057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ Jr(T9); 14157b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ Nop(); 14257b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe __ Break(); 14357b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe 14457b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe size_t cs = assembler->CodeSize(); 14557b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs)); 14657b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 14757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe assembler->FinalizeInstructions(code); 14857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe 14957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe return entry_stub.release(); 15057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe} 15157b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe} // namespace mips64 15257b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe 153659efe783f45f46b9940aecf07be981057102ca7Ian Rogersnamespace x86 { 154dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogersstatic const std::vector<uint8_t>* CreateTrampoline(ThreadOffset<4> offset) { 155700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86))); 156659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 157659efe783f45f46b9940aecf07be981057102ca7Ian Rogers // All x86 trampolines call via the Thread* held in fs. 158659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ fs()->jmp(Address::Absolute(offset)); 159659efe783f45f46b9940aecf07be981057102ca7Ian Rogers __ int3(); 160659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 161659efe783f45f46b9940aecf07be981057102ca7Ian Rogers size_t cs = assembler->CodeSize(); 162700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs)); 163659efe783f45f46b9940aecf07be981057102ca7Ian Rogers MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 164659efe783f45f46b9940aecf07be981057102ca7Ian Rogers assembler->FinalizeInstructions(code); 165659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 166659efe783f45f46b9940aecf07be981057102ca7Ian Rogers return entry_stub.release(); 167659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} 168659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} // namespace x86 169659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 170befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogersnamespace x86_64 { 171dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogersstatic const std::vector<uint8_t>* CreateTrampoline(ThreadOffset<8> offset) { 172700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<x86_64::X86_64Assembler> 173dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers assembler(static_cast<x86_64::X86_64Assembler*>(Assembler::Create(kX86_64))); 174befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers 175befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers // All x86 trampolines call via the Thread* held in gs. 176dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers __ gs()->jmp(x86_64::Address::Absolute(offset, true)); 177befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers __ int3(); 178befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers 179befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers size_t cs = assembler->CodeSize(); 180700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs)); 181befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers MemoryRegion code(&(*entry_stub)[0], entry_stub->size()); 182befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers assembler->FinalizeInstructions(code); 183befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers 184befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers return entry_stub.release(); 185befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers} 186befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers} // namespace x86_64 187befbd5731ecca08f08780ee28a913d08ffb14656Ian Rogers 188dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogersconst std::vector<uint8_t>* CreateTrampoline64(InstructionSet isa, EntryPointCallingConvention abi, 189dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ThreadOffset<8> offset) { 190dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers switch (isa) { 191dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers case kArm64: 192dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers return arm64::CreateTrampoline(abi, offset); 19357b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe case kMips64: 19457b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe return mips64::CreateTrampoline(abi, offset); 195dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers case kX86_64: 196dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers return x86_64::CreateTrampoline(offset); 197dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers default: 198dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers LOG(FATAL) << "Unexpected InstructionSet: " << isa; 199d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers UNREACHABLE(); 200dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers } 201dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers} 202dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers 203dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogersconst std::vector<uint8_t>* CreateTrampoline32(InstructionSet isa, EntryPointCallingConvention abi, 204dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ThreadOffset<4> offset) { 205659efe783f45f46b9940aecf07be981057102ca7Ian Rogers switch (isa) { 206659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kArm: 207659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kThumb2: 208659efe783f45f46b9940aecf07be981057102ca7Ian Rogers return arm::CreateTrampoline(abi, offset); 209659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kMips: 210659efe783f45f46b9940aecf07be981057102ca7Ian Rogers return mips::CreateTrampoline(abi, offset); 211659efe783f45f46b9940aecf07be981057102ca7Ian Rogers case kX86: 212659efe783f45f46b9940aecf07be981057102ca7Ian Rogers return x86::CreateTrampoline(offset); 213659efe783f45f46b9940aecf07be981057102ca7Ian Rogers default: 214dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers LOG(FATAL) << "Unexpected InstructionSet: " << isa; 215d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers UNREACHABLE(); 216659efe783f45f46b9940aecf07be981057102ca7Ian Rogers } 217659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} 218659efe783f45f46b9940aecf07be981057102ca7Ian Rogers 219659efe783f45f46b9940aecf07be981057102ca7Ian Rogers} // namespace art 220