blob: 29d6bb2d1db1f37d7e19cafe47bb826d821a93e9 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Shih-wei Liao31384c52011-09-06 15:27:45 -070016
17#include "assembler_arm.h"
18#include "jni_internal.h"
19#include "object.h"
Brian Carlstrom40381fb2011-10-19 14:13:40 -070020#include "stack_indirect_reference_table.h"
Shih-wei Liao31384c52011-09-06 15:27:45 -070021
22#define __ assembler->
23
24namespace art {
25namespace arm {
26
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070027ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) {
Elliott Hughes362f9bc2011-10-17 18:56:41 -070028 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
Ian Rogersad25ac52011-10-04 19:13:33 -070029 // | Out args |
30 // | Method* | <- SP on entry
31 // | LR | return address into caller
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070032 // | ... | callee saves
Ian Rogersad25ac52011-10-04 19:13:33 -070033 // | R3 | possible argument
34 // | R2 | possible argument
35 // | R1 | possible argument
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070036 // | R0 | junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
37 // | Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
38 // Save callee saves and ready frame for exception delivery
39 RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) |
40 (1 << R10) | (1 << R11) | (1 << LR);
41 // TODO: enable when GetCalleeSaveMethod is available at stub generation time
42 // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
Ian Rogersad25ac52011-10-04 19:13:33 -070043 __ PushList(save);
Ian Rogersad25ac52011-10-04 19:13:33 -070044 __ LoadFromOffset(kLoadWord, R12, TR,
45 OFFSETOF_MEMBER(Thread, pUnresolvedDirectMethodTrampolineFromCode));
46 __ mov(R2, ShifterOperand(TR)); // Pass Thread::Current() in R2
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070047 __ LoadImmediate(R3, type);
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070048 __ IncreaseFrameSize(8); // 2 words of space for alignment
49 __ mov(R1, ShifterOperand(SP)); // Pass SP
Ian Rogersad25ac52011-10-04 19:13:33 -070050 // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
51 __ blx(R12);
Ian Rogers4f0d07c2011-10-06 23:38:47 -070052 __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070053 // Restore registers which may have been modified by GC, "R0" will hold the Method*
54 __ DecreaseFrameSize(4);
55 __ PopList((1 << R0) | save);
Ian Rogersae675992011-10-09 17:10:22 -070056 __ bx(R12); // Leaf call to method's code
Ian Rogersad25ac52011-10-04 19:13:33 -070057
58 __ bkpt(0);
59
60 assembler->EmitSlowPaths();
61 size_t cs = assembler->CodeSize();
Brian Carlstrom40381fb2011-10-19 14:13:40 -070062 SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
63 CHECK(resolution_trampoline.get() != NULL);
Ian Rogersad25ac52011-10-04 19:13:33 -070064 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
65 assembler->FinalizeInstructions(code);
66
Brian Carlstrom40381fb2011-10-19 14:13:40 -070067 return resolution_trampoline.get();
Ian Rogersad25ac52011-10-04 19:13:33 -070068}
69
Shih-wei Liaoc486c112011-09-13 16:43:52 -070070typedef void (*ThrowAme)(Method*, Thread*);
71
Ian Rogersbdb03912011-09-14 00:55:44 -070072ByteArray* CreateAbstractMethodErrorStub() {
Elliott Hughes362f9bc2011-10-17 18:56:41 -070073 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
Ian Rogersff1ed472011-09-20 13:46:24 -070074 // Save callee saves and ready frame for exception delivery
Ian Rogers4f0d07c2011-10-06 23:38:47 -070075 RegList save = (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) | (1 << R9) |
76 (1 << R10) | (1 << R11) | (1 << LR);
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070077 // TODO: enable when GetCalleeSaveMethod is available at stub generation time
78 // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetCoreSpillMask());
Ian Rogers4f0d07c2011-10-06 23:38:47 -070079 __ PushList(save); // push {r4-r11, lr} - 9 words of callee saves
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070080 // TODO: enable when GetCalleeSaveMethod is available at stub generation time
81 // DCHECK_EQ(Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetFpSpillMask(), 0xFFFFU);
Ian Rogers4f0d07c2011-10-06 23:38:47 -070082 __ Emit(0xed2d0a20); // vpush {s0-s31}
Brian Carlstrom6a4be3a2011-10-20 16:34:03 -070083
Ian Rogers4f0d07c2011-10-06 23:38:47 -070084 __ IncreaseFrameSize(12); // 3 words of space, bottom word will hold callee save Method*
Shih-wei Liaoc486c112011-09-13 16:43:52 -070085
Ian Rogersff1ed472011-09-20 13:46:24 -070086 // R0 is the Method* already
87 __ mov(R1, ShifterOperand(R9)); // Pass Thread::Current() in R1
88 __ mov(R2, ShifterOperand(SP)); // Pass SP in R2
Ian Rogersbdb03912011-09-14 00:55:44 -070089 // Call to throw AbstractMethodError
90 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode));
Ian Rogers4f0d07c2011-10-06 23:38:47 -070091 __ mov(PC, ShifterOperand(R12)); // Leaf call to routine that never returns
Shih-wei Liaoc486c112011-09-13 16:43:52 -070092
93 __ bkpt(0);
94
95 assembler->EmitSlowPaths();
96
97 size_t cs = assembler->CodeSize();
Brian Carlstrom40381fb2011-10-19 14:13:40 -070098 SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
99 CHECK(abstract_stub.get() != NULL);
Shih-wei Liaoc486c112011-09-13 16:43:52 -0700100 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
101 assembler->FinalizeInstructions(code);
102
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700103 return abstract_stub.get();
Shih-wei Liaoc486c112011-09-13 16:43:52 -0700104}
105
Elliott Hughes8add92d2012-01-18 18:18:43 -0800106ByteArray* CreateJniDlsymLookupStub() {
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700107 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700108 // Build frame and save argument registers and LR.
Shih-wei Liao31384c52011-09-06 15:27:45 -0700109 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700110 __ PushList(save);
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700111 __ AddConstant(SP, -12); // Ensure 16-byte alignment
112 __ mov(R0, ShifterOperand(R9)); // Pass Thread::Current() in R0
Shih-wei Liao31384c52011-09-06 15:27:45 -0700113 // Call FindNativeMethod
Brian Carlstrom16192862011-09-12 17:50:06 -0700114 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod));
Shih-wei Liao31384c52011-09-06 15:27:45 -0700115 __ blx(R12);
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700116 __ mov(R12, ShifterOperand(R0)); // Save result of FindNativeMethod in R12
Ian Rogersae675992011-10-09 17:10:22 -0700117 __ AddConstant(SP, 12); // Restore registers (including outgoing arguments)
Shih-wei Liao31384c52011-09-06 15:27:45 -0700118 __ PopList(save);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700119 __ cmp(R12, ShifterOperand(0));
Ian Rogersae675992011-10-09 17:10:22 -0700120 __ bx(R12, NE); // If R12 != 0 tail call into native code
121 __ bx(LR); // Return to caller to handle exception
Shih-wei Liao31384c52011-09-06 15:27:45 -0700122
123 assembler->EmitSlowPaths();
124
125 size_t cs = assembler->CodeSize();
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700126 SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
127 CHECK(jni_stub.get() != NULL);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700128 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
129 assembler->FinalizeInstructions(code);
130
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700131 return jni_stub.get();
Shih-wei Liao31384c52011-09-06 15:27:45 -0700132}
133
134} // namespace arm
135} // namespace art