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 "asm_defines.h" 17 18.macro SAVE_CALLEE_GP_REGS base_reg, offset 19 stp x27, x28, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*8)] 20 CFI_REL_OFFSET(x28, (\offset - CALLEE_REG0_OFFSET + 8*9)) 21 CFI_REL_OFFSET(x27, (\offset - CALLEE_REG0_OFFSET + 8*8)) 22 stp x25, x26, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*6)] 23 CFI_REL_OFFSET(x26, (\offset - CALLEE_REG0_OFFSET + 8*7)) 24 CFI_REL_OFFSET(x25, (\offset - CALLEE_REG0_OFFSET + 8*6)) 25 stp x23, x24, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*4)] 26 CFI_REL_OFFSET(x24, (\offset - CALLEE_REG0_OFFSET + 8*5)) 27 CFI_REL_OFFSET(x23, (\offset - CALLEE_REG0_OFFSET + 8*4)) 28 stp x21, x22, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*2)] 29 CFI_REL_OFFSET(x22, (\offset - CALLEE_REG0_OFFSET + 8*3)) 30 CFI_REL_OFFSET(x21, (\offset - CALLEE_REG0_OFFSET + 8*2)) 31 stp x19, x20, [\base_reg, #(\offset - CALLEE_REG0_OFFSET)] 32 CFI_REL_OFFSET(x20, (\offset - CALLEE_REG0_OFFSET + 8*1)) 33 CFI_REL_OFFSET(x19, (\offset - CALLEE_REG0_OFFSET + 8*0)) 34.endm 35 36.macro RESTORE_CALLEE_GP_REGS base_reg, offset 37 ldp x27, x28, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*8)] 38 CFI_RESTORE(x28) 39 CFI_RESTORE(x27) 40 ldp x25, x26, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*6)] 41 CFI_RESTORE(x26) 42 CFI_RESTORE(x25) 43 ldp x23, x24, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*4)] 44 CFI_RESTORE(x24) 45 CFI_RESTORE(x23) 46 ldp x21, x22, [\base_reg, #(\offset - CALLEE_REG0_OFFSET + 8*2)] 47 CFI_RESTORE(x22) 48 CFI_RESTORE(x21) 49 ldp x19, x20, [\base_reg, #(\offset - CALLEE_REG0_OFFSET)] 50 CFI_RESTORE(x20) 51 CFI_RESTORE(x19) 52.endm 53 54.macro SAVE_CALLEE_FP_REGS base_reg, offset 55 stp d14, d15, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET + 8*6)] 56 CFI_REL_OFFSET(d15, (\offset - CALLEE_VREG0_OFFSET + 8*7)) 57 CFI_REL_OFFSET(d14, (\offset - CALLEE_VREG0_OFFSET + 8*6)) 58 stp d12, d13, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET + 8*4)] 59 CFI_REL_OFFSET(d13, (\offset - CALLEE_VREG0_OFFSET + 8*5)) 60 CFI_REL_OFFSET(d12, (\offset - CALLEE_VREG0_OFFSET + 8*4)) 61 stp d10, d11, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET + 8*2)] 62 CFI_REL_OFFSET(d11, (\offset - CALLEE_VREG0_OFFSET + 8*3)) 63 CFI_REL_OFFSET(d10, (\offset - CALLEE_VREG0_OFFSET + 8*2)) 64 stp d8, d9, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET)] 65 CFI_REL_OFFSET(d9, (\offset - CALLEE_VREG0_OFFSET + 8*1)) 66 CFI_REL_OFFSET(d8, (\offset - CALLEE_VREG0_OFFSET + 8*0)) 67.endm 68 69.macro RESTORE_CALLEE_FP_REGS base_reg, offset 70 ldp d14, d15, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET + 8*6)] 71 CFI_RESTORE(d15) 72 CFI_RESTORE(d14) 73 ldp d12, d13, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET + 8*4)] 74 CFI_RESTORE(d13) 75 CFI_RESTORE(d12) 76 ldp d10, d11, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET + 8*2)] 77 CFI_RESTORE(d11) 78 CFI_RESTORE(d10) 79 ldp d8, d9, [\base_reg, #(\offset - CALLEE_VREG0_OFFSET)] 80 CFI_RESTORE(d9) 81 CFI_RESTORE(d8) 82.endm 83 84.macro SAVE_CALLER_GP_REGS fp_reg, paramsnum, mode 85.if \mode != RUNTIME_MODE_STUB 86 // parameter holding registers are saved by the caller function 87.ifeq \paramsnum 88 stp x0, x1, [\fp_reg, #-CALLER_REG0_OFFSET+8*0] 89.endif 90.ifle \paramsnum-2 91 stp x2, x3, [\fp_reg, #-CALLER_REG0_OFFSET+8*2] 92.endif 93.ifle \paramsnum-4 94 stp x4, x5, [\fp_reg, #-CALLER_REG0_OFFSET+8*4] 95.endif 96.endif // \mode != RUNTIME_MODE_STUB 97 98 // Save caller saved regs 99 // first registers are stored by user of this macro or caller which uses them for arguments 100 stp x6, x7, [\fp_reg, #-CALLER_REG0_OFFSET+8*6] 101 stp x8, x9, [\fp_reg, #-CALLER_REG0_OFFSET+8*8] 102 stp x10, x11, [\fp_reg, #-CALLER_REG0_OFFSET+8*10] 103 stp x12, x13, [\fp_reg, #-CALLER_REG0_OFFSET+8*12] 104 stp x14, x15, [\fp_reg, #-CALLER_REG0_OFFSET+8*14] 105 stp x16, x17, [\fp_reg, #-CALLER_REG0_OFFSET+8*16] 106 str x18, [\fp_reg, #-CALLER_REG0_OFFSET+8*18] 107.endm 108 109.macro RESTORE_CALLER_GP_REGS fp_reg, tmp_reg, is_void 110.if \is_void == 1 111 ldp x0, x1, [\fp_reg, #-CALLER_REG0_OFFSET+8*0] 112.else 113 // do not load x0 here as it can overwrite the result value 114 add \tmp_reg, \fp_reg, #-CALLER_REG0_OFFSET 115 ldr x1, [\tmp_reg, #8*1] 116.endif 117 ldp x2, x3, [\fp_reg, #-CALLER_REG0_OFFSET+8*2] 118 ldp x4, x5, [\fp_reg, #-CALLER_REG0_OFFSET+8*4] 119 ldp x6, x7, [\fp_reg, #-CALLER_REG0_OFFSET+8*6] 120 ldp x8, x9, [\fp_reg, #-CALLER_REG0_OFFSET+8*8] 121 ldp x10, x11, [\fp_reg, #-CALLER_REG0_OFFSET+8*10] 122 ldp x12, x13, [\fp_reg, #-CALLER_REG0_OFFSET+8*12] 123 ldp x14, x15, [\fp_reg, #-CALLER_REG0_OFFSET+8*14] 124 ldp x16, x17, [\fp_reg, #-CALLER_REG0_OFFSET+8*16] 125 ldr x18, [\fp_reg, #-CALLER_REG0_OFFSET+8*18] 126.endm 127 128.macro SAVE_CALLER_FP_REGS fp_reg, tmp_reg 129 add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET 130 stp d0, d1, [\tmp_reg] 131 stp d2, d3, [\tmp_reg, #8*2] 132 stp d4, d5, [\tmp_reg, #8*4] 133 stp d6, d7, [\tmp_reg, #8*6] 134 stp d16, d17, [\tmp_reg, #8*8] 135 stp d18, d19, [\tmp_reg, #8*10] 136 stp d20, d21, [\tmp_reg, #8*12] 137 stp d22, d23, [\tmp_reg, #8*14] 138 stp d24, d25, [\tmp_reg, #8*16] 139 stp d26, d27, [\tmp_reg, #8*18] 140 stp d28, d29, [\tmp_reg, #8*20] 141 stp d30, d31, [\tmp_reg, #8*22] 142.endm 143 144.macro RESTORE_CALLER_FP_REGS fp_reg, tmp_reg 145 add \tmp_reg, \fp_reg, #-CALLER_VREG0_OFFSET 146 ldp d0, d1, [\tmp_reg] 147 ldp d2, d3, [\tmp_reg, #8*2] 148 ldp d4, d5, [\tmp_reg, #8*4] 149 ldp d6, d7, [\tmp_reg, #8*6] 150 ldp d16, d17, [\tmp_reg, #8*8] 151 ldp d18, d19, [\tmp_reg, #8*10] 152 ldp d20, d21, [\tmp_reg, #8*12] 153 ldp d22, d23, [\tmp_reg, #8*14] 154 ldp d24, d25, [\tmp_reg, #8*16] 155 ldp d26, d27, [\tmp_reg, #8*18] 156 ldp d28, d29, [\tmp_reg, #8*20] 157 ldp d30, d31, [\tmp_reg, #8*22] 158.endm 159 160.macro CHECK_NATIVE_EXCEPTION is_void 161 ldr lr, [THREAD_REG, #MANAGED_THREAD_EXCEPTION_OFFSET] 162 cmp lr, 0 163 164 beq 1f 165 CFI_REMEMBER_STATE 166 167.if \is_void == 0 168 add lr, fp, #-CALLER_REG0_OFFSET 169 ldr x0, [lr] 170.endif 171 172 ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 8)] 173 CFI_RESTORE(lr) 174 175 add sp, sp, #BRIDGE_FRAME_SIZE 176 CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE) 177 178 b ThrowNativeExceptionBridge 179 CFI_RESTORE_STATE 180 1811: 182 ldr lr, [sp, #(BRIDGE_FRAME_SIZE - 8)] 183 CFI_RESTORE(lr) 184 185 add sp, sp, #BRIDGE_FRAME_SIZE 186 CFI_ADJUST_CFA_OFFSET(-BRIDGE_FRAME_SIZE) 187.endm 188 189.macro CALL_RUNTIME mode, entry, paramsnum, is_void 190 sub sp, sp, #BRIDGE_FRAME_SIZE 191 CFI_ADJUST_CFA_OFFSET(BRIDGE_FRAME_SIZE) 192 193 // BoundaryFrame setup 194 str lr, [sp, #(BRIDGE_FRAME_SIZE - 8)] // Bridge frame, slot 1 = npc = LR (the StackMap is just after the bridge call) 195 CFI_REL_OFFSET(lr, (BRIDGE_FRAME_SIZE - 1 * 8)) 196 str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET] // ManagedThread.npc update 197 mov lr, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 198 str lr, [sp, #(BRIDGE_FRAME_SIZE - 16)] // Bridge frame, slot 2 = COMPILED_CODE_TO_INTERPRETER 199 str fp, [sp, #(BRIDGE_FRAME_SIZE - 24)] // Bridge frame, slot 3 = parent frame pointer 200 CFI_REL_OFFSET(fp, (BRIDGE_FRAME_SIZE - 3 * 8)) 201 add lr, sp, #(BRIDGE_FRAME_SIZE - 24) 202 str lr, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] // ManagedThread._frame = this boundary frame 203 204 SAVE_CALLEE_GP_REGS sp, BRIDGE_FRAME_SIZE 205 // StackWalker requires callee-saved FP registers to be saved unconditionally in the runtime bridge 206 SAVE_CALLEE_FP_REGS sp, BRIDGE_FRAME_SIZE 207 208.if \mode != RUNTIME_MODE_SLOW_PATH 209 SAVE_CALLER_GP_REGS fp, \paramsnum, \mode 210.endif 211 212 ldr x19, [fp, #(-CFRAME_FLAGS_SLOT * 8)] 213 tbz x19, #CFRAME_HAS_FLOAT_REGS_FLAG_BIT, 2f 214 215 SAVE_CALLER_FP_REGS fp, lr 216 2172: 218 // The call 219 bl \entry 220 221 // Restore previous state 222 str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET] 223 224 tbz x19, #CFRAME_HAS_FLOAT_REGS_FLAG_BIT, 3f 225 226 RESTORE_CALLEE_FP_REGS sp, BRIDGE_FRAME_SIZE 227 RESTORE_CALLER_FP_REGS fp, lr 228 2293: 230 RESTORE_CALLEE_GP_REGS sp, BRIDGE_FRAME_SIZE 231 RESTORE_CALLER_GP_REGS fp, lr, \is_void 232 233 CHECK_NATIVE_EXCEPTION \is_void 234.endm 235