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.extern InvokeInterpreter 19 20.global DeoptimizeAfterCFrame 21.type DeoptimizeAfterCFrame, %function 22DeoptimizeAfterCFrame: 23 CFI_STARTPROC 24 25 // Parameters: 26 // r0 - thread 27 // r1 - pc of the entry 28 // r2 - pointer to interpreter Frame 29 // r3 - pointer to cframe origin 30 // r4(slot0) - last restored interpreter Frame 31 32 // Morph CFrame into C2I bridge frame 33 // FROM TO 34 // lr lr 35 // fp <---- COMPILED_CODE_TO_INTERPRETER_BRIDGE 36 // method fp <---- 37 38 CFI_DEF_CFA(r3, (2 * 4)) 39 CFI_REL_OFFSET(lr, 4) 40 CFI_REL_OFFSET(fp, 0) 41 CFI_REL_OFFSET(THREAD_REG, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 4)) 42 CFI_REL_OFFSET(r9, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 4)) 43 CFI_REL_OFFSET(r8, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 4)) 44 CFI_REL_OFFSET(r7, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 4)) 45 CFI_REL_OFFSET(r6, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 4)) 46 CFI_REL_OFFSET(r5, -((CFRAME_CALLEE_REGS_START_SLOT + 5) * 4)) 47 CFI_REL_OFFSET(r4, -((CFRAME_CALLEE_REGS_START_SLOT + 6) * 4)) 48 ldr r4, [sp] 49 50 sub sp, r3, #((CFRAME_CALLEE_REGS_START_SLOT * 4) + CALLEE_SAVED_SIZE) 51 52 ldr r5, [r3], #-4 53 CFI_ADJUST_CFA_OFFSET(4) 54 mov r6, #COMPILED_CODE_TO_INTERPRETER_BRIDGE 55 stm r3, {r5, r6} 56 CFI_REL_OFFSET(fp, 0) 57 58 mov fp, r3 59 CFI_DEF_CFA_REGISTER(fp) 60 61 // Set IFrame's prev_frame to this C2I bridge frame 62 str r3, [r4, #FRAME_PREV_FRAME_OFFSET] 63 64 BOUNDARY_FRAME_SLOT = ((CFRAME_HEADER_SIZE - 3) + 1) 65 66 // Copy callee saved registers from cframe into boundary frame. 67 sub r12, r3, #((CFRAME_CALLEE_REGS_START_SLOT - 1) * 4 - 4) 68 sub r11, r3, #((BOUNDARY_FRAME_SLOT - 1) * 4) 69 70 // Scalar 71 ldr r10, [r12, #-4]! 72 str r10, [r11, #-4]! 73 CFI_REL_OFFSET(r10, -((BOUNDARY_FRAME_SLOT + 0) * 4)) 74 ldr r10, [r12, #-4]! 75 str r10, [r11, #-4]! 76 CFI_REL_OFFSET(r9, -((BOUNDARY_FRAME_SLOT + 1) * 4)) 77 ldr r10, [r12, #-4]! 78 str r10, [r11, #-4]! 79 CFI_REL_OFFSET(r8, -((BOUNDARY_FRAME_SLOT + 2) * 4)) 80 ldr r10, [r12, #-4]! 81 str r10, [r11, #-4]! 82 CFI_REL_OFFSET(r7, -((BOUNDARY_FRAME_SLOT + 3) * 4)) 83 ldr r10, [r12, #-4]! 84 str r10, [r11, #-4]! 85 CFI_REL_OFFSET(r6, -((BOUNDARY_FRAME_SLOT + 4) * 4)) 86 ldr r10, [r12, #-4]! 87 str r10, [r11, #-4]! 88 CFI_REL_OFFSET(r5, -((BOUNDARY_FRAME_SLOT + 5) * 4)) 89 ldr r10, [r12, #-4]! 90 str r10, [r11, #-4]! 91 CFI_REL_OFFSET(r4, -((BOUNDARY_FRAME_SLOT + 6) * 4)) 92 // Vector (use 32-bit) 93 ldr r10, [r12, #-4]! 94 str r10, [r11, #-4]! 95 CFI_REL_OFFSET(s31, -((BOUNDARY_FRAME_SLOT + 7) * 4)) 96 ldr r10, [r12, #-4]! 97 str r10, [r11, #-4]! 98 CFI_REL_OFFSET(s30, -((BOUNDARY_FRAME_SLOT + 8) * 4)) 99 ldr r10, [r12, #-4]! 100 str r10, [r11, #-4]! 101 CFI_REL_OFFSET(s29, -((BOUNDARY_FRAME_SLOT + 9) * 4)) 102 ldr r10, [r12, #-4]! 103 str r10, [r11, #-4]! 104 CFI_REL_OFFSET(s28, -((BOUNDARY_FRAME_SLOT + 10) * 4)) 105 ldr r10, [r12, #-4]! 106 str r10, [r11, #-4]! 107 CFI_REL_OFFSET(s27, -((BOUNDARY_FRAME_SLOT + 11) * 4)) 108 ldr r10, [r12, #-4]! 109 str r10, [r11, #-4]! 110 CFI_REL_OFFSET(s26, -((BOUNDARY_FRAME_SLOT + 12) * 4)) 111 ldr r10, [r12, #-4]! 112 str r10, [r11, #-4]! 113 CFI_REL_OFFSET(s25, -((BOUNDARY_FRAME_SLOT + 13) * 4)) 114 ldr r10, [r12, #-4]! 115 str r10, [r11, #-4]! 116 CFI_REL_OFFSET(s24, -((BOUNDARY_FRAME_SLOT + 14) * 4)) 117 ldr r10, [r12, #-4]! 118 str r10, [r11, #-4]! 119 CFI_REL_OFFSET(s23, -((BOUNDARY_FRAME_SLOT + 15) * 4)) 120 ldr r10, [r12, #-4]! 121 str r10, [r11, #-4]! 122 CFI_REL_OFFSET(s22, -((BOUNDARY_FRAME_SLOT + 16) * 4)) 123 ldr r10, [r12, #-4]! 124 str r10, [r11, #-4]! 125 CFI_REL_OFFSET(s21, -((BOUNDARY_FRAME_SLOT + 17) * 4)) 126 ldr r10, [r12, #-4]! 127 str r10, [r11, #-4]! 128 CFI_REL_OFFSET(s20, -((BOUNDARY_FRAME_SLOT + 18) * 4)) 129 ldr r10, [r12, #-4]! 130 str r10, [r11, #-4]! 131 CFI_REL_OFFSET(s19, -((BOUNDARY_FRAME_SLOT + 19) * 4)) 132 ldr r10, [r12, #-4]! 133 str r10, [r11, #-4]! 134 CFI_REL_OFFSET(s18, -((BOUNDARY_FRAME_SLOT + 20) * 4)) 135 ldr r10, [r12, #-4]! 136 str r10, [r11, #-4]! 137 CFI_REL_OFFSET(s17, -((BOUNDARY_FRAME_SLOT + 21) * 4)) 138 ldr r10, [r12, #-4]! 139 str r10, [r11, #-4]! 140 CFI_REL_OFFSET(s16, -((BOUNDARY_FRAME_SLOT + 22) * 4)) 141 // Save used registers 142 str r3, [sp, #-4]! 143 str r2, [sp, #-4]! 144 str r1, [sp, #-4]! 145 str r0, [sp, #-4]! 146 mov r3, r4 147 148 // Arguments are already lay in registers, because signature of DeoptimizeAfterCFrame is similar to InvokeInterpreter 149 blx InvokeInterpreter 150 // r0, r1 - return values 151 152 // Restore used registers, but not r0, r1 which holds result of the invoked method and should be survive to the end 153 // So we use r4 instead of r0 for restoring THREAD_REG 154 ldr r4, [sp], #4 155 add sp, sp, #4 156 ldrd r2, r3, [sp], #8 157 158 // Restore stack pointer so that it points to COMPILED_CODE_TO_INTERPRETER_BRIDGE 159 sub sp, r3, #4 160 161 // Restore callee saved registers 162 sub r3, r3, #((BOUNDARY_FRAME_SLOT - 1) * 4) 163 164 ldr r10, [r3, #-4]! 165 ldrd r8, r9, [r3, #-8]! 166 CFI_RESTORE(r9) 167 CFI_RESTORE(r8) 168 ldrd r6, r7, [r3, #-8]! 169 CFI_RESTORE(r7) 170 CFI_RESTORE(r6) 171 // THREAD_REG is r10, but we can't remove `ldr r10, [r3, #-4]!` because we can change number of the THREAD_REG 172 // !NOTE fix this code if THREAD_REG will be change to r4 or r5 173 mov THREAD_REG, r4 174 CFI_RESTORE(THREAD_REG) 175 176 ldrd r4, r5, [r3, #-8]! 177 CFI_RESTORE(r5) 178 CFI_RESTORE(r4) 179 180#ifndef PANDA_TARGET_ARM32_ABI_SOFT 181 vldr d15, [r3, #-8] 182 CFI_RESTORE(d15) 183 vldr d14, [r3, #-16] 184 CFI_RESTORE(d14) 185 vldr d13, [r3, #-24] 186 CFI_RESTORE(d13) 187 vldr d12, [r3, #-32] 188 CFI_RESTORE(d12) 189 vldr d11, [r3, #-40] 190 CFI_RESTORE(d11) 191 vldr d10, [r3, #-48] 192 CFI_RESTORE(d10) 193 vldr d9, [r3, #-56] 194 CFI_RESTORE(d9) 195 vldr d8, [r3, #-64] 196 CFI_RESTORE(d8) 197 198 vmov.f64 d0, r0, r1 199#endif 200 201 ldr fp, [sp, #4] 202 CFI_RESTORE(fp) 203 CFI_DEF_CFA(sp, (4 * 4)) 204 ldr lr, [sp, #12] 205 CFI_RESTORE(lr) 206 add sp, sp, #16 207 CFI_ADJUST_CFA_OFFSET(-(4 * 4)) 208 bx lr 209 CFI_ENDPROC 210 211.global DeoptimizeAfterIFrame 212.type DeoptimizeAfterIFrame, %function 213DeoptimizeAfterIFrame: 214 CFI_STARTPROC 215 216 // Parameters: 217 // r0 - thread 218 // r1 - pc of the entry 219 // r2 - pointer to interpreter Frame 220 // r3 - pointer to cframe origin 221 // r4(slot0) - last restored interpreter Frame 222 // load num_inlined_methods from stack 223 224 CFI_DEF_CFA(r3, (2 * 4)) 225 CFI_REL_OFFSET(lr, 4) 226 CFI_REL_OFFSET(fp, 0) 227 CFI_REL_OFFSET(r10, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 4)) 228 CFI_REL_OFFSET(r9, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 4)) 229 CFI_REL_OFFSET(r8, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 4)) 230 CFI_REL_OFFSET(r7, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 4)) 231 CFI_REL_OFFSET(r6, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 4)) 232 CFI_REL_OFFSET(r5, -((CFRAME_CALLEE_REGS_START_SLOT + 5) * 4)) 233 CFI_REL_OFFSET(r4, -((CFRAME_CALLEE_REGS_START_SLOT + 6) * 4)) 234 235 ldr r4, [sp] 236 237 // Restore fp by pointer to the I2C boundary frame 238 // Restore return address, so after interperter finish its work it returns to the I2C bridge 239 mov fp, r3 240 CFI_DEF_CFA_REGISTER(fp) 241 242 // Restore stack pointer to the beginning of the cframe 243 mov sp, fp 244 245 // save num_inlined_methods to new stack 246 str r4, [sp, #-4]! 247 248 // Restore callee saved registers 249 sub r3, r3, #((CFRAME_CALLEE_REGS_START_SLOT * 4) - 4) 250 ldr r10, [r3, #-4]! 251 CFI_RESTORE(r10) 252 ldrd r8, r9, [r3, #-8]! 253 CFI_RESTORE(r9) 254 CFI_RESTORE(r8) 255 ldrd r6, r7, [r3, #-8]! 256 CFI_RESTORE(r7) 257 CFI_RESTORE(r6) 258 ldrd r4, r5, [r3, #-8]! 259 CFI_RESTORE(r5) 260 CFI_RESTORE(r4) 261 262#ifndef PANDA_TARGET_ARM32_ABI_SOFT 263 vldr d15, [r3, #-8] 264 CFI_RESTORE(d15) 265 vldr d14, [r3, #-16] 266 CFI_RESTORE(d14) 267 vldr d13, [r3, #-24] 268 CFI_RESTORE(d13) 269 vldr d12, [r3, #-32] 270 CFI_RESTORE(d12) 271 vldr d11, [r3, #-40] 272 CFI_RESTORE(d11) 273 vldr d10, [r3, #-48] 274 CFI_RESTORE(d10) 275 vldr d9, [r3, #-56] 276 CFI_RESTORE(d9) 277 vldr d8, [r3, #-64] 278 CFI_RESTORE(d8) 279#endif 280 281 // load num_inlined_methods from new stack 282 ldr r3, [sp], #4 283 284 bl InvokeInterpreter 285 286#ifndef PANDA_TARGET_ARM32_ABI_SOFT 287 // InvokeInterpreter returns int64 value, but result can be double, so we copy value to vector register 288 vmov.f64 d0, r0, r1 289#endif 290 291 pop {fp, lr} 292 CFI_RESTORE(lr) 293 CFI_RESTORE(fp) 294 CFI_DEF_CFA(sp, 0) 295 bx lr 296 CFI_ENDPROC 297 298.global DropCompiledFrameAndReturn 299.type DropCompiledFrameAndReturn, %function 300DropCompiledFrameAndReturn: 301 CFI_STARTPROC 302 303 // r0 - pointer to cframe origin 304 CFI_DEF_CFA(r0, (2 * 4)) 305 CFI_REL_OFFSET(lr, 4) 306 CFI_REL_OFFSET(fp, 0) 307 CFI_REL_OFFSET(r10, -((CFRAME_CALLEE_REGS_START_SLOT + 0) * 4)) 308 CFI_REL_OFFSET(r9, -((CFRAME_CALLEE_REGS_START_SLOT + 1) * 4)) 309 CFI_REL_OFFSET(r8, -((CFRAME_CALLEE_REGS_START_SLOT + 2) * 4)) 310 CFI_REL_OFFSET(r7, -((CFRAME_CALLEE_REGS_START_SLOT + 3) * 4)) 311 CFI_REL_OFFSET(r6, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 4)) 312 CFI_REL_OFFSET(r5, -((CFRAME_CALLEE_REGS_START_SLOT + 5) * 4)) 313 CFI_REL_OFFSET(r4, -((CFRAME_CALLEE_REGS_START_SLOT + 6) * 4)) 314 315 mov fp, r0 316 CFI_DEF_CFA_REGISTER(fp) 317 318 // Restore callee saved registers from dropped CFrame 319 sub r0, r0, #((CFRAME_CALLEE_REGS_START_SLOT * 4) - 4) 320 ldr r10, [r0, #-4]! 321 CFI_RESTORE(r10) 322 ldrd r8, r9, [r0, #-8]! 323 CFI_RESTORE(r9) 324 CFI_RESTORE(r8) 325 ldrd r6, r7, [r0, #-8]! 326 CFI_RESTORE(r7) 327 CFI_RESTORE(r6) 328 ldrd r4, r5, [r0, #-8]! 329 CFI_RESTORE(r5) 330 CFI_RESTORE(r4) 331 332#ifndef PANDA_TARGET_ARM32_ABI_SOFT 333 vldr d15, [r0, #-8] 334 CFI_RESTORE(d15) 335 vldr d14, [r0, #-16] 336 CFI_RESTORE(d14) 337 vldr d13, [r0, #-24] 338 CFI_RESTORE(d13) 339 vldr d12, [r0, #-32] 340 CFI_RESTORE(d12) 341 vldr d11, [r0, #-40] 342 CFI_RESTORE(d11) 343 vldr d10, [r0, #-48] 344 CFI_RESTORE(d10) 345 vldr d9, [r0, #-56] 346 CFI_RESTORE(d9) 347 vldr d8, [r0, #-64] 348 CFI_RESTORE(d8) 349#endif 350 351 // We need to clear return value, since it will be written to the IFrame's accumulator. Without this, it holds 352 // garbage and StackWalker verification might fail. 353 mov r0, #0 354 mov r1, #0 355 356 mov sp, fp 357 pop {fp, lr} 358 CFI_RESTORE(lr) 359 CFI_RESTORE(fp) 360 CFI_DEF_CFA(sp, 0) 361 bx lr 362 CFI_ENDPROC 363 364