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 18.macro SAVE_CALLEE_GP_REGS base_reg, tmp_reg, offset 19 add \tmp_reg, \base_reg, #(\offset - CALLEE_REG0_OFFSET) 20 stm \tmp_reg, {r4-r10} 21 CFI_REL_OFFSET(r10, (\offset - CALLEE_REG0_OFFSET + 4*6)) 22 CFI_REL_OFFSET(r9, (\offset - CALLEE_REG0_OFFSET + 4*5)) 23 CFI_REL_OFFSET(r8, (\offset - CALLEE_REG0_OFFSET + 4*4)) 24 CFI_REL_OFFSET(r7, (\offset - CALLEE_REG0_OFFSET + 4*3)) 25 CFI_REL_OFFSET(r6, (\offset - CALLEE_REG0_OFFSET + 4*2)) 26 CFI_REL_OFFSET(r5, (\offset - CALLEE_REG0_OFFSET + 4*1)) 27 CFI_REL_OFFSET(r4, (\offset - CALLEE_REG0_OFFSET + 4*0)) 28.endm 29 30.macro RESTORE_CALLEE_GP_REGS base_reg, tmp_reg, offset 31 add \tmp_reg, \base_reg, #(\offset - CALLEE_REG0_OFFSET) 32 ldm \tmp_reg, {r4-r10} 33 CFI_RESTORE(r10) 34 CFI_RESTORE(r9) 35 CFI_RESTORE(r8) 36 CFI_RESTORE(r7) 37 CFI_RESTORE(r6) 38 CFI_RESTORE(r5) 39 CFI_RESTORE(r4) 40.endm 41 42.macro SAVE_CALLEE_FP_REGS base_reg, tmp_reg, offset 43 add \tmp_reg, \base_reg, #(\offset - CALLEE_VREG0_OFFSET) 44 vstm \tmp_reg, {d8-d15} 45 CFI_REL_OFFSET(d15, (\offset - CALLEE_VREG0_OFFSET + 4*14)) 46 CFI_REL_OFFSET(d14, (\offset - CALLEE_VREG0_OFFSET + 4*12)) 47 CFI_REL_OFFSET(d13, (\offset - CALLEE_VREG0_OFFSET + 4*10)) 48 CFI_REL_OFFSET(d12, (\offset - CALLEE_VREG0_OFFSET + 4*8)) 49 CFI_REL_OFFSET(d11, (\offset - CALLEE_VREG0_OFFSET + 4*6)) 50 CFI_REL_OFFSET(d10, (\offset - CALLEE_VREG0_OFFSET + 4*4)) 51 CFI_REL_OFFSET(d9, (\offset - CALLEE_VREG0_OFFSET + 4*2)) 52 CFI_REL_OFFSET(d8, (\offset - CALLEE_VREG0_OFFSET + 4*0)) 53.endm 54 55.macro RESTORE_CALLEE_FP_REGS base_reg, tmp_reg, offset 56 add \tmp_reg, \base_reg, #(\offset - CALLEE_VREG0_OFFSET) 57 vldm \tmp_reg, {d8-d15} 58 CFI_RESTORE(d15) 59 CFI_RESTORE(d14) 60 CFI_RESTORE(d13) 61 CFI_RESTORE(d12) 62 CFI_RESTORE(d11) 63 CFI_RESTORE(d10) 64 CFI_RESTORE(d9) 65 CFI_RESTORE(d8) 66.endm 67 68.macro SAVE_CALLER_GP_REGS fp_reg, tmp_reg, paramsnum 69 add \tmp_reg, \fp_reg, #-CALLER_REG0_OFFSET+4*4 70.ifeq \paramsnum 71 stmdb \tmp_reg, {r0-r3} 72.endif 73.ifeq \paramsnum-1 74 stmdb \tmp_reg, {r1-r3} 75.endif 76.ifeq \paramsnum-2 77 stmdb \tmp_reg, {r2-r3} 78.endif 79.ifeq \paramsnum-3 80 str r3, [\tmp_reg, #-4] 81.endif 82.endm 83 84.macro RESTORE_CALLER_GP_REGS fp_reg, tmp_reg, is_void 85 add \tmp_reg, \fp_reg, #-CALLER_REG0_OFFSET+4*4 86.if \is_void == 1 87 ldmdb \tmp_reg, {r0-r3} 88.else 89 ldmdb \tmp_reg, {r1-r3} 90.endif 91.endm 92 93.macro SAVE_CALLER_FP_REGS fp_reg, tmp_reg 94 add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET 95 vstm \tmp_reg, {d0-d7} 96.endm 97 98.macro RESTORE_CALLER_FP_REGS fp_reg, tmp_reg 99 add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET 100 vldm \tmp_reg, {d0-d7} 101.endm 102 103.macro CHECK_NATIVE_EXCEPTION is_void 104 ldr lr, [THREAD_REG, #MANAGED_THREAD_EXCEPTION_OFFSET] 105 cmp lr, #0 106 107 beq 3f 108 CFI_REMEMBER_STATE 109 110.if \is_void == 0 111 add lr, fp, #-CALLER_REG0_OFFSET 112 ldr r0, [lr] 113.endif 114 115 ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 4)] 116 CFI_RESTORE(lr) 117 118 add sp, sp, #BRIDGE_FRAME_SIZE 119 CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE) 120 121 b ThrowNativeExceptionBridge 122 CFI_RESTORE_STATE 123 1243: 125 ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 4)] 126 CFI_RESTORE(lr) 127 128 add sp, sp, #BRIDGE_FRAME_SIZE 129 CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE) 130.endm 131 132.macro BRIDGE_SELECTOR name, notcompiled_entry, compiled_entry 133.global \name 134.type \name, %function 135\name: 136 ldrb r12, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET] 137 tst r12, r12 138 bne \compiled_entry 139 b \notcompiled_entry 140.endm 141 142 143.macro RUNTIME_CALL_CHECKER name, entry 144.global \name 145.type \name, %function 146\name: 147 CFI_STARTPROC 148 CFI_DEF_CFA(sp, 0) 149 150 ldr r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET] 151 152 sub sp, sp, #8 153 CFI_ADJUST_CFA_OFFSET(8) 154 155 stm sp, {r12, lr} 156 CFI_REL_OFFSET(lr, -4) 157 158 mov r12, #0 159 str r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET] 160 161 bl \entry 162 163 ldm sp, {r12, lr} 164 CFI_RESTORE(lr) 165 166 add sp, sp, #8 167 CFI_ADJUST_CFA_OFFSET(-8) 168 169 str r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET] 170 171 bx lr 172 CFI_ENDPROC 173.endm 174 175.macro CALL_RUNTIME mode, entry, paramsnum, is_void 176 sub sp, sp, #BRIDGE_FRAME_SIZE 177 CFI_ADJUST_CFA_OFFSET(BRIDGE_FRAME_SIZE) 178 179 // Setup BoundaryFrame 180 str lr, [sp, #(BRIDGE_FRAME_SIZE - 1 * 4)] // Bridge frame, slot 1 = npc = LR (the StackMap stays just after the bridge call) 181 CFI_REL_OFFSET(lr, (BRIDGE_FRAME_SIZE - 1 * 4)) 182 str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] // ManagedThread.npc update 183 mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 184 str lr, [sp, #(BRIDGE_FRAME_SIZE - 2 * 4)] // Bridge frame, slot 2 = COMPILED_CODE_TO_INTERPRETER_BRIDGE flag 185 str fp, [sp, #(BRIDGE_FRAME_SIZE - 3 * 4)] // Bridge frame, slot 3 = parent frame pointer 186 CFI_REL_OFFSET(fp, (BRIDGE_FRAME_SIZE - 3 * 4)) 187 add lr, sp, #(BRIDGE_FRAME_SIZE - 3 * 4) 188 str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] // ManagedThread._frame = this boundary frame 189 190 SAVE_CALLEE_GP_REGS sp, lr, BRIDGE_FRAME_SIZE 191#ifndef PANDA_TARGET_ARM32_ABI_SOFT 192 // StackWalker requires callee-saved FP registers to be saved unconditionally in the runtime bridge 193 SAVE_CALLEE_FP_REGS sp, lr, BRIDGE_FRAME_SIZE 194#endif 195 196.if \mode != RUNTIME_MODE_SLOW_PATH 197 SAVE_CALLER_GP_REGS fp, lr, \paramsnum 198.endif 199 200#ifndef PANDA_TARGET_ARM32_ABI_SOFT 201 ldr r4, [fp, #(-CFRAME_FLAGS_SLOT * 4)] 202 tst r4, #CFRAME_HAS_FLOAT_REGS_FLAG_MASK 203 beq 1f 204 205 SAVE_CALLER_FP_REGS fp, lr 2061: 207#endif 208 209 bl \entry 210 211 // State restore 212 str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 213 214#ifndef PANDA_TARGET_ARM32_ABI_SOFT 215 tst r4, #CFRAME_HAS_FLOAT_REGS_FLAG_MASK 216 beq 2f 217 218 RESTORE_CALLEE_FP_REGS sp, lr, BRIDGE_FRAME_SIZE 219 RESTORE_CALLER_FP_REGS fp, lr 2202: 221#endif 222 223 RESTORE_CALLEE_GP_REGS sp, lr, BRIDGE_FRAME_SIZE 224 RESTORE_CALLER_GP_REGS fp, lr, \is_void 225 226 CHECK_NATIVE_EXCEPTION \is_void 227.endm 228 229.macro ENTRYPOINT name, entry, paramsnum, is_void 230.global \name 231.type \name, %function 232\name: 233 CFI_STARTPROC 234 CFI_DEF_CFA(sp, 0) 235 236 CALL_RUNTIME RUNTIME_MODE_DEFAULT, \entry, \paramsnum, \is_void 237 bx lr 238 CFI_ENDPROC 239.endm 240 241.macro ENTRYPOINT_SLOW_PATH name, entry, paramsnum, is_void 242.global \name 243.type \name, %function 244\name: 245 CFI_STARTPROC 246 CFI_DEF_CFA(sp, 0) 247 248 CALL_RUNTIME RUNTIME_MODE_SLOW_PATH, \entry, \paramsnum, \is_void 249 bx lr 250 CFI_ENDPROC 251.endm 252 253.macro MethodEntrypointStub name, entry, notcompiled 254.global \name 255.type \name, %function 256\name: 257 CFI_STARTPROC 258 CFI_DEF_CFA(sp, 0) 259 260 // If the caller is not a compiled method, we need to call \entry 261 // and return back after its execution 262 ldrb r1, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET] 263 tst r1, r1 264 beq .L\notcompiled 265 CFI_REMEMBER_STATE 266 267 str lr, [sp, #-4] 268 CFI_REL_OFFSET(lr, -4) 269 str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] 270 mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 271 str lr, [sp, #-8] 272 str fp, [sp, #-12] 273 CFI_REL_OFFSET(fp, -12) 274 sub lr, sp, #12 275 str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 276 sub sp, sp, #16 277 CFI_ADJUST_CFA_OFFSET(16) 278 279 push {r4 - r10} 280 CFI_ADJUST_CFA_OFFSET(28) 281 CFI_REL_OFFSET(r10, (6 * 4)) 282 CFI_REL_OFFSET(r9, (5 * 4)) 283 CFI_REL_OFFSET(r8, (4 * 4)) 284 CFI_REL_OFFSET(r7, (3 * 4)) 285 CFI_REL_OFFSET(r6, (2 * 4)) 286 CFI_REL_OFFSET(r5, (1 * 4)) 287 CFI_REL_OFFSET(r4, (0 * 4)) 288 289#ifndef PANDA_TARGET_ARM32_ABI_SOFT 290 vpush {d8 - d15} 291 CFI_ADJUST_CFA_OFFSET(64) 292 CFI_REL_OFFSET(d15, (14 * 4)) 293 CFI_REL_OFFSET(d14, (12 * 4)) 294 CFI_REL_OFFSET(d13, (10 * 4)) 295 CFI_REL_OFFSET(d12, (8 * 4)) 296 CFI_REL_OFFSET(d11, (6 * 4)) 297 CFI_REL_OFFSET(d10, (4 * 4)) 298 CFI_REL_OFFSET(d9, (2 * 4)) 299 CFI_REL_OFFSET(d8, (0 * 4)) 300#endif 301 302 // align to 8 303 sub sp, sp, #4 304 305 bl \entry 306 // we're not going to return back here 307 308.L\notcompiled: 309 CFI_RESTORE_STATE 310 CFI_DEF_CFA(sp, 0) 311 str lr, [sp, #-4] 312 CFI_REL_OFFSET(lr, -(1 * 4)) 313 sub sp, sp, #8 314 CFI_ADJUST_CFA_OFFSET(2 * 4) 315 bl \entry 316 add sp, sp, #8 317 CFI_ADJUST_CFA_OFFSET(-(2 * 4)) 318 ldr lr, [sp, #-4] 319 CFI_RESTORE(lr) 320 bx lr 321 CFI_ENDPROC 322.endm 323 324#include "entrypoints_gen.S" 325#include "entrypoints_bridge_asm_macro.inl" 326 327MethodEntrypointStub AbstractMethodStub AbstractMethodErrorEntrypoint ame_not_compiled 328 329MethodEntrypointStub DefaultConflictMethodStub IncompatibleClassChangeErrorForMethodConflictEntrypoint icce_not_compiled 330