blob: dfbd5247f90cf15dc08f23a581bf213bd555c3d9 [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) {
Elliott Hughes362f9bc2011-10-17 18:56:41 -070013 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
Ian Rogersad25ac52011-10-04 19:13:33 -070014 // | Out args |
15 // | Method* | <- SP on entry
16 // | LR | return address into caller
17 // | R3 | possible argument
18 // | R2 | possible argument
19 // | R1 | possible argument
20 // | R0 | method index (loaded from code and method array - will be converted to Method*)
Ian Rogers4f0d07c2011-10-06 23:38:47 -070021 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
Ian Rogersad25ac52011-10-04 19:13:33 -070022 __ PushList(save);
23 __ mov(R1, ShifterOperand(SP)); // Pass address of saved R0... in R1
24 __ LoadFromOffset(kLoadWord, R12, TR,
25 OFFSETOF_MEMBER(Thread, pUnresolvedDirectMethodTrampolineFromCode));
26 __ mov(R2, ShifterOperand(TR)); // Pass Thread::Current() in R2
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070027 __ LoadImmediate(R3, type);
Ian Rogersad25ac52011-10-04 19:13:33 -070028 __ IncreaseFrameSize(12); // 3 words of space for alignment
29 // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
30 __ blx(R12);
Ian Rogers4f0d07c2011-10-06 23:38:47 -070031 __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
Ian Rogersad25ac52011-10-04 19:13:33 -070032 // Restore registers which may have been modified by GC and R0 which will now hold the method*
33 __ DecreaseFrameSize(12);
34 __ PopList(save);
Ian Rogersae675992011-10-09 17:10:22 -070035 __ bx(R12); // Leaf call to method's code
Ian Rogersad25ac52011-10-04 19:13:33 -070036
37 __ bkpt(0);
38
39 assembler->EmitSlowPaths();
40 size_t cs = assembler->CodeSize();
41 ByteArray* resolution_trampoline = ByteArray::Alloc(cs);
42 CHECK(resolution_trampoline != NULL);
43 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
44 assembler->FinalizeInstructions(code);
45
46 return resolution_trampoline;
47}
48
Shih-wei Liaoc486c112011-09-13 16:43:52 -070049typedef void (*ThrowAme)(Method*, Thread*);
50
Ian Rogersbdb03912011-09-14 00:55:44 -070051ByteArray* CreateAbstractMethodErrorStub() {
Elliott Hughes362f9bc2011-10-17 18:56:41 -070052 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
Ian Rogersff1ed472011-09-20 13:46:24 -070053 // Save callee saves and ready frame for exception delivery
Ian Rogers4f0d07c2011-10-06 23:38:47 -070054 RegList save = (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) | (1 << R9) |
55 (1 << R10) | (1 << R11) | (1 << LR);
56 __ PushList(save); // push {r4-r11, lr} - 9 words of callee saves
57 __ Emit(0xed2d0a20); // vpush {s0-s31}
58 __ IncreaseFrameSize(12); // 3 words of space, bottom word will hold callee save Method*
Shih-wei Liaoc486c112011-09-13 16:43:52 -070059
Ian Rogersff1ed472011-09-20 13:46:24 -070060 // R0 is the Method* already
61 __ mov(R1, ShifterOperand(R9)); // Pass Thread::Current() in R1
62 __ mov(R2, ShifterOperand(SP)); // Pass SP in R2
Ian Rogersbdb03912011-09-14 00:55:44 -070063 // Call to throw AbstractMethodError
64 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode));
Ian Rogers4f0d07c2011-10-06 23:38:47 -070065 __ mov(PC, ShifterOperand(R12)); // Leaf call to routine that never returns
Shih-wei Liaoc486c112011-09-13 16:43:52 -070066
67 __ bkpt(0);
68
69 assembler->EmitSlowPaths();
70
71 size_t cs = assembler->CodeSize();
72 ByteArray* abstract_stub = ByteArray::Alloc(cs);
73 CHECK(abstract_stub != NULL);
Brian Carlstrome24fa612011-09-29 00:53:55 -070074 CHECK(abstract_stub->GetClass()->GetDescriptor());
Shih-wei Liaoc486c112011-09-13 16:43:52 -070075 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
76 assembler->FinalizeInstructions(code);
77
78 return abstract_stub;
79}
80
Shih-wei Liao31384c52011-09-06 15:27:45 -070081ByteArray* CreateJniStub() {
Elliott Hughes362f9bc2011-10-17 18:56:41 -070082 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
Ian Rogers4f0d07c2011-10-06 23:38:47 -070083 // Build frame and save argument registers and LR.
Shih-wei Liao31384c52011-09-06 15:27:45 -070084 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
Shih-wei Liao31384c52011-09-06 15:27:45 -070085 __ PushList(save);
Ian Rogers4f0d07c2011-10-06 23:38:47 -070086 __ AddConstant(SP, -12); // Ensure 16-byte alignment
87 __ mov(R0, ShifterOperand(R9)); // Pass Thread::Current() in R0
Shih-wei Liao31384c52011-09-06 15:27:45 -070088 // Call FindNativeMethod
Brian Carlstrom16192862011-09-12 17:50:06 -070089 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod));
Shih-wei Liao31384c52011-09-06 15:27:45 -070090 __ blx(R12);
Ian Rogers4f0d07c2011-10-06 23:38:47 -070091 __ mov(R12, ShifterOperand(R0)); // Save result of FindNativeMethod in R12
Ian Rogersae675992011-10-09 17:10:22 -070092 __ AddConstant(SP, 12); // Restore registers (including outgoing arguments)
Shih-wei Liao31384c52011-09-06 15:27:45 -070093 __ PopList(save);
Shih-wei Liao31384c52011-09-06 15:27:45 -070094 __ cmp(R12, ShifterOperand(0));
Ian Rogersae675992011-10-09 17:10:22 -070095 __ bx(R12, NE); // If R12 != 0 tail call into native code
96 __ bx(LR); // Return to caller to handle exception
Shih-wei Liao31384c52011-09-06 15:27:45 -070097
98 assembler->EmitSlowPaths();
99
100 size_t cs = assembler->CodeSize();
101 ByteArray* jni_stub = ByteArray::Alloc(cs);
102 CHECK(jni_stub != NULL);
103 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
104 assembler->FinalizeInstructions(code);
105
106 return jni_stub;
107}
108
109} // namespace arm
110} // namespace art