blob: 304e56b8359f678d050ecbabdf0b6c0cce50e800 [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
Vladimir Marko93205e32016-04-13 11:59:46 +010019#include "base/arena_allocator.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070020#include "jni_env_ext.h"
Alex Light50fa9932015-08-10 15:30:07 -070021
22#ifdef ART_ENABLE_CODEGEN_arm
Vladimir Markocf93a5c2015-06-16 11:33:24 +000023#include "utils/arm/assembler_thumb2.h"
Alex Light50fa9932015-08-10 15:30:07 -070024#endif
25
26#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000027#include "utils/arm64/assembler_arm64.h"
Alex Light50fa9932015-08-10 15:30:07 -070028#endif
29
30#ifdef ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -070031#include "utils/mips/assembler_mips.h"
Alex Light50fa9932015-08-10 15:30:07 -070032#endif
33
34#ifdef ART_ENABLE_CODEGEN_mips64
Andreas Gampe57b34292015-01-14 15:45:59 -080035#include "utils/mips64/assembler_mips64.h"
Alex Light50fa9932015-08-10 15:30:07 -070036#endif
37
38#ifdef ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -070039#include "utils/x86/assembler_x86.h"
Alex Light50fa9932015-08-10 15:30:07 -070040#endif
41
42#ifdef ART_ENABLE_CODEGEN_x86_64
Ian Rogersdd7624d2014-03-14 17:43:00 -070043#include "utils/x86_64/assembler_x86_64.h"
Alex Light50fa9932015-08-10 15:30:07 -070044#endif
Ian Rogers659efe72013-08-07 22:54:13 -070045
Vladimir Markocf93a5c2015-06-16 11:33:24 +000046#define __ assembler.
Ian Rogers659efe72013-08-07 22:54:13 -070047
48namespace art {
49
Alex Light50fa9932015-08-10 15:30:07 -070050#ifdef ART_ENABLE_CODEGEN_arm
Ian Rogers659efe72013-08-07 22:54:13 -070051namespace arm {
Vladimir Marko93205e32016-04-13 11:59:46 +010052static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(
Andreas Gampe542451c2016-07-26 09:02:02 -070053 ArenaAllocator* arena, EntryPointCallingConvention abi, ThreadOffset32 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +010054 Thumb2Assembler assembler(arena);
Ian Rogers659efe72013-08-07 22:54:13 -070055
56 switch (abi) {
57 case kInterpreterAbi: // Thread* is first argument (R0) in interpreter ABI.
58 __ LoadFromOffset(kLoadWord, PC, R0, offset.Int32Value());
59 break;
60 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (R0).
Andreas Gampe4d98c842015-12-09 15:14:04 -080061 __ LoadFromOffset(kLoadWord, IP, R0, JNIEnvExt::SelfOffset(4).Int32Value());
Ian Rogers659efe72013-08-07 22:54:13 -070062 __ LoadFromOffset(kLoadWord, PC, IP, offset.Int32Value());
63 break;
Elliott Hughes956af0f2014-12-11 14:34:28 -080064 case kQuickAbi: // R9 holds Thread*.
Ian Rogers659efe72013-08-07 22:54:13 -070065 __ LoadFromOffset(kLoadWord, PC, R9, offset.Int32Value());
66 }
67 __ bkpt(0);
68
Vladimir Markocf93a5c2015-06-16 11:33:24 +000069 __ FinalizeCode();
70 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -070071 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Vladimir Marko93205e32016-04-13 11:59:46 +010072 MemoryRegion code(entry_stub->data(), entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +000073 __ FinalizeInstructions(code);
Ian Rogers659efe72013-08-07 22:54:13 -070074
Vladimir Marko93205e32016-04-13 11:59:46 +010075 return std::move(entry_stub);
Ian Rogers659efe72013-08-07 22:54:13 -070076}
77} // namespace arm
Alex Light50fa9932015-08-10 15:30:07 -070078#endif // ART_ENABLE_CODEGEN_arm
Ian Rogers659efe72013-08-07 22:54:13 -070079
Alex Light50fa9932015-08-10 15:30:07 -070080#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000081namespace arm64 {
Vladimir Marko93205e32016-04-13 11:59:46 +010082static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(
Andreas Gampe542451c2016-07-26 09:02:02 -070083 ArenaAllocator* arena, EntryPointCallingConvention abi, ThreadOffset64 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +010084 Arm64Assembler assembler(arena);
Stuart Monteithb95a5342014-03-12 13:32:32 +000085
86 switch (abi) {
87 case kInterpreterAbi: // Thread* is first argument (X0) in interpreter ABI.
Alexandre Rames37c92df2014-10-17 14:35:27 +010088 __ JumpTo(Arm64ManagedRegister::FromXRegister(X0), Offset(offset.Int32Value()),
89 Arm64ManagedRegister::FromXRegister(IP1));
Stuart Monteithb95a5342014-03-12 13:32:32 +000090
91 break;
92 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (X0).
Alexandre Rames37c92df2014-10-17 14:35:27 +010093 __ LoadRawPtr(Arm64ManagedRegister::FromXRegister(IP1),
94 Arm64ManagedRegister::FromXRegister(X0),
Andreas Gampe4d98c842015-12-09 15:14:04 -080095 Offset(JNIEnvExt::SelfOffset(8).Int32Value()));
Stuart Monteithb95a5342014-03-12 13:32:32 +000096
Alexandre Rames37c92df2014-10-17 14:35:27 +010097 __ JumpTo(Arm64ManagedRegister::FromXRegister(IP1), Offset(offset.Int32Value()),
98 Arm64ManagedRegister::FromXRegister(IP0));
Stuart Monteithb95a5342014-03-12 13:32:32 +000099
100 break;
Elliott Hughes956af0f2014-12-11 14:34:28 -0800101 case kQuickAbi: // X18 holds Thread*.
Alexandre Rames37c92df2014-10-17 14:35:27 +0100102 __ JumpTo(Arm64ManagedRegister::FromXRegister(TR), Offset(offset.Int32Value()),
103 Arm64ManagedRegister::FromXRegister(IP0));
Stuart Monteithb95a5342014-03-12 13:32:32 +0000104
105 break;
106 }
107
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000108 __ FinalizeCode();
109 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700110 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Vladimir Marko93205e32016-04-13 11:59:46 +0100111 MemoryRegion code(entry_stub->data(), entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000112 __ FinalizeInstructions(code);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000113
Vladimir Marko93205e32016-04-13 11:59:46 +0100114 return std::move(entry_stub);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000115}
116} // namespace arm64
Alex Light50fa9932015-08-10 15:30:07 -0700117#endif // ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +0000118
Alex Light50fa9932015-08-10 15:30:07 -0700119#ifdef ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -0700120namespace mips {
Vladimir Marko93205e32016-04-13 11:59:46 +0100121static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(
Andreas Gampe542451c2016-07-26 09:02:02 -0700122 ArenaAllocator* arena, EntryPointCallingConvention abi, ThreadOffset32 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +0100123 MipsAssembler assembler(arena);
Ian Rogers659efe72013-08-07 22:54:13 -0700124
125 switch (abi) {
126 case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI.
127 __ LoadFromOffset(kLoadWord, T9, A0, offset.Int32Value());
128 break;
129 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0).
Andreas Gampe4d98c842015-12-09 15:14:04 -0800130 __ LoadFromOffset(kLoadWord, T9, A0, JNIEnvExt::SelfOffset(4).Int32Value());
Ian Rogers659efe72013-08-07 22:54:13 -0700131 __ LoadFromOffset(kLoadWord, T9, T9, offset.Int32Value());
132 break;
Elliott Hughes956af0f2014-12-11 14:34:28 -0800133 case kQuickAbi: // S1 holds Thread*.
Ian Rogers659efe72013-08-07 22:54:13 -0700134 __ LoadFromOffset(kLoadWord, T9, S1, offset.Int32Value());
135 }
136 __ Jr(T9);
137 __ Nop();
138 __ Break();
139
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000140 __ FinalizeCode();
141 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700142 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Vladimir Marko93205e32016-04-13 11:59:46 +0100143 MemoryRegion code(entry_stub->data(), entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000144 __ FinalizeInstructions(code);
Ian Rogers659efe72013-08-07 22:54:13 -0700145
Vladimir Marko93205e32016-04-13 11:59:46 +0100146 return std::move(entry_stub);
Ian Rogers659efe72013-08-07 22:54:13 -0700147}
148} // namespace mips
Alex Light50fa9932015-08-10 15:30:07 -0700149#endif // ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -0700150
Alex Light50fa9932015-08-10 15:30:07 -0700151#ifdef ART_ENABLE_CODEGEN_mips64
Andreas Gampe57b34292015-01-14 15:45:59 -0800152namespace mips64 {
Vladimir Marko93205e32016-04-13 11:59:46 +0100153static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(
Andreas Gampe542451c2016-07-26 09:02:02 -0700154 ArenaAllocator* arena, EntryPointCallingConvention abi, ThreadOffset64 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +0100155 Mips64Assembler assembler(arena);
Andreas Gampe57b34292015-01-14 15:45:59 -0800156
157 switch (abi) {
158 case kInterpreterAbi: // Thread* is first argument (A0) in interpreter ABI.
159 __ LoadFromOffset(kLoadDoubleword, T9, A0, offset.Int32Value());
160 break;
161 case kJniAbi: // Load via Thread* held in JNIEnv* in first argument (A0).
Andreas Gampe4d98c842015-12-09 15:14:04 -0800162 __ LoadFromOffset(kLoadDoubleword, T9, A0, JNIEnvExt::SelfOffset(8).Int32Value());
Andreas Gampe57b34292015-01-14 15:45:59 -0800163 __ LoadFromOffset(kLoadDoubleword, T9, T9, offset.Int32Value());
164 break;
165 case kQuickAbi: // Fall-through.
166 __ LoadFromOffset(kLoadDoubleword, T9, S1, offset.Int32Value());
167 }
168 __ Jr(T9);
169 __ Nop();
170 __ Break();
171
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000172 __ FinalizeCode();
173 size_t cs = __ CodeSize();
Andreas Gampe57b34292015-01-14 15:45:59 -0800174 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Vladimir Marko93205e32016-04-13 11:59:46 +0100175 MemoryRegion code(entry_stub->data(), entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000176 __ FinalizeInstructions(code);
Andreas Gampe57b34292015-01-14 15:45:59 -0800177
Vladimir Marko93205e32016-04-13 11:59:46 +0100178 return std::move(entry_stub);
Andreas Gampe57b34292015-01-14 15:45:59 -0800179}
180} // namespace mips64
Alex Light50fa9932015-08-10 15:30:07 -0700181#endif // ART_ENABLE_CODEGEN_mips
Andreas Gampe57b34292015-01-14 15:45:59 -0800182
Alex Light50fa9932015-08-10 15:30:07 -0700183#ifdef ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -0700184namespace x86 {
Vladimir Marko93205e32016-04-13 11:59:46 +0100185static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(ArenaAllocator* arena,
Andreas Gampe542451c2016-07-26 09:02:02 -0700186 ThreadOffset32 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +0100187 X86Assembler assembler(arena);
Ian Rogers659efe72013-08-07 22:54:13 -0700188
189 // All x86 trampolines call via the Thread* held in fs.
190 __ fs()->jmp(Address::Absolute(offset));
191 __ int3();
192
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000193 __ FinalizeCode();
194 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700195 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Vladimir Marko93205e32016-04-13 11:59:46 +0100196 MemoryRegion code(entry_stub->data(), entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000197 __ FinalizeInstructions(code);
Ian Rogers659efe72013-08-07 22:54:13 -0700198
Vladimir Marko93205e32016-04-13 11:59:46 +0100199 return std::move(entry_stub);
Ian Rogers659efe72013-08-07 22:54:13 -0700200}
201} // namespace x86
Alex Light50fa9932015-08-10 15:30:07 -0700202#endif // ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -0700203
Alex Light50fa9932015-08-10 15:30:07 -0700204#ifdef ART_ENABLE_CODEGEN_x86_64
Ian Rogersbefbd572014-03-06 01:13:39 -0800205namespace x86_64 {
Vladimir Marko93205e32016-04-13 11:59:46 +0100206static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(ArenaAllocator* arena,
Andreas Gampe542451c2016-07-26 09:02:02 -0700207 ThreadOffset64 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +0100208 x86_64::X86_64Assembler assembler(arena);
Ian Rogersbefbd572014-03-06 01:13:39 -0800209
210 // All x86 trampolines call via the Thread* held in gs.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700211 __ gs()->jmp(x86_64::Address::Absolute(offset, true));
Ian Rogersbefbd572014-03-06 01:13:39 -0800212 __ int3();
213
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000214 __ FinalizeCode();
215 size_t cs = __ CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700216 std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
Vladimir Marko93205e32016-04-13 11:59:46 +0100217 MemoryRegion code(entry_stub->data(), entry_stub->size());
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000218 __ FinalizeInstructions(code);
Ian Rogersbefbd572014-03-06 01:13:39 -0800219
Vladimir Marko93205e32016-04-13 11:59:46 +0100220 return std::move(entry_stub);
Ian Rogersbefbd572014-03-06 01:13:39 -0800221}
222} // namespace x86_64
Alex Light50fa9932015-08-10 15:30:07 -0700223#endif // ART_ENABLE_CODEGEN_x86_64
Ian Rogersbefbd572014-03-06 01:13:39 -0800224
Vladimir Marko93205e32016-04-13 11:59:46 +0100225std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline64(InstructionSet isa,
226 EntryPointCallingConvention abi,
Andreas Gampe542451c2016-07-26 09:02:02 -0700227 ThreadOffset64 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +0100228 ArenaPool pool;
229 ArenaAllocator arena(&pool);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700230 switch (isa) {
Alex Light50fa9932015-08-10 15:30:07 -0700231#ifdef ART_ENABLE_CODEGEN_arm64
Ian Rogersdd7624d2014-03-14 17:43:00 -0700232 case kArm64:
Vladimir Marko93205e32016-04-13 11:59:46 +0100233 return arm64::CreateTrampoline(&arena, abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700234#endif
235#ifdef ART_ENABLE_CODEGEN_mips64
Andreas Gampe57b34292015-01-14 15:45:59 -0800236 case kMips64:
Vladimir Marko93205e32016-04-13 11:59:46 +0100237 return mips64::CreateTrampoline(&arena, abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700238#endif
239#ifdef ART_ENABLE_CODEGEN_x86_64
Ian Rogersdd7624d2014-03-14 17:43:00 -0700240 case kX86_64:
Vladimir Marko93205e32016-04-13 11:59:46 +0100241 return x86_64::CreateTrampoline(&arena, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700242#endif
Ian Rogersdd7624d2014-03-14 17:43:00 -0700243 default:
Alex Light50fa9932015-08-10 15:30:07 -0700244 UNUSED(abi);
245 UNUSED(offset);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700246 LOG(FATAL) << "Unexpected InstructionSet: " << isa;
Ian Rogersd4c4d952014-10-16 20:31:53 -0700247 UNREACHABLE();
Ian Rogersdd7624d2014-03-14 17:43:00 -0700248 }
249}
250
Vladimir Marko93205e32016-04-13 11:59:46 +0100251std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline32(InstructionSet isa,
252 EntryPointCallingConvention abi,
Andreas Gampe542451c2016-07-26 09:02:02 -0700253 ThreadOffset32 offset) {
Vladimir Marko93205e32016-04-13 11:59:46 +0100254 ArenaPool pool;
255 ArenaAllocator arena(&pool);
Ian Rogers659efe72013-08-07 22:54:13 -0700256 switch (isa) {
Alex Light50fa9932015-08-10 15:30:07 -0700257#ifdef ART_ENABLE_CODEGEN_arm
Ian Rogers659efe72013-08-07 22:54:13 -0700258 case kArm:
259 case kThumb2:
Vladimir Marko93205e32016-04-13 11:59:46 +0100260 return arm::CreateTrampoline(&arena, abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700261#endif
262#ifdef ART_ENABLE_CODEGEN_mips
Ian Rogers659efe72013-08-07 22:54:13 -0700263 case kMips:
Vladimir Marko93205e32016-04-13 11:59:46 +0100264 return mips::CreateTrampoline(&arena, abi, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700265#endif
266#ifdef ART_ENABLE_CODEGEN_x86
Ian Rogers659efe72013-08-07 22:54:13 -0700267 case kX86:
Alex Light50fa9932015-08-10 15:30:07 -0700268 UNUSED(abi);
Vladimir Marko93205e32016-04-13 11:59:46 +0100269 return x86::CreateTrampoline(&arena, offset);
Alex Light50fa9932015-08-10 15:30:07 -0700270#endif
Ian Rogers659efe72013-08-07 22:54:13 -0700271 default:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700272 LOG(FATAL) << "Unexpected InstructionSet: " << isa;
Ian Rogersd4c4d952014-10-16 20:31:53 -0700273 UNREACHABLE();
Ian Rogers659efe72013-08-07 22:54:13 -0700274 }
275}
276
277} // namespace art