| Shih-wei Liao | 31384c5 | 2011-09-06 15:27:45 -0700 | [diff] [blame] | 1 | // 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 |  | 
|  | 9 | namespace art { | 
|  | 10 | namespace arm { | 
|  | 11 |  | 
| Shih-wei Liao | c486c11 | 2011-09-13 16:43:52 -0700 | [diff] [blame] | 12 | typedef void (*ThrowAme)(Method*, Thread*); | 
|  | 13 |  | 
| Ian Rogers | bdb0391 | 2011-09-14 00:55:44 -0700 | [diff] [blame] | 14 | ByteArray* CreateAbstractMethodErrorStub() { | 
| Shih-wei Liao | c486c11 | 2011-09-13 16:43:52 -0700 | [diff] [blame] | 15 | UniquePtr<ArmAssembler> assembler( static_cast<ArmAssembler*>(Assembler::Create(kArm)) ); | 
|  | 16 |  | 
| Ian Rogers | ff1ed47 | 2011-09-20 13:46:24 -0700 | [diff] [blame] | 17 | // 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 Rogers | 15fdb8c | 2011-09-25 15:45:07 -0700 | [diff] [blame] | 21 | __ Emit(0xed2d0a20);  // vpush {s0-s31} | 
| Ian Rogers | ff1ed47 | 2011-09-20 13:46:24 -0700 | [diff] [blame] | 22 | __ IncreaseFrameSize(16);  // 4 words of space, bottom word will hold callee save Method* | 
| Shih-wei Liao | c486c11 | 2011-09-13 16:43:52 -0700 | [diff] [blame] | 23 |  | 
| Ian Rogers | ff1ed47 | 2011-09-20 13:46:24 -0700 | [diff] [blame] | 24 | // 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 Rogers | bdb0391 | 2011-09-14 00:55:44 -0700 | [diff] [blame] | 27 | // Call to throw AbstractMethodError | 
|  | 28 | __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode)); | 
| Shih-wei Liao | c486c11 | 2011-09-13 16:43:52 -0700 | [diff] [blame] | 29 | // 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 Carlstrom | e24fa61 | 2011-09-29 00:53:55 -0700 | [diff] [blame^] | 39 | CHECK(abstract_stub->GetClass()->GetDescriptor()); | 
| Shih-wei Liao | c486c11 | 2011-09-13 16:43:52 -0700 | [diff] [blame] | 40 | MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); | 
|  | 41 | assembler->FinalizeInstructions(code); | 
|  | 42 |  | 
|  | 43 | return abstract_stub; | 
|  | 44 | } | 
|  | 45 |  | 
| Shih-wei Liao | 31384c5 | 2011-09-06 15:27:45 -0700 | [diff] [blame] | 46 | ByteArray* 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 Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 60 | __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod)); | 
| Shih-wei Liao | 31384c5 | 2011-09-06 15:27:45 -0700 | [diff] [blame] | 61 | __ 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 |