blob: 75d60f553ca0191139452b4e7a174297d1d6764e [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
Shih-wei Liaoc486c112011-09-13 16:43:52 -070012typedef void (*ThrowAme)(Method*, Thread*);
13
Ian Rogersbdb03912011-09-14 00:55:44 -070014ByteArray* CreateAbstractMethodErrorStub() {
Shih-wei Liaoc486c112011-09-13 16:43:52 -070015 UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
16
Ian Rogersff1ed472011-09-20 13:46:24 -070017 // Save callee saves and ready frame for exception delivery
18 RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
19 (1 << R8) | (1 << R9) | (1 << R10) | (1 << R11) | (1 << LR);
20 __ PushList(save);
Ian Rogers15fdb8c2011-09-25 15:45:07 -070021 __ Emit(0xed2d0a20); // vpush {s0-s31}
Ian Rogersff1ed472011-09-20 13:46:24 -070022 __ IncreaseFrameSize(16); // 4 words of space, bottom word will hold callee save Method*
Shih-wei Liaoc486c112011-09-13 16:43:52 -070023
Ian Rogersff1ed472011-09-20 13:46:24 -070024 // R0 is the Method* already
25 __ mov(R1, ShifterOperand(R9)); // Pass Thread::Current() in R1
26 __ mov(R2, ShifterOperand(SP)); // Pass SP in R2
Ian Rogersbdb03912011-09-14 00:55:44 -070027 // Call to throw AbstractMethodError
28 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode));
Shih-wei Liaoc486c112011-09-13 16:43:52 -070029 // Leaf call to routine that never returns
30 __ mov(PC, ShifterOperand(R12));
31
32 __ bkpt(0);
33
34 assembler->EmitSlowPaths();
35
36 size_t cs = assembler->CodeSize();
37 ByteArray* abstract_stub = ByteArray::Alloc(cs);
38 CHECK(abstract_stub != NULL);
Brian Carlstrome24fa612011-09-29 00:53:55 -070039 CHECK(abstract_stub->GetClass()->GetDescriptor());
Shih-wei Liaoc486c112011-09-13 16:43:52 -070040 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
41 assembler->FinalizeInstructions(code);
42
43 return abstract_stub;
44}
45
Shih-wei Liao31384c52011-09-06 15:27:45 -070046ByteArray* CreateJniStub() {
47 UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) );
48
49 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
50
51 // Build frame and save registers. Save 5 registers.
52 __ PushList(save);
53 // Ensure 16-byte alignment
54 __ AddConstant(SP, -12);
55
56 // Pass Thread::Current() in R0
57 __ mov(R0, ShifterOperand(R9));
58
59 // Call FindNativeMethod
Brian Carlstrom16192862011-09-12 17:50:06 -070060 __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod));
Shih-wei Liao31384c52011-09-06 15:27:45 -070061 __ blx(R12);
62
63 // Save result of FindNativeMethod in R12
64 __ mov(R12, ShifterOperand(R0));
65
66 // Restore registers (including outgoing arguments)
67 __ AddConstant(SP, 12);
68 __ PopList(save);
69
70 __ cmp(R12, ShifterOperand(0));
71
72 // If R12 != 0 tail call into native code
73 __ mov(PC, ShifterOperand(R12), NE);
74
75 // Return to caller to handle exception
76 __ mov(PC, ShifterOperand(LR));
77
78 assembler->EmitSlowPaths();
79
80 size_t cs = assembler->CodeSize();
81 ByteArray* jni_stub = ByteArray::Alloc(cs);
82 CHECK(jni_stub != NULL);
83 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
84 assembler->FinalizeInstructions(code);
85
86 return jni_stub;
87}
88
89} // namespace arm
90} // namespace art