blob: aeee8c8d60c6bab6e8c3df55b871f2c7ff5c2cc6 [file] [log] [blame]
Shih-wei Liao31384c52011-09-06 15:27:45 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "assembler_arm.h"
4#include "jni_internal.h"
5#include "object.h"
6
7#define __ assembler->
8
9namespace art {
10namespace arm {
11
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070012ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) {
Ian Rogersad25ac52011-10-04 19:13:33 -070013 UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
14 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
15
16 // | Out args |
17 // | Method* | <- SP on entry
18 // | LR | return address into caller
19 // | R3 | possible argument
20 // | R2 | possible argument
21 // | R1 | possible argument
22 // | R0 | method index (loaded from code and method array - will be converted to Method*)
23 __ PushList(save);
24 __ mov(R1, ShifterOperand(SP)); // Pass address of saved R0... in R1
25 __ LoadFromOffset(kLoadWord, R12, TR,
26 OFFSETOF_MEMBER(Thread, pUnresolvedDirectMethodTrampolineFromCode));
27 __ mov(R2, ShifterOperand(TR)); // Pass Thread::Current() in R2
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070028 __ LoadImmediate(R3, type);
Ian Rogersad25ac52011-10-04 19:13:33 -070029 __ IncreaseFrameSize(12); // 3 words of space for alignment
30 // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
31 __ blx(R12);
32 // Save code address returned into R12
33 __ mov(R12, ShifterOperand(R0));
34 // Restore registers which may have been modified by GC and R0 which will now hold the method*
35 __ DecreaseFrameSize(12);
36 __ PopList(save);
37 // Leaf call to method's code
38 __ mov(PC, ShifterOperand(R12));
39
40 __ bkpt(0);
41
42 assembler->EmitSlowPaths();
43 size_t cs = assembler->CodeSize();
44 ByteArray* resolution_trampoline = ByteArray::Alloc(cs);
45 CHECK(resolution_trampoline != NULL);
46 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
47 assembler->FinalizeInstructions(code);
48
49 return resolution_trampoline;
50}
51
Shih-wei Liaoc486c112011-09-13 16:43:52 -070052typedef void (*ThrowAme)(Method*, Thread*);
53
Ian Rogersbdb03912011-09-14 00:55:44 -070054ByteArray* CreateAbstractMethodErrorStub() {
Shih-wei Liaoc486c112011-09-13 16:43:52 -070055 UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
56
Ian Rogersff1ed472011-09-20 13:46:24 -070057 // Save callee saves and ready frame for exception delivery
58 RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
59 (1 << R8) | (1 << R9) | (1 << R10) | (1 << R11) | (1 << LR);
60 __ PushList(save);
Ian Rogers15fdb8c2011-09-25 15:45:07 -070061 __ Emit(0xed2d0a20); // vpush {s0-s31}
Ian Rogersff1ed472011-09-20 13:46:24 -070062 __ IncreaseFrameSize(16); // 4 words of space, bottom word will hold callee save Method*
Shih-wei Liaoc486c112011-09-13 16:43:52 -070063
Ian Rogersff1ed472011-09-20 13:46:24 -070064 // R0 is the Method* already
65 __ mov(R1, ShifterOperand(R9)); // Pass Thread::Current() in R1
66 __ mov(R2, ShifterOperand(SP)); // Pass SP in R2
Ian Rogersbdb03912011-09-14 00:55:44 -070067 // Call to throw AbstractMethodError
68 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode));
Shih-wei Liaoc486c112011-09-13 16:43:52 -070069 // Leaf call to routine that never returns
70 __ mov(PC, ShifterOperand(R12));
71
72 __ bkpt(0);
73
74 assembler->EmitSlowPaths();
75
76 size_t cs = assembler->CodeSize();
77 ByteArray* abstract_stub = ByteArray::Alloc(cs);
78 CHECK(abstract_stub != NULL);
Brian Carlstrome24fa612011-09-29 00:53:55 -070079 CHECK(abstract_stub->GetClass()->GetDescriptor());
Shih-wei Liaoc486c112011-09-13 16:43:52 -070080 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
81 assembler->FinalizeInstructions(code);
82
83 return abstract_stub;
84}
85
Shih-wei Liao31384c52011-09-06 15:27:45 -070086ByteArray* CreateJniStub() {
87 UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
88
89 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
90
91 // Build frame and save registers. Save 5 registers.
92 __ PushList(save);
93 // Ensure 16-byte alignment
94 __ AddConstant(SP, -12);
95
96 // Pass Thread::Current() in R0
97 __ mov(R0, ShifterOperand(R9));
98
99 // Call FindNativeMethod
Brian Carlstrom16192862011-09-12 17:50:06 -0700100 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod));
Shih-wei Liao31384c52011-09-06 15:27:45 -0700101 __ blx(R12);
102
103 // Save result of FindNativeMethod in R12
104 __ mov(R12, ShifterOperand(R0));
105
106 // Restore registers (including outgoing arguments)
107 __ AddConstant(SP, 12);
108 __ PopList(save);
109
110 __ cmp(R12, ShifterOperand(0));
111
112 // If R12 != 0 tail call into native code
113 __ mov(PC, ShifterOperand(R12), NE);
114
115 // Return to caller to handle exception
116 __ mov(PC, ShifterOperand(LR));
117
118 assembler->EmitSlowPaths();
119
120 size_t cs = assembler->CodeSize();
121 ByteArray* jni_stub = ByteArray::Alloc(cs);
122 CHECK(jni_stub != NULL);
123 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
124 assembler->FinalizeInstructions(code);
125
126 return jni_stub;
127}
128
129} // namespace arm
130} // namespace art