portable_entrypoints_arm.S revision e832e64a7e82d7f72aedbd7d798fb929d458ee8f
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright (C) 2012 The Android Open Source Project 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License"); 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * you may not use this file except in compliance with the License. 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * You may obtain a copy of the License at 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * http://www.apache.org/licenses/LICENSE-2.0 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS, 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * See the License for the specific language governing permissions and 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * limitations under the License. 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "asm_support_arm.S" 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Portable invocation stub. 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * On entry: 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * r0 = method pointer 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * r1 = argument array or NULL for no argument methods 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * r2 = size of argument array in bytes 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * r3 = (managed) thread pointer 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * [sp] = JValue* result 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * [sp + 4] = result type char 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruENTRY art_portable_invoke_stub 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru push {r0, r4, r5, r9, r11, lr} @ spill regs 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .save {r0, r4, r5, r9, r11, lr} 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_adjust_cfa_offset 24 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_rel_offset r0, 0 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_rel_offset r4, 4 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_rel_offset r5, 8 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_rel_offset r9, 12 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_rel_offset r11, 16 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_rel_offset lr, 20 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru mov r11, sp @ save the stack pointer 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru .cfi_def_cfa_register r11 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru @.movsp r11 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru mov r9, r3 @ move managed thread pointer into r9 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru mov r4, #SUSPEND_CHECK_INTERVAL @ reset r4 to suspend check interval 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru add r5, r2, #16 @ create space for method pointer in frame 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru and r5, #0xFFFFFFF0 @ align frame size to 16 bytes 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sub sp, r5 @ reserve stack space for argument array 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru add r0, sp, #4 @ pass stack pointer + method ptr as dest for memcpy 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru bl memcpy @ memcpy (dest, src, bytes) 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ldr r0, [r11] @ restore method* 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ldr r1, [sp, #4] @ copy arg value for r1 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ldr r2, [sp, #8] @ copy arg value for r2 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ldr r3, [sp, #12] @ copy arg value for r3 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru mov ip, #0 @ set ip to 0 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str ip, [sp] @ store NULL for method* at bottom of frame 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru add sp, #16 @ first 4 args are not passed on stack for portable 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ldr ip, [r0, #METHOD_PORTABLE_CODE_OFFSET_32] @ get pointer to the code 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru blx ip @ call the method 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru mov sp, r11 @ restore the stack pointer 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ldr ip, [sp, #24] @ load the result pointer 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru strd r0, [ip] @ store r0/r1 into result pointer 61 pop {r0, r4, r5, r9, r11, lr} @ restore spill regs 62 .cfi_adjust_cfa_offset -24 63 bx lr 64END art_portable_invoke_stub 65 66 .extern artPortableProxyInvokeHandler 67ENTRY art_portable_proxy_invoke_handler 68 @ Fake callee save ref and args frame set up, note portable doesn't use callee save frames. 69 @ TODO: just save the registers that are needed in artPortableProxyInvokeHandler. 70 push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves 71 .save {r1-r3, r5-r8, r10-r11, lr} 72 .cfi_adjust_cfa_offset 40 73 .cfi_rel_offset r1, 0 74 .cfi_rel_offset r2, 4 75 .cfi_rel_offset r3, 8 76 .cfi_rel_offset r5, 12 77 .cfi_rel_offset r6, 16 78 .cfi_rel_offset r7, 20 79 .cfi_rel_offset r8, 24 80 .cfi_rel_offset r10, 28 81 .cfi_rel_offset r11, 32 82 .cfi_rel_offset lr, 36 83 sub sp, #8 @ 2 words of space, bottom word will hold Method* 84 .pad #8 85 .cfi_adjust_cfa_offset 8 86 @ Begin argument set up. 87 str r0, [sp, #0] @ place proxy method at bottom of frame 88 mov r2, r9 @ pass Thread::Current 89 mov r3, sp @ pass SP 90 blx artPortableProxyInvokeHandler @ (Method* proxy method, receiver, Thread*, SP) 91 ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_ 92 ldr lr, [sp, #44] @ restore lr 93 add sp, #48 @ pop frame 94 .cfi_adjust_cfa_offset -48 95 bx lr @ return 96END art_portable_proxy_invoke_handler 97 98 .extern artPortableResolutionTrampoline 99ENTRY art_portable_resolution_trampoline 100 @ Fake callee save ref and args frame set up, note portable doesn't use callee save frames. 101 @ TODO: just save the registers that are needed in artPortableResolutionTrampoline. 102 push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves 103 .save {r1-r3, r5-r8, r10-r11, lr} 104 .cfi_adjust_cfa_offset 40 105 .cfi_rel_offset r1, 0 106 .cfi_rel_offset r2, 4 107 .cfi_rel_offset r3, 8 108 .cfi_rel_offset r5, 12 109 .cfi_rel_offset r6, 16 110 .cfi_rel_offset r7, 20 111 .cfi_rel_offset r8, 24 112 .cfi_rel_offset r10, 28 113 .cfi_rel_offset r11, 32 114 .cfi_rel_offset lr, 36 115 sub sp, #8 @ 2 words of space, bottom word will hold Method* 116 .pad #8 117 .cfi_adjust_cfa_offset 8 118 mov r2, r9 @ pass Thread::Current 119 mov r3, sp @ pass SP 120 blx artPortableResolutionTrampoline @ (Method* called, receiver, Thread*, SP) 121 cmp r0, #0 @ is code pointer null? 122 beq 1f @ goto exception 123 mov r12, r0 124 ldr r0, [sp, #0] @ load resolved method in r0 125 ldr r1, [sp, #8] @ restore non-callee save r1 126 ldrd r2, [sp, #12] @ restore non-callee saves r2-r3 127 ldr lr, [sp, #44] @ restore lr 128 add sp, #48 @ rewind sp 129 .cfi_adjust_cfa_offset -48 130 bx r12 @ tail-call into actual code 1311: 132 ldr r1, [sp, #8] @ restore non-callee save r1 133 ldrd r2, [sp, #12] @ restore non-callee saves r2-r3 134 ldr lr, [sp, #44] @ restore lr 135 add sp, #48 @ rewind sp 136 .cfi_adjust_cfa_offset -48 137 bx lr 138END art_portable_resolution_trampoline 139 140 .extern artPortableToInterpreterBridge 141ENTRY_NO_HIDE art_portable_to_interpreter_bridge 142 @ Fake callee save ref and args frame set up, note portable doesn't use callee save frames. 143 @ TODO: just save the registers that are needed in artPortableToInterpreterBridge. 144 push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves 145 .save {r1-r3, r5-r8, r10-r11, lr} 146 .cfi_adjust_cfa_offset 40 147 .cfi_rel_offset r1, 0 148 .cfi_rel_offset r2, 4 149 .cfi_rel_offset r3, 8 150 .cfi_rel_offset r5, 12 151 .cfi_rel_offset r6, 16 152 .cfi_rel_offset r7, 20 153 .cfi_rel_offset r8, 24 154 .cfi_rel_offset r10, 28 155 .cfi_rel_offset r11, 32 156 .cfi_rel_offset lr, 36 157 sub sp, #8 @ 2 words of space, bottom word will hold Method* 158 .pad #8 159 .cfi_adjust_cfa_offset 8 160 mov r1, r9 @ pass Thread::Current 161 mov r2, sp @ pass SP 162 blx artPortableToInterpreterBridge @ (Method* method, Thread*, SP) 163 ldr lr, [sp, #44] @ restore lr 164 add sp, #48 @ pop frame 165 .cfi_adjust_cfa_offset -48 166 bx lr @ return 167END art_portable_to_interpreter_bridge 168