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