1/** 2 * Copyright (c) 2021-2024 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, ret_type 85 add \tmp_reg, \fp_reg, #-CALLER_REG0_OFFSET+4*4 86#ifdef PANDA_TARGET_ARM32_ABI_HARD 87.ifnc \ret_type,INTEGER 88#else 89.ifc \ret_type,VOID 90#endif 91 ldmdb \tmp_reg, {r0-r3} 92.else 93 // r0-r1 is 64-bit return value 94 ldmdb \tmp_reg, {r2-r3} 95.endif 96.endm 97 98.macro SAVE_CALLER_FP_REGS fp_reg, tmp_reg 99 add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET 100 vstm \tmp_reg, {d0-d7} 101.endm 102 103.macro RESTORE_CALLER_FP_REGS fp_reg, tmp_reg, ret_type 104 add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET+8*8 105#ifdef PANDA_TARGET_ARM32_ABI_HARD 106.ifnc \ret_type,FLOAT 107 vldmdb \tmp_reg!, {d0-d7} 108.else 109 vldmdb \tmp_reg!, {d1-d7} 110.endif 111#else 112 vldmdb \tmp_reg!, {d0-d7} 113#endif 114.endm 115 116.macro CHECK_NATIVE_EXCEPTION ret_type 117 ldr lr, [THREAD_REG, #MANAGED_THREAD_EXCEPTION_OFFSET] 118 cmp lr, #0 119 120 beq 3f 121 CFI_REMEMBER_STATE 122 123#ifdef PANDA_TARGET_ARM32_ABI_HARD 124.ifc \ret_type,INTEGER 125#else 126.ifnc \ret_type,VOID 127#endif 128 add lr, fp, #-CALLER_REG0_OFFSET 129 ldm lr, {r0-r1} 130.endif 131#ifdef PANDA_TARGET_ARM32_ABI_HARD 132.ifc \ret_type,FLOAT 133 add lr, fp, #-CALLER_VREG0_OFFSET 134 vldr d0, [lr] 135.endif 136#endif 137 138 ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 4)] 139 CFI_RESTORE(lr) 140 141 add sp, sp, #BRIDGE_FRAME_SIZE 142 CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE) 143 144 b ThrowNativeExceptionBridge 145 CFI_RESTORE_STATE 146 1473: 148 ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 4)] 149 CFI_RESTORE(lr) 150 151 add sp, sp, #BRIDGE_FRAME_SIZE 152 CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE) 153.endm 154 155.macro BRIDGE_SELECTOR name, notcompiled_entry, compiled_entry 156.global \name 157.type \name, %function 158\name: 159 ldrb r12, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET] 160 tst r12, r12 161 bne \compiled_entry 162 b \notcompiled_entry 163.endm 164 165 166.macro RUNTIME_CALL_CHECKER name, entry 167.global \name 168.type \name, %function 169\name: 170 CFI_STARTPROC 171 CFI_DEF_CFA(sp, 0) 172 173 ldr r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET] 174 175 sub sp, sp, #8 176 CFI_ADJUST_CFA_OFFSET(8) 177 178 stm sp, {r12, lr} 179 CFI_REL_OFFSET(lr, -4) 180 181 mov r12, #0 182 str r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET] 183 184 bl \entry 185 186 ldm sp, {r12, lr} 187 CFI_RESTORE(lr) 188 189 add sp, sp, #8 190 CFI_ADJUST_CFA_OFFSET(-8) 191 192 str r12, [THREAD_REG, #MANAGED_THREAD_RUNTIME_CALL_ENABLED_OFFSET] 193 194 bx lr 195 CFI_ENDPROC 196.endm 197 198.macro CALL_RUNTIME mode, entry, paramsnum, ret_type 199 sub sp, sp, #BRIDGE_FRAME_SIZE 200 CFI_ADJUST_CFA_OFFSET(BRIDGE_FRAME_SIZE) 201 202 // Setup BoundaryFrame 203 str lr, [sp, #(BRIDGE_FRAME_SIZE - 1 * 4)] // Bridge frame, slot 1 = npc = LR (the StackMap stays just after the bridge call) 204 CFI_REL_OFFSET(lr, (BRIDGE_FRAME_SIZE - 1 * 4)) 205 str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] // ManagedThread.npc update 206 mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 207 str lr, [sp, #(BRIDGE_FRAME_SIZE - 2 * 4)] // Bridge frame, slot 2 = COMPILED_CODE_TO_INTERPRETER_BRIDGE flag 208 str fp, [sp, #(BRIDGE_FRAME_SIZE - 3 * 4)] // Bridge frame, slot 3 = parent frame pointer 209 CFI_REL_OFFSET(fp, (BRIDGE_FRAME_SIZE - 3 * 4)) 210 add lr, sp, #(BRIDGE_FRAME_SIZE - 3 * 4) 211 str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] // ManagedThread._frame = this boundary frame 212 213 SAVE_CALLEE_GP_REGS sp, lr, BRIDGE_FRAME_SIZE 214#ifndef PANDA_TARGET_ARM32_ABI_SOFT 215 // StackWalker requires callee-saved FP registers to be saved unconditionally in the runtime bridge 216 SAVE_CALLEE_FP_REGS sp, lr, BRIDGE_FRAME_SIZE 217#endif 218 219.if \mode != RUNTIME_MODE_SLOW_PATH 220 SAVE_CALLER_GP_REGS fp, lr, \paramsnum 221.endif 222 223#ifndef PANDA_TARGET_ARM32_ABI_SOFT 224 ldr r4, [fp, #(-CFRAME_FLAGS_SLOT * 4)] 225 tst r4, #CFRAME_HAS_FLOAT_REGS_FLAG_MASK 226 beq 1f 227 228 SAVE_CALLER_FP_REGS fp, lr 2291: 230#endif 231 232 bl \entry 233 234 // State restore 235 str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 236 237#ifndef PANDA_TARGET_ARM32_ABI_SOFT 238 tst r4, #CFRAME_HAS_FLOAT_REGS_FLAG_MASK 239 beq 2f 240 241 RESTORE_CALLEE_FP_REGS sp, lr, BRIDGE_FRAME_SIZE 242 RESTORE_CALLER_FP_REGS fp, lr, \ret_type 2432: 244#endif 245 246 RESTORE_CALLEE_GP_REGS sp, lr, BRIDGE_FRAME_SIZE 247 RESTORE_CALLER_GP_REGS fp, lr, \ret_type 248 249 CHECK_NATIVE_EXCEPTION \ret_type 250.endm 251 252.macro ENTRYPOINT name, entry, paramsnum, ret_type 253.global \name 254.type \name, %function 255\name: 256 CFI_STARTPROC 257 CFI_DEF_CFA(sp, 0) 258 259 CALL_RUNTIME RUNTIME_MODE_DEFAULT, \entry, \paramsnum, \ret_type 260 bx lr 261 CFI_ENDPROC 262.endm 263 264// Unused for 32-bit arm 265.macro ENTRYPOINT_ODD_SAVED name, entry, paramsnum, ret_type 266 ENTRYPOINT \name, \entry, \paramsnum, \ret_type 267.endm 268 269.macro ENTRYPOINT_SLOW_PATH name, entry, paramsnum, ret_type 270.global \name 271.type \name, %function 272\name: 273 CFI_STARTPROC 274 CFI_DEF_CFA(sp, 0) 275 276 CALL_RUNTIME RUNTIME_MODE_SLOW_PATH, \entry, \paramsnum, \ret_type 277 bx lr 278 CFI_ENDPROC 279.endm 280 281.macro MethodEntrypointStub name, entry, notcompiled 282.global \name 283.type \name, %function 284\name: 285 CFI_STARTPROC 286 CFI_DEF_CFA(sp, 0) 287 288 // If the caller is not a compiled method, we need to call \entry 289 // and return back after its execution 290 ldrb r1, [THREAD_REG, #MANAGED_THREAD_FRAME_KIND_OFFSET] 291 tst r1, r1 292 beq .L\notcompiled 293 CFI_REMEMBER_STATE 294 295 str lr, [sp, #-4] 296 CFI_REL_OFFSET(lr, -4) 297 str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] 298 mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 299 str lr, [sp, #-8] 300 str fp, [sp, #-12] 301 CFI_REL_OFFSET(fp, -12) 302 sub lr, sp, #12 303 str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 304 sub sp, sp, #16 305 CFI_ADJUST_CFA_OFFSET(16) 306 307 push {r4 - r10} 308 CFI_ADJUST_CFA_OFFSET(28) 309 CFI_REL_OFFSET(r10, (6 * 4)) 310 CFI_REL_OFFSET(r9, (5 * 4)) 311 CFI_REL_OFFSET(r8, (4 * 4)) 312 CFI_REL_OFFSET(r7, (3 * 4)) 313 CFI_REL_OFFSET(r6, (2 * 4)) 314 CFI_REL_OFFSET(r5, (1 * 4)) 315 CFI_REL_OFFSET(r4, (0 * 4)) 316 317#ifndef PANDA_TARGET_ARM32_ABI_SOFT 318 vpush {d8 - d15} 319 CFI_ADJUST_CFA_OFFSET(64) 320 CFI_REL_OFFSET(d15, (14 * 4)) 321 CFI_REL_OFFSET(d14, (12 * 4)) 322 CFI_REL_OFFSET(d13, (10 * 4)) 323 CFI_REL_OFFSET(d12, (8 * 4)) 324 CFI_REL_OFFSET(d11, (6 * 4)) 325 CFI_REL_OFFSET(d10, (4 * 4)) 326 CFI_REL_OFFSET(d9, (2 * 4)) 327 CFI_REL_OFFSET(d8, (0 * 4)) 328#endif 329 330 // align to 8 331 sub sp, sp, #4 332 333 bl \entry 334 // we're not going to return back here 335 336.L\notcompiled: 337 CFI_RESTORE_STATE 338 CFI_DEF_CFA(sp, 0) 339 str lr, [sp, #-4] 340 CFI_REL_OFFSET(lr, -(1 * 4)) 341 sub sp, sp, #8 342 CFI_ADJUST_CFA_OFFSET(2 * 4) 343 bl \entry 344 add sp, sp, #8 345 CFI_ADJUST_CFA_OFFSET(-(2 * 4)) 346 ldr lr, [sp, #-4] 347 CFI_RESTORE(lr) 348 bx lr 349 CFI_ENDPROC 350.endm 351 352#include "entrypoints_gen.S" 353#include "entrypoints_bridge_asm_macro.inl" 354 355MethodEntrypointStub AbstractMethodStub AbstractMethodErrorEntrypoint ame_not_compiled 356 357MethodEntrypointStub DefaultConflictMethodStub IncompatibleClassChangeErrorForMethodConflictEntrypoint icce_not_compiled 358