blob: 8ab3f8d92154af272d58019db3367617d8b0e46f [file] [log] [blame]
jeffhao7fbee072012-08-24 17:56:54 -07001/*
2 * Copyright (C) 2011 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 "jni_internal.h"
18#include "oat/runtime/oat_support_entrypoints.h"
19#include "oat/runtime/stub.h"
20#include "oat/utils/mips/assembler_mips.h"
21#include "object.h"
22#include "stack_indirect_reference_table.h"
23
24#define __ assembler->
25
26namespace art {
27namespace mips {
28
29ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) {
30 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
31#if !defined(ART_USE_LLVM_COMPILER)
32 // | Out args |
33 // | Method* | <- SP on entry
34 // | RA | return address into caller
35 // | ... | callee saves
36 // | A3 | possible argument
37 // | A2 | possible argument
38 // | A1 | possible argument
39 // | A0 | junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
40 // | Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
41 // Save callee saves and ready frame for exception delivery
42 __ AddConstant(SP, SP, -64);
43 __ StoreToOffset(kStoreWord, RA, SP, 60);
44 __ StoreToOffset(kStoreWord, T9, SP, 56);
45 __ StoreToOffset(kStoreWord, T8, SP, 52);
46 __ StoreToOffset(kStoreWord, T7, SP, 48);
47 __ StoreToOffset(kStoreWord, T6, SP, 44);
48 __ StoreToOffset(kStoreWord, T5, SP, 40);
49 __ StoreToOffset(kStoreWord, T4, SP, 36);
50 __ StoreToOffset(kStoreWord, T3, SP, 32);
51 __ StoreToOffset(kStoreWord, T2, SP, 28);
52 __ StoreToOffset(kStoreWord, T1, SP, 24);
53 __ StoreToOffset(kStoreWord, T0, SP, 20);
54 __ StoreToOffset(kStoreWord, A3, SP, 16);
55 __ StoreToOffset(kStoreWord, A2, SP, 12);
56 __ StoreToOffset(kStoreWord, A1, SP, 8);
57
58 __ LoadFromOffset(kLoadWord, T9, S1,
59 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
60 __ Move(A2, S1); // Pass Thread::Current() in A2
61 __ LoadImmediate(A3, type); // Pass is_static
62 __ Move(A1, SP); // Pass SP for Method** callee_addr
63 __ Jalr(T9); // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
64
65 // Restore registers which may have been modified by GC
66 __ LoadFromOffset(kLoadWord, A1, SP, 8);
67 __ LoadFromOffset(kLoadWord, A2, SP, 12);
68 __ LoadFromOffset(kLoadWord, A3, SP, 16);
69 __ LoadFromOffset(kLoadWord, T0, SP, 20);
70 __ LoadFromOffset(kLoadWord, T1, SP, 24);
71 __ LoadFromOffset(kLoadWord, T2, SP, 28);
72 __ LoadFromOffset(kLoadWord, T3, SP, 32);
73 __ LoadFromOffset(kLoadWord, T4, SP, 36);
74 __ LoadFromOffset(kLoadWord, T5, SP, 40);
75 __ LoadFromOffset(kLoadWord, T6, SP, 44);
76 __ LoadFromOffset(kLoadWord, T7, SP, 48);
77 __ LoadFromOffset(kLoadWord, T8, SP, 52);
78 __ LoadFromOffset(kLoadWord, T9, SP, 56);
79 __ LoadFromOffset(kLoadWord, RA, SP, 60);
80 __ AddConstant(SP, SP, 64);
81
82 __ Move(A0, V0); // Put returned Method* into A0
83 __ Jr(V0); // Leaf call to method's code
84
85 __ Break();
86#else // ART_USE_LLVM_COMPILER
87 // Build frame and save argument registers and RA.
88 __ AddConstant(SP, SP, -32);
89 __ StoreToOffset(kStoreWord, RA, SP, 28);
90 __ StoreToOffset(kStoreWord, A3, SP, 24);
91 __ StoreToOffset(kStoreWord, A2, SP, 20);
92 __ StoreToOffset(kStoreWord, A1, SP, 16);
93 __ StoreToOffset(kStoreWord, A0, SP, 12);
94
95 __ LoadFromOffset(kLoadWord, T9, S1,
96 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
jeffhao0ac41d52012-08-27 13:07:54 -070097 __ Move(A2, S1); // Pass Thread::Current() in A2
jeffhao7fbee072012-08-24 17:56:54 -070098 __ LoadImmediate(A3, type); // Pass is_static
jeffhao0ac41d52012-08-27 13:07:54 -070099 __ Move(A1, SP); // Pass SP for Method** callee_addr
jeffhao7fbee072012-08-24 17:56:54 -0700100 __ Jalr(T9); // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
101
102 // Restore frame, argument registers, and RA.
103 __ LoadFromOffset(kLoadWord, A0, SP, 12);
104 __ LoadFromOffset(kLoadWord, A1, SP, 16);
105 __ LoadFromOffset(kLoadWord, A2, SP, 20);
106 __ LoadFromOffset(kLoadWord, A3, SP, 24);
107 __ LoadFromOffset(kLoadWord, RA, SP, 28);
108 __ AddConstant(SP, SP, 32);
109
110 Label resolve_fail;
111 __ EmitBranch(V0, ZERO, &resolve_fail, true);
112 __ Jr(V0); // If V0 != 0 tail call method's code
113 __ Bind(&resolve_fail, false);
114 __ Jr(RA); // Return to caller to handle exception
115#endif // ART_USE_LLVM_COMPILER
116
117 assembler->EmitSlowPaths();
118
119 size_t cs = assembler->CodeSize();
120 SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
121 CHECK(resolution_trampoline.get() != NULL);
122 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
123 assembler->FinalizeInstructions(code);
124
125 return resolution_trampoline.get();
126}
127
Mathieu Chartier66f19252012-09-18 08:57:04 -0700128typedef void (*ThrowAme)(AbstractMethod*, Thread*);
jeffhao7fbee072012-08-24 17:56:54 -0700129
130ByteArray* CreateAbstractMethodErrorStub() {
131 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
132#if !defined(ART_USE_LLVM_COMPILER)
133 // Save callee saves and ready frame for exception delivery
134 __ AddConstant(SP, SP, -176);
135 __ StoreToOffset(kStoreWord, RA, SP, 172);
136 __ StoreToOffset(kStoreWord, T9, SP, 168);
137 __ StoreToOffset(kStoreWord, T8, SP, 164);
138 __ StoreToOffset(kStoreWord, T7, SP, 160);
139 __ StoreToOffset(kStoreWord, T6, SP, 156);
140 __ StoreToOffset(kStoreWord, T5, SP, 152);
141 __ StoreToOffset(kStoreWord, T4, SP, 148);
142 __ StoreToOffset(kStoreWord, T3, SP, 144);
143 __ StoreToOffset(kStoreWord, T2, SP, 140);
144 __ StoreToOffset(kStoreWord, T1, SP, 136);
145 __ StoreToOffset(kStoreWord, T0, SP, 132);
146 __ StoreDToOffset(D15, SP, 124);
147 __ StoreDToOffset(D14, SP, 116);
148 __ StoreDToOffset(D13, SP, 108);
149 __ StoreDToOffset(D12, SP, 100);
150 __ StoreDToOffset(D11, SP, 92);
151 __ StoreDToOffset(D10, SP, 84);
152 __ StoreDToOffset(D9, SP, 76);
153 __ StoreDToOffset(D8, SP, 68);
154 __ StoreDToOffset(D7, SP, 60);
155 __ StoreDToOffset(D6, SP, 52);
156 __ StoreDToOffset(D5, SP, 44);
157 __ StoreDToOffset(D4, SP, 36);
158 __ StoreDToOffset(D3, SP, 28);
159 __ StoreDToOffset(D2, SP, 20);
160 __ StoreDToOffset(D1, SP, 12);
161 __ StoreDToOffset(D0, SP, 4);
162
163 // R0 is the Method* already
164 __ Move(A1, S1); // Pass Thread::Current() in A1
165 __ Move(A2, SP); // Pass SP in A2
166 // Call to throw AbstractMethodError
167 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
168 __ Jr(T9); // Leaf call to routine that never returns
169
170 __ Break();
171#else // ART_USE_LLVM_COMPILER
172 // R0 is the Method* already
173 __ Move(A1, S1); // Pass Thread::Current() in A1
174 // Call to throw AbstractMethodError
175 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
176 __ Jr(T9); // Leaf call to routine that never returns
177
178 __ Break();
179#endif // ART_USE_LLVM_COMPILER
180
181 assembler->EmitSlowPaths();
182
183 size_t cs = assembler->CodeSize();
184 SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
185 CHECK(abstract_stub.get() != NULL);
186 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
187 assembler->FinalizeInstructions(code);
188
189 return abstract_stub.get();
190}
191
192ByteArray* CreateJniDlsymLookupStub() {
193 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
194
195 // Build frame and save argument registers and RA.
196 __ AddConstant(SP, SP, -32);
197 __ StoreToOffset(kStoreWord, RA, SP, 28);
198 __ StoreToOffset(kStoreWord, A3, SP, 24);
199 __ StoreToOffset(kStoreWord, A2, SP, 20);
200 __ StoreToOffset(kStoreWord, A1, SP, 16);
201 __ StoreToOffset(kStoreWord, A0, SP, 12);
202
203 __ Move(A0, S1); // Pass Thread::Current() in A0
204 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pFindNativeMethod));
205 __ Jalr(T9); // Call FindNativeMethod
206
207 // Restore frame, argument registers, and RA.
208 __ LoadFromOffset(kLoadWord, A0, SP, 12);
209 __ LoadFromOffset(kLoadWord, A1, SP, 16);
210 __ LoadFromOffset(kLoadWord, A2, SP, 20);
211 __ LoadFromOffset(kLoadWord, A3, SP, 24);
212 __ LoadFromOffset(kLoadWord, RA, SP, 28);
213 __ AddConstant(SP, SP, 32);
214
215 Label no_native_code_found;
216 __ EmitBranch(V0, ZERO, &no_native_code_found, true);
217 __ Jr(V0); // If V0 != 0 tail call method's code
218 __ Bind(&no_native_code_found, false);
219 __ Jr(RA); // Return to caller to handle exception
220
221 assembler->EmitSlowPaths();
222
223 size_t cs = assembler->CodeSize();
224 SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
225 CHECK(jni_stub.get() != NULL);
226 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
227 assembler->FinalizeInstructions(code);
228
229 return jni_stub.get();
230}
231
232} // namespace mips
233} // namespace art