1/** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "arch/asm_support.h" 17#include "arch/arm/shorty.S" 18#include "shorty_values.h" 19 20#define SHORTY_PTR_REG DEFAULT_SHORTY_PTR_REG 21#define SHORTY_REG DEFAULT_SHORTY_REG 22 23// Frame* CreateFrameForMethod(Method* method, Frame* prev); 24.extern CreateFrameForMethod 25// void InterpreterEntryPoint(Method *method, Frame* frame); 26.extern InterpreterEntryPoint 27// bool IncrementHotnessCounter(Method *method); 28.extern IncrementHotnessCounter 29 30.global CompiledCodeToInterpreterBridge 31.type CompiledCodeToInterpreterBridge, %function 32CompiledCodeToInterpreterBridge: 33 CFI_STARTPROC 34 CFI_DEF_CFA(sp, 0) 35 36 // construct the frame 37 sub sp, sp, #16 38 CFI_ADJUST_CFA_OFFSET(16) 39 str lr, [sp, #12] 40 CFI_REL_OFFSET(lr, 12) 41 mov ip, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 42 str ip, [sp, #8] 43 str fp, [sp, #4] 44 CFI_REL_OFFSET(fp, 4) 45 add fp, sp, #4 46 CFI_DEF_CFA(fp, 12) 47 48 // Save return address to the TLS field 49 str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] 50 51 // save all the callee saved registers to the stack 52 // stack walker will read them during stack unwinding 53 push {r4 - r10} 54 CFI_REL_OFFSET(r10, -(2 * 4)) 55 CFI_REL_OFFSET(r9, -(3 * 4)) 56 CFI_REL_OFFSET(r8, -(4 * 4)) 57 CFI_REL_OFFSET(r7, -(5 * 4)) 58 CFI_REL_OFFSET(r6, -(6 * 4)) 59 CFI_REL_OFFSET(r5, -(7 * 4)) 60 CFI_REL_OFFSET(r4, -(8 * 4)) 61 vpush {d8 - d15} 62 CFI_REL_OFFSET(d15, -(10 * 4)) 63 CFI_REL_OFFSET(d14, -(12 * 4)) 64 CFI_REL_OFFSET(d13, -(14 * 4)) 65 CFI_REL_OFFSET(d12, -(16 * 4)) 66 CFI_REL_OFFSET(d11, -(18 * 4)) 67 CFI_REL_OFFSET(d10, -(20 * 4)) 68 CFI_REL_OFFSET(d9, -(22 * 4)) 69 CFI_REL_OFFSET(d8, -(24 * 4)) 70 71 // align to 8 72 sub sp, sp, #4 73 74 // Before we call IncrementHotnessCounter we should set pointer to C2I frame in the TLS, 75 // because compilation may fall into safepoint, so we need to make caller's callee registers 76 // visible for the stack walker. 77 str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 78 79 push {r0 - r3} 80 vpush {d0 - d7} 81 82 blx IncrementHotnessCounter 83 cmp r0, #0 84 beq .Lnot_compiled 85 vpop {d0 - d7} 86 pop {r0 - r3} 87 88 // Compilation finished, so recover caller's frame in the TLS. 89 sub sp, fp, #4 90 ldr fp, [sp, #4] 91 CFI_REMEMBER_STATE 92 CFI_RESTORE(fp) 93 CFI_DEF_CFA(sp, 16) 94 95 str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 96 ldr lr, [sp, #12] 97 CFI_RESTORE(lr) 98 add sp, sp, #16 // c2i 99 CFI_ADJUST_CFA_OFFSET(-16) 100 101 ldr pc, [r0, #METHOD_COMPILED_ENTRY_POINT_OFFSET] 102 103 CFI_RESTORE_STATE 104 CFI_DEF_CFA(fp, 12) 105 106.Lnot_compiled: 107 vpop {d0 - d7} 108 pop {r0 - r3} 109 110 // save arguments to the stack 111 vpush {d0 - d7} 112 push {r0 - r3} 113 114 mov r4, r0 // save method to r4 to survive the call 115 116 // create an interpreter frame 117 mov r1, fp 118 blx CreateFrameForMethod 119 120 // setup regs as follow 121 // r0 - SHORTY_PTR_REG, r1 - SHORTY_REG, r2 - iframe.vregs_ + num_vregs_, 122 // r3 - gpr args begin, r4 - gpr args end, r5 - fpr args begin, r6 - fpr args end, 123 // r7 - stack args, r8 - iframe, r9, r10, r12 - temps, lr - method 124 mov r8, r0 125 ldr r5, [r8, #FRAME_NUM_VREGS_OFFSET] 126 mov r12, r5, lsl #3 127 ldr r0, [r4, #METHOD_NUM_ARGS_OFFSET] 128 sub r5, r5, r0 129 mov lr, r4 130 ldr SHORTY_PTR_REG, [lr, #METHOD_SHORTY_OFFSET] 131 INIT_SHORTY_REG 132 add r2, r8, #FRAME_VREGS_OFFSET 133 add r2, r2, r5, lsl #3 134 add r3, sp, #4 // skip Method* 135 add r4, sp, #16 136 mov r5, r4 137 add r6, r5, #64 138 add r7, fp, #12 139 140 // parameter 'this' of instance methods is not encoded in the shorty 141 // in case of instance method hack SHORTY_REG by replacing the return type by REF 142 // in the another case just skip the return type 143 144 // check whether the method is an instance 145 ldr r9, [lr, #METHOD_ACCESS_FLAGS_OFFSET] 146 tst r9, #ACCESS_STATIC 147 bne 1f 148 // it is an instance method 149 // replace the return type by REF 150 bic r1, r1, #0xF // clear the the least significant 4 bits 151 orr r1, r1, #SHORTY_REFERENCE 152 b .Lloop_copy_args 1531: SKIP_SHORTY 154 155 // fill in the iframe 156.Lloop_copy_args: 157 NEXT_SHORTY r9 158 cmp r9, #0 159 beq .Lloopend_copy_args 160 161 cmp r9, #SHORTY_REFERENCE 162 moveq r10, #1 163 movne r10, #0 164 str r10, [r2, r12] 165 cmpne r9, #SHORTY_LAST_INT32 166 bhi 1f 167 // it is a 32bit int or reference 168 sub r9, r4, r3 169 cmp r9, #0 170 ldrne r9, [r3], #4 171 ldreq r9, [r7], #4 172 str r9, [r2] 173 add r2, r2, #FRAME_VREGISTER_SIZE 174 b .Lloop_copy_args 175 1761: sub r9, r9, #SHORTY_FIRST_FLOAT 177 cmp r9, #(SHORTY_NUM_FLOAT_TYPES - 1) 178 bls 2f 179 // it is a 64bit int 180 //align r3 181 add r3, r3, #7 182 bic r3, r3, #7 183 sub r9, r4, r3 184 cmp r9, #0 185 beq 3f 186 ldm r3!, {r9, r10} 187 stm r2, {r9, r10} 188 add r2, r2, #FRAME_VREGISTER_SIZE 189 b .Lloop_copy_args 190 1912: // it is a float 192 sub r9, r6, r5 193 cmp r9, #0 194 beq 3f 195 ldm r5!, {r9, r10} 196 stm r2, {r9, r10} 197 add r2, r2, #FRAME_VREGISTER_SIZE 198 b .Lloop_copy_args 199 2003: // read arg from the stack 201 add r7, r7, #7 202 bic r7, r7, #7 203 ldm r7!, {r9, r10} 204 stm r2, {r9, r10} 205 add r2, r2, #FRAME_VREGISTER_SIZE 206 b .Lloop_copy_args 207.Lloopend_copy_args: 208 // load method.shorty to r4 to survive the call 209 ldr r4, [lr, #METHOD_SHORTY_OFFSET] 210 211 // call InterpreterEntryPoint 212 mov r0, lr 213 mov r1, r8 214 blx InterpreterEntryPoint 215 216 // handle the result 217 // setup regs as follow 218 // r0 - iframe, r1 - *method.shorty, r2 - &iframe.acc_ 219 // r4, r5 - result 220 ldrb r1, [r4] 221 mov r0, r8 222 add r2, r0, #FRAME_ACC_OFFSET 223 and r1, r1, #0xF 224 225 cmp r1, #SHORTY_VOID 226 bne 1f 227 // void method 228 blx FreeFrame 229 b 4f 230 2311: cmp r1, #SHORTY_REFERENCE 232 cmpne r1, #SHORTY_LAST_INT32 233 bhi 2f 234 // it is a 32bit int of reference 235 ldr r4, [r2] 236 blx FreeFrame 237 mov r0, r4 238 b 4f 239 2402: ldm r2, {r4, r5} 241 sub r1, r1, #SHORTY_FIRST_FLOAT 242 cmp r1, #(SHORTY_NUM_FLOAT_TYPES - 1) 243 bls 3f 244 // it is a 64bit int 245 blx FreeFrame 246 mov r0, r4 247 mov r1, r5 248 b 4f 249 2503: // it is a float value 251 vmov.f64 d0, r4, r5 252 blx FreeFrame 253 2544: sub sp, fp, #(4 + 7 * 4 + 8 * 8) 255 vpop {d8 - d15} 256 CFI_RESTORE(d15) 257 CFI_RESTORE(d14) 258 CFI_RESTORE(d13) 259 CFI_RESTORE(d12) 260 CFI_RESTORE(d11) 261 CFI_RESTORE(d10) 262 CFI_RESTORE(d9) 263 CFI_RESTORE(d8) 264 265 pop {r4 - r10} 266 CFI_RESTORE(r10) 267 CFI_RESTORE(r9) 268 CFI_RESTORE(r8) 269 CFI_RESTORE(r7) 270 CFI_RESTORE(r6) 271 CFI_RESTORE(r5) 272 CFI_RESTORE(r4) 273 274 ldr fp, [sp, #4] 275 CFI_DEF_CFA(sp, 16) 276 CFI_RESTORE(fp) 277 278 ldr lr, [sp, #12] 279 CFI_RESTORE(lr) 280 add sp, sp, #16 // c2i 281 CFI_ADJUST_CFA_OFFSET(-16) 282 bx lr 283 CFI_ENDPROC 284