blob: 48465e64aa0e3ef75881ea30f5bdef7315e26330 [file] [log] [blame]
Ian Rogers659efe72013-08-07 22:54:13 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "trampoline_compiler.h"
18
Ian Rogers68d8b422014-07-17 11:09:10 -070019#include "jni_env_ext.h"
Alex Light50fa9932015-08-10 15:30:07 -070020
21#ifdef ART_ENABLE_CODEGEN_arm
Vladimir Markocf93a5c2015-06-16 11:33:24 +000022#include "utils/arm/assembler_thumb2.h"
Alex Light50fa9932015-08-10 15:30:07 -070023#endif
24
25#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000026#include "utils/arm64/assembler_arm64.h"
Alex Light50fa9932015-08-10 15:30:07 -070027#endif
28
29#ifdef ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -070030#include "utils/mips/assembler_mips.h"
Alex Light50fa9932015-08-10 15:30:07 -070031#endif
32
33#ifdef ART_ENABLE_CODEGEN_mips64
Andreas Gampe57b34292015-01-14 15:45:59 -080034#include "utils/mips64/assembler_mips64.h"
Alex Light50fa9932015-08-10 15:30:07 -070035#endif
36
37#ifdef ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -070038#include "utils/x86/assembler_x86.h"
Alex Light50fa9932015-08-10 15:30:07 -070039#endif
40
41#ifdef ART_ENABLE_CODEGEN_x86_64
Ian Rogersdd7624d2014-03-14 17:43:00 -070042#include "utils/x86_64/assembler_x86_64.h"
Alex Light50fa9932015-08-10 15:30:07 -070043#endif
Ian Rogers659efe72013-08-07 22:54:13 -070044
Vladimir Markocf93a5c2015-06-16 11:33:24 +000045#define __ assembler.
Ian Rogers659efe72013-08-07 22:54:13 -070046
47namespace art {
48
Alex Light50fa9932015-08-10 15:30:07 -070049#ifdef ART_ENABLE_CODEGEN_arm
Ian Rogers659efe72013-08-07 22:54:13 -070050namespace arm {
51static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi,
Ian Rogersdd7624d2014-03-14 17:43:00 -070052 ThreadOffset<4> offset) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +000053 Thumb2Assembler assembler;
Ian Rogers659efe72013-08-07 22:54:13 -070054
55 switch (abi) {
56 case kInterpreterAbi: // Thread* is first argument (R0) in interpreter ABI.
57 __ LoadFromOffset(kLoadWord, PC, R0, offset.Int32Value());
58 break;
59 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (R0).
Andreas Gampe4d98c842015-12-09 15:14:04 -080060 __ LoadFromOffset(kLoadWord, IP, R0, JNIEnvExt::SelfOffset(4).Int32Value());
Ian Rogers659efe72013-08-07 22:54:13 -070061 __ LoadFromOffset(kLoadWord, PC, IP, offset.Int32Value());
62 break;
Elliott Hughes956af0f2014-12-11 14:34:28 -080063 case kQuickAbi: // R9 holds Thread*.
Ian Rogers659efe72013-08-07 22:54:13 -070064 __ LoadFromOffset(kLoadWord, PC, R9, offset.Int32Value());
65 }
66 __ bkpt(0);
67
Vladimir Markocf93a5c2015-06-16 11:33:24 +000068 __ FinalizeCode();
69 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -070070 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Ian Rogers659efe72013-08-07 22:54:13 -070071 MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +000072 __ FinalizeInstructions(code);
Ian Rogers659efe72013-08-07 22:54:13 -070073
74 return entry_stub.release();
75}
76} // namespace arm
Alex Light50fa9932015-08-10 15:30:07 -070077#endif // ART_ENABLE_CODEGEN_arm
Ian Rogers659efe72013-08-07 22:54:13 -070078
Alex Light50fa9932015-08-10 15:30:07 -070079#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000080namespace arm64 {
81static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi,
Ian Rogersdd7624d2014-03-14 17:43:00 -070082 ThreadOffset<8> offset) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +000083 Arm64Assembler assembler;
Stuart Monteithb95a5342014-03-12 13:32:32 +000084
85 switch (abi) {
86 case kInterpreterAbi: // Thread* is first argument (X0) in interpreter ABI.
Alexandre Rames37c92df2014-10-17 14:35:27 +010087 __ JumpTo(Arm64ManagedRegister::FromXRegister(X0), Offset(offset.Int32Value()),
88 Arm64ManagedRegister::FromXRegister(IP1));
Stuart Monteithb95a5342014-03-12 13:32:32 +000089
90 break;
91 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (X0).
Alexandre Rames37c92df2014-10-17 14:35:27 +010092 __ LoadRawPtr(Arm64ManagedRegister::FromXRegister(IP1),
93 Arm64ManagedRegister::FromXRegister(X0),
Andreas Gampe4d98c842015-12-09 15:14:04 -080094 Offset(JNIEnvExt::SelfOffset(8).Int32Value()));
Stuart Monteithb95a5342014-03-12 13:32:32 +000095
Alexandre Rames37c92df2014-10-17 14:35:27 +010096 __ JumpTo(Arm64ManagedRegister::FromXRegister(IP1), Offset(offset.Int32Value()),
97 Arm64ManagedRegister::FromXRegister(IP0));
Stuart Monteithb95a5342014-03-12 13:32:32 +000098
99 break;
Elliott Hughes956af0f2014-12-11 14:34:28 -0800100 case kQuickAbi: // X18 holds Thread*.
Alexandre Rames37c92df2014-10-17 14:35:27 +0100101 __ JumpTo(Arm64ManagedRegister::FromXRegister(TR), Offset(offset.Int32Value()),
102 Arm64ManagedRegister::FromXRegister(IP0));
Stuart Monteithb95a5342014-03-12 13:32:32 +0000103
104 break;
105 }
106
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000107 __ FinalizeCode();
108 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700109 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Stuart Monteithb95a5342014-03-12 13:32:32 +0000110 MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000111 __ FinalizeInstructions(code);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000112
113 return entry_stub.release();
114}
115} // namespace arm64
Alex Light50fa9932015-08-10 15:30:07 -0700116#endif // ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +0000117
Alex Light50fa9932015-08-10 15:30:07 -0700118#ifdef ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -0700119namespace mips {
120static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700121 ThreadOffset<4> offset) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000122 MipsAssembler assembler;
Ian Rogers659efe72013-08-07 22:54:13 -0700123
124 switch (abi) {
125 case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI.
126 __ LoadFromOffset(kLoadWord, T9, A0, offset.Int32Value());
127 break;
128 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0).
Andreas Gampe4d98c842015-12-09 15:14:04 -0800129 __ LoadFromOffset(kLoadWord, T9, A0, JNIEnvExt::SelfOffset(4).Int32Value());
Ian Rogers659efe72013-08-07 22:54:13 -0700130 __ LoadFromOffset(kLoadWord, T9, T9, offset.Int32Value());
131 break;
Elliott Hughes956af0f2014-12-11 14:34:28 -0800132 case kQuickAbi: // S1 holds Thread*.
Ian Rogers659efe72013-08-07 22:54:13 -0700133 __ LoadFromOffset(kLoadWord, T9, S1, offset.Int32Value());
134 }
135 __ Jr(T9);
136 __ Nop();
137 __ Break();
138
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000139 __ FinalizeCode();
140 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700141 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Ian Rogers659efe72013-08-07 22:54:13 -0700142 MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000143 __ FinalizeInstructions(code);
Ian Rogers659efe72013-08-07 22:54:13 -0700144
145 return entry_stub.release();
146}
147} // namespace mips
Alex Light50fa9932015-08-10 15:30:07 -0700148#endif // ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -0700149
Alex Light50fa9932015-08-10 15:30:07 -0700150#ifdef ART_ENABLE_CODEGEN_mips64
Andreas Gampe57b34292015-01-14 15:45:59 -0800151namespace mips64 {
152static const std::vector<uint8_t>* CreateTrampoline(EntryPointCallingConvention abi,
153 ThreadOffset<8> offset) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000154 Mips64Assembler assembler;
Andreas Gampe57b34292015-01-14 15:45:59 -0800155
156 switch (abi) {
157 case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI.
158 __ LoadFromOffset(kLoadDoubleword, T9, A0, offset.Int32Value());
159 break;
160 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0).
Andreas Gampe4d98c842015-12-09 15:14:04 -0800161 __ LoadFromOffset(kLoadDoubleword, T9, A0, JNIEnvExt::SelfOffset(8).Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -0800162 __ LoadFromOffset(kLoadDoubleword, T9, T9, offset.Int32Value());
163 break;
164 case kQuickAbi: // Fall-through.
165 __ LoadFromOffset(kLoadDoubleword, T9, S1, offset.Int32Value());
166 }
167 __ Jr(T9);
168 __ Nop();
169 __ Break();
170
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000171 __ FinalizeCode();
172 size_t cs = __ CodeSize();
Andreas Gampe57b34292015-01-14 15:45:59 -0800173 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
174 MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000175 __ FinalizeInstructions(code);
Andreas Gampe57b34292015-01-14 15:45:59 -0800176
177 return entry_stub.release();
178}
179} // namespace mips64
Alex Light50fa9932015-08-10 15:30:07 -0700180#endif // ART_ENABLE_CODEGEN_mips
Andreas Gampe57b34292015-01-14 15:45:59 -0800181
Alex Light50fa9932015-08-10 15:30:07 -0700182#ifdef ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -0700183namespace x86 {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700184static const std::vector<uint8_t>* CreateTrampoline(ThreadOffset<4> offset) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000185 X86Assembler assembler;
Ian Rogers659efe72013-08-07 22:54:13 -0700186
187 // All x86 trampolines call via the Thread* held in fs.
188 __ fs()->jmp(Address::Absolute(offset));
189 __ int3();
190
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000191 __ FinalizeCode();
192 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700193 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Ian Rogers659efe72013-08-07 22:54:13 -0700194 MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000195 __ FinalizeInstructions(code);
Ian Rogers659efe72013-08-07 22:54:13 -0700196
197 return entry_stub.release();
198}
199} // namespace x86
Alex Light50fa9932015-08-10 15:30:07 -0700200#endif // ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -0700201
Alex Light50fa9932015-08-10 15:30:07 -0700202#ifdef ART_ENABLE_CODEGEN_x86_64
Ian Rogersbefbd572014-03-06 01:13:39 -0800203namespace x86_64 {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700204static const std::vector<uint8_t>* CreateTrampoline(ThreadOffset<8> offset) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000205 x86_64::X86_64Assembler assembler;
Ian Rogersbefbd572014-03-06 01:13:39 -0800206
207 // All x86 trampolines call via the Thread* held in gs.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700208 __ gs()->jmp(x86_64::Address::Absolute(offset, true));
Ian Rogersbefbd572014-03-06 01:13:39 -0800209 __ int3();
210
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000211 __ FinalizeCode();
212 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700213 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Ian Rogersbefbd572014-03-06 01:13:39 -0800214 MemoryRegion code(&(*entry_stub)[0], entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000215 __ FinalizeInstructions(code);
Ian Rogersbefbd572014-03-06 01:13:39 -0800216
217 return entry_stub.release();
218}
219} // namespace x86_64
Alex Light50fa9932015-08-10 15:30:07 -0700220#endif // ART_ENABLE_CODEGEN_x86_64
Ian Rogersbefbd572014-03-06 01:13:39 -0800221
Ian Rogersdd7624d2014-03-14 17:43:00 -0700222const std::vector<uint8_t>* CreateTrampoline64(InstructionSet isa, EntryPointCallingConvention abi,
223 ThreadOffset<8> offset) {
224 switch (isa) {
Alex Light50fa9932015-08-10 15:30:07 -0700225#ifdef ART_ENABLE_CODEGEN_arm64
Ian Rogersdd7624d2014-03-14 17:43:00 -0700226 case kArm64:
227 return arm64::CreateTrampoline(abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700228#endif
229#ifdef ART_ENABLE_CODEGEN_mips64
Andreas Gampe57b34292015-01-14 15:45:59 -0800230 case kMips64:
231 return mips64::CreateTrampoline(abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700232#endif
233#ifdef ART_ENABLE_CODEGEN_x86_64
Ian Rogersdd7624d2014-03-14 17:43:00 -0700234 case kX86_64:
235 return x86_64::CreateTrampoline(offset);
Alex Light50fa9932015-08-10 15:30:07 -0700236#endif
Ian Rogersdd7624d2014-03-14 17:43:00 -0700237 default:
Alex Light50fa9932015-08-10 15:30:07 -0700238 UNUSED(abi);
239 UNUSED(offset);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700240 LOG(FATAL) << "Unexpected InstructionSet: " << isa;
Ian Rogersd4c4d952014-10-16 20:31:53 -0700241 UNREACHABLE();
Ian Rogersdd7624d2014-03-14 17:43:00 -0700242 }
243}
244
245const std::vector<uint8_t>* CreateTrampoline32(InstructionSet isa, EntryPointCallingConvention abi,
246 ThreadOffset<4> offset) {
Ian Rogers659efe72013-08-07 22:54:13 -0700247 switch (isa) {
Alex Light50fa9932015-08-10 15:30:07 -0700248#ifdef ART_ENABLE_CODEGEN_arm
Ian Rogers659efe72013-08-07 22:54:13 -0700249 case kArm:
250 case kThumb2:
251 return arm::CreateTrampoline(abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700252#endif
253#ifdef ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -0700254 case kMips:
255 return mips::CreateTrampoline(abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700256#endif
257#ifdef ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -0700258 case kX86:
Alex Light50fa9932015-08-10 15:30:07 -0700259 UNUSED(abi);
Ian Rogers659efe72013-08-07 22:54:13 -0700260 return x86::CreateTrampoline(offset);
Alex Light50fa9932015-08-10 15:30:07 -0700261#endif
Ian Rogers659efe72013-08-07 22:54:13 -0700262 default:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700263 LOG(FATAL) << "Unexpected InstructionSet: " << isa;
Ian Rogersd4c4d952014-10-16 20:31:53 -0700264 UNREACHABLE();
Ian Rogers659efe72013-08-07 22:54:13 -0700265 }
266}
267
268} // namespace art