1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_S_ 18#define ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_S_ 19 20#include "asm_support_arm64.h" 21#include "interpreter/cfi_asm_support.h" 22 23// Define special registers. 24 25// Register holding Thread::Current(). 26#define xSELF x19 27// Frame Pointer 28#define xFP x29 29// Link Register 30#define xLR x30 31// Define the intraprocedural linkage temporary registers. 32#define xIP0 x16 33#define wIP0 w16 34#define xIP1 x17 35#define wIP1 w17 36 37#ifdef RESERVE_MARKING_REGISTER 38// Marking Register, holding Thread::Current()->GetIsGcMarking(). 39#define wMR w20 40#endif 41 42// Implicit suspend check register. 43#define xSUSPEND x21 44 45.macro CFI_EXPRESSION_BREG n, b, offset 46 .if (-0x40 <= (\offset)) && ((\offset) < 0x40) 47 CFI_EXPRESSION_BREG_1(\n, \b, \offset) 48 .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000) 49 CFI_EXPRESSION_BREG_2(\n, \b, \offset) 50 .else 51 .error "Unsupported offset" 52 .endif 53.endm 54 55.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size 56 .if ((\size) < 0) 57 .error "Size should be positive" 58 .endif 59 .if (((\offset) < -0x40) || ((\offset) >= 0x40)) 60 .error "Unsupported offset" 61 .endif 62 .if ((\size) < 0x80) 63 CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size) 64 .elseif ((\size) < 0x4000) 65 CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size) 66 .else 67 .error "Unsupported size" 68 .endif 69.endm 70 71.macro CFI_REMEMBER_STATE 72 .cfi_remember_state 73.endm 74 75// The spec is not clear whether the CFA is part of the saved state and tools 76// differ in the behaviour, so explicitly set the CFA to avoid any ambiguity. 77// The restored CFA state should match the CFA state during CFI_REMEMBER_STATE. 78.macro CFI_RESTORE_STATE_AND_DEF_CFA reg, offset 79 .cfi_restore_state 80 .cfi_def_cfa \reg, \offset 81.endm 82 83.macro ENTRY_ALIGNED name, alignment 84 .type \name, #function 85 .hidden \name // Hide this as a global symbol, so we do not incur plt calls. 86 .global \name 87 .balign \alignment 88\name: 89 .cfi_startproc 90.endm 91 92.macro ENTRY name 93 ENTRY_ALIGNED \name, 16 94.endm 95 96.macro END name 97 .cfi_endproc 98 .size \name, .-\name 99.endm 100 101.macro UNIMPLEMENTED name 102 ENTRY \name 103 brk 0 104 END \name 105.endm 106 107// Macro to poison (negate) the reference for heap poisoning. 108.macro POISON_HEAP_REF rRef 109#ifdef USE_HEAP_POISONING 110 neg \rRef, \rRef 111#endif // USE_HEAP_POISONING 112.endm 113 114// Macro to unpoison (negate) the reference for heap poisoning. 115.macro UNPOISON_HEAP_REF rRef 116#ifdef USE_HEAP_POISONING 117 neg \rRef, \rRef 118#endif // USE_HEAP_POISONING 119.endm 120 121.macro INCREASE_FRAME frame_adjustment 122 sub sp, sp, #(\frame_adjustment) 123 .cfi_adjust_cfa_offset (\frame_adjustment) 124.endm 125 126.macro DECREASE_FRAME frame_adjustment 127 add sp, sp, #(\frame_adjustment) 128 .cfi_adjust_cfa_offset -(\frame_adjustment) 129.endm 130 131.macro SAVE_REG reg, offset 132 str \reg, [sp, #(\offset)] 133 .cfi_rel_offset \reg, (\offset) 134.endm 135 136.macro RESTORE_REG_BASE base, reg, offset 137 ldr \reg, [\base, #(\offset)] 138 .cfi_restore \reg 139.endm 140 141.macro RESTORE_REG reg, offset 142 RESTORE_REG_BASE sp, \reg, \offset 143.endm 144 145.macro SAVE_TWO_REGS_BASE base, reg1, reg2, offset 146 stp \reg1, \reg2, [\base, #(\offset)] 147 .cfi_rel_offset \reg1, (\offset) 148 .cfi_rel_offset \reg2, (\offset) + 8 149.endm 150 151.macro SAVE_TWO_REGS reg1, reg2, offset 152 SAVE_TWO_REGS_BASE sp, \reg1, \reg2, \offset 153.endm 154 155.macro SAVE_TWO_REGS_INCREASE_FRAME reg1, reg2, frame_adjustment 156 stp \reg1, \reg2, [sp, #-(\frame_adjustment)]! 157 .cfi_adjust_cfa_offset (\frame_adjustment) 158 .cfi_rel_offset \reg1, 0 159 .cfi_rel_offset \reg2, 8 160.endm 161 162.macro RESTORE_TWO_REGS_BASE base, reg1, reg2, offset 163 ldp \reg1, \reg2, [\base, #(\offset)] 164 .cfi_restore \reg1 165 .cfi_restore \reg2 166.endm 167 168.macro RESTORE_TWO_REGS reg1, reg2, offset 169 RESTORE_TWO_REGS_BASE sp, \reg1, \reg2, \offset 170.endm 171 172.macro RESTORE_TWO_REGS_DECREASE_FRAME reg1, reg2, frame_adjustment 173 ldp \reg1, \reg2, [sp], #(\frame_adjustment) 174 .cfi_restore \reg1 175 .cfi_restore \reg2 176 .cfi_adjust_cfa_offset -(\frame_adjustment) 177.endm 178 179#define ALL_ARGS_SIZE (/*x0-x7*/ 8 * 8 + /*d0-d7*/ 8 * 8) 180 181.macro SAVE_ALL_ARGS_INCREASE_FRAME extra_space 182 // Save register args x0-x7, d0-d7 and return address. 183 stp x0, x1, [sp, #-(ALL_ARGS_SIZE + \extra_space)]! 184 .cfi_adjust_cfa_offset (ALL_ARGS_SIZE + \extra_space) 185 stp x2, x3, [sp, #16] 186 stp x4, x5, [sp, #32] 187 stp x6, x7, [sp, #48] 188 stp d0, d1, [sp, #64] 189 stp d2, d3, [sp, #80] 190 stp d4, d5, [sp, #96] 191 stp d6, d7, [sp, #112] 192.endm 193 194.macro RESTORE_ALL_ARGS_DECREASE_FRAME extra_space 195 ldp x2, x3, [sp, #16] 196 ldp x4, x5, [sp, #32] 197 ldp x6, x7, [sp, #48] 198 ldp d0, d1, [sp, #64] 199 ldp d2, d3, [sp, #80] 200 ldp d4, d5, [sp, #96] 201 ldp d6, d7, [sp, #112] 202 ldp x0, x1, [sp], #(ALL_ARGS_SIZE + \extra_space) 203 .cfi_adjust_cfa_offset -(ALL_ARGS_SIZE + \extra_space) 204.endm 205 206.macro LOAD_RUNTIME_INSTANCE reg 207#if __has_feature(hwaddress_sanitizer) 208 adrp \reg, :pg_hi21_nc:_ZN3art7Runtime9instance_E 209#else 210 adrp \reg, _ZN3art7Runtime9instance_E 211#endif 212 ldr \reg, [\reg, #:lo12:_ZN3art7Runtime9instance_E] 213.endm 214 215// Macro to refresh the Marking Register (W20). 216// 217// This macro must be called at the end of functions implementing 218// entrypoints that possibly (directly or indirectly) perform a 219// suspend check (before they return). 220.macro REFRESH_MARKING_REGISTER 221#ifdef RESERVE_MARKING_REGISTER 222 ldr wMR, [xSELF, #THREAD_IS_GC_MARKING_OFFSET] 223#endif 224.endm 225 226// Macro to refresh the suspend check register. 227// 228// We do not refresh `xSUSPEND` after every transition to Runnable, so there is 229// a chance that an implicit suspend check loads null to xSUSPEND but before 230// causing a SIGSEGV at the next implicit suspend check we make a runtime call 231// that performs the suspend check explicitly. This can cause a spurious fault 232// without a pending suspend check request but it should be rare and the fault 233// overhead was already expected when we triggered the suspend check, we just 234// pay the price later than expected. 235.macro REFRESH_SUSPEND_CHECK_REGISTER 236 ldr xSUSPEND, [xSELF, #THREAD_SUSPEND_TRIGGER_OFFSET] 237.endm 238 239 /* 240 * Macro that sets up the callee save frame to conform with 241 * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly). 242 */ 243.macro SETUP_SAVE_REFS_ONLY_FRAME 244 // art::Runtime* xIP0 = art::Runtime::instance_; 245 // Our registers aren't intermixed - just spill in order. 246 LOAD_RUNTIME_INSTANCE xIP0 247 248 // ArtMethod* xIP0 = Runtime::instance_->callee_save_methods_[kSaveRefOnly]; 249 ldr xIP0, [xIP0, RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET] 250 251 INCREASE_FRAME 96 252 253 // Ugly compile-time check, but we only have the preprocessor. 254#if (FRAME_SIZE_SAVE_REFS_ONLY != 96) 255#error "FRAME_SIZE_SAVE_REFS_ONLY(ARM64) size not as expected." 256#endif 257 258 // GP callee-saves. 259 // x20 paired with ArtMethod* - see below. 260 SAVE_TWO_REGS x21, x22, 16 261 SAVE_TWO_REGS x23, x24, 32 262 SAVE_TWO_REGS x25, x26, 48 263 SAVE_TWO_REGS x27, x28, 64 264 SAVE_TWO_REGS x29, xLR, 80 265 266 // Store ArtMethod* Runtime::callee_save_methods_[kSaveRefsOnly]. 267 // Note: We could avoid saving X20 in the case of Baker read 268 // barriers, as it is overwritten by REFRESH_MARKING_REGISTER 269 // later; but it's not worth handling this special case. 270 stp xIP0, x20, [sp] 271 .cfi_rel_offset x20, 8 272 273 // Place sp in Thread::Current()->top_quick_frame. 274 mov xIP0, sp 275 str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET] 276.endm 277 278// TODO: Probably no need to restore registers preserved by aapcs64. 279.macro RESTORE_SAVE_REFS_ONLY_FRAME 280 // Callee-saves. 281 // Note: Likewise, we could avoid restoring X20 in the case of Baker 282 // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER 283 // later; but it's not worth handling this special case. 284 RESTORE_REG x20, 8 285 RESTORE_TWO_REGS x21, x22, 16 286 RESTORE_TWO_REGS x23, x24, 32 287 RESTORE_TWO_REGS x25, x26, 48 288 RESTORE_TWO_REGS x27, x28, 64 289 RESTORE_TWO_REGS x29, xLR, 80 290 291 DECREASE_FRAME 96 292.endm 293 294.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL base 295 // Ugly compile-time check, but we only have the preprocessor. 296#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 224) 297#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(ARM64) size not as expected." 298#endif 299 300 // Stack alignment filler [\base, #8]. 301 // FP args. 302 stp d0, d1, [\base, #16] 303 stp d2, d3, [\base, #32] 304 stp d4, d5, [\base, #48] 305 stp d6, d7, [\base, #64] 306 307 // Core args. 308 stp x1, x2, [\base, #80] 309 stp x3, x4, [\base, #96] 310 stp x5, x6, [\base, #112] 311 312 // x7, Callee-saves. 313 // Note: We could avoid saving X20 in the case of Baker read 314 // barriers, as it is overwritten by REFRESH_MARKING_REGISTER 315 // later; but it's not worth handling this special case. 316 stp x7, x20, [\base, #128] 317 .cfi_rel_offset x20, 136 318 SAVE_TWO_REGS_BASE \base, x21, x22, 144 319 SAVE_TWO_REGS_BASE \base, x23, x24, 160 320 SAVE_TWO_REGS_BASE \base, x25, x26, 176 321 SAVE_TWO_REGS_BASE \base, x27, x28, 192 322 323 // x29(callee-save) and LR. 324 SAVE_TWO_REGS_BASE \base, x29, xLR, 208 325.endm 326 327// TODO: Probably no need to restore registers preserved by aapcs64. (That would require 328// auditing all users to make sure they restore aapcs64 callee-save registers they clobber.) 329.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL base 330 // FP args. 331 ldp d0, d1, [\base, #16] 332 ldp d2, d3, [\base, #32] 333 ldp d4, d5, [\base, #48] 334 ldp d6, d7, [\base, #64] 335 336 // Core args. 337 ldp x1, x2, [\base, #80] 338 ldp x3, x4, [\base, #96] 339 ldp x5, x6, [\base, #112] 340 341 // x7, callee-saves and LR. 342 // Note: Likewise, we could avoid restoring X20 in the case of Baker 343 // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER 344 // later; but it's not worth handling this special case. 345 ldp x7, x20, [\base, #128] 346 .cfi_restore x20 347 RESTORE_TWO_REGS_BASE \base, x21, x22, 144 348 RESTORE_TWO_REGS_BASE \base, x23, x24, 160 349 RESTORE_TWO_REGS_BASE \base, x25, x26, 176 350 RESTORE_TWO_REGS_BASE \base, x27, x28, 192 351 RESTORE_TWO_REGS_BASE \base, x29, xLR, 208 352.endm 353 354.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME 355 RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL sp 356 DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 357.endm 358 359.macro SAVE_ALL_CALLEE_SAVES offset 360 // FP callee-saves. 361 stp d8, d9, [sp, #(0 + \offset)] 362 stp d10, d11, [sp, #(16 + \offset)] 363 stp d12, d13, [sp, #(32 + \offset)] 364 stp d14, d15, [sp, #(48 + \offset)] 365 366 // GP callee-saves 367 SAVE_TWO_REGS x19, x20, (64 + \offset) 368 SAVE_TWO_REGS x21, x22, (80 + \offset) 369 SAVE_TWO_REGS x23, x24, (96 + \offset) 370 SAVE_TWO_REGS x25, x26, (112 + \offset) 371 SAVE_TWO_REGS x27, x28, (128 + \offset) 372 SAVE_TWO_REGS x29, xLR, (144 + \offset) 373.endm 374 375 /* 376 * Macro that sets up the callee save frame to conform with 377 * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves) 378 */ 379.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME 380 // art::Runtime* xIP0 = art::Runtime::instance_; 381 // Our registers aren't intermixed - just spill in order. 382 LOAD_RUNTIME_INSTANCE xIP0 383 384 // ArtMethod* xIP0 = Runtime::instance_->callee_save_methods_[kSaveAllCalleeSaves]; 385 ldr xIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET] 386 387 INCREASE_FRAME 176 388 389 // Ugly compile-time check, but we only have the preprocessor. 390#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 176) 391#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(ARM64) size not as expected." 392#endif 393 394 // Stack alignment filler [sp, #8]. 395 SAVE_ALL_CALLEE_SAVES 16 396 397 // Store ArtMethod* Runtime::callee_save_methods_[kSaveAllCalleeSaves]. 398 str xIP0, [sp] 399 // Place sp in Thread::Current()->top_quick_frame. 400 mov xIP0, sp 401 str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET] 402.endm 403 404 /* 405 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 406 * exception is Thread::Current()->exception_ when the runtime method frame is ready. 407 */ 408.macro DELIVER_PENDING_EXCEPTION_FRAME_READY 409 mov x0, xSELF 410 411 // Point of no return. 412 bl artDeliverPendingExceptionFromCode // artDeliverPendingExceptionFromCode(Thread*) 413 bl art_quick_do_long_jump // (Context*) 414 brk 0 // Unreached 415.endm 416 417 /* 418 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 419 * exception is Thread::Current()->exception_. 420 */ 421.macro DELIVER_PENDING_EXCEPTION 422 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME 423 DELIVER_PENDING_EXCEPTION_FRAME_READY 424.endm 425 426.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg 427 ldr \reg, [xSELF, # THREAD_EXCEPTION_OFFSET] // Get exception field. 428 cbnz \reg, 1f 429 ret 4301: 431 DELIVER_PENDING_EXCEPTION 432.endm 433 434.macro RETURN_OR_DELIVER_PENDING_EXCEPTION 435 RETURN_OR_DELIVER_PENDING_EXCEPTION_REG xIP0 436.endm 437 438// Locking is needed for both managed code and JNI stubs. 439.macro LOCK_OBJECT_FAST_PATH obj, slow_lock, can_be_null 440 // Use scratch registers x8-x11 as temporaries. 441 ldr w9, [xSELF, #THREAD_ID_OFFSET] 442 .if \can_be_null 443 cbz \obj, \slow_lock 444 .endif 445 // Exclusive load/store has no immediate anymore. 446 add x8, \obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET 4471: 448 ldaxr w10, [x8] // Acquire needed only in most common case. 449 eor w11, w10, w9 // Prepare the value to store if unlocked 450 // (thread id, count of 0 and preserved read barrier bits), 451 // or prepare to compare thread id for recursive lock check 452 // (lock_word.ThreadId() ^ self->ThreadId()). 453 tst w10, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED // Test the non-gc bits. 454 b.ne 2f // Check if unlocked. 455 // Unlocked case - store w11: original lock word plus thread id, preserved read barrier bits. 456 stxr w10, w11, [x8] 457 cbnz w10, 1b // If the store failed, retry. 458 ret 4592: // w10: original lock word, w9: thread id, w11: w10 ^ w9 460 // Check lock word state and thread id together, 461 tst w11, #(LOCK_WORD_STATE_MASK_SHIFTED | LOCK_WORD_THIN_LOCK_OWNER_MASK_SHIFTED) 462 b.ne \slow_lock 463 add w11, w10, #LOCK_WORD_THIN_LOCK_COUNT_ONE // Increment the recursive lock count. 464 tst w11, #LOCK_WORD_THIN_LOCK_COUNT_MASK_SHIFTED // Test the new thin lock count. 465 b.eq \slow_lock // Zero as the new count indicates overflow, go slow path. 466 stxr w10, w11, [x8] 467 cbnz w10, 1b // If the store failed, retry. 468 ret 469.endm 470 471// Unlocking is needed for both managed code and JNI stubs. 472.macro UNLOCK_OBJECT_FAST_PATH obj, slow_unlock, can_be_null 473 // Use scratch registers x8-x11 as temporaries. 474 ldr w9, [xSELF, #THREAD_ID_OFFSET] 475 .if \can_be_null 476 cbz \obj, \slow_unlock 477 .endif 478 // Exclusive load/store has no immediate anymore. 479 add x8, \obj, #MIRROR_OBJECT_LOCK_WORD_OFFSET 4801: 481#ifndef USE_READ_BARRIER 482 ldr w10, [x8] 483#else 484 ldxr w10, [x8] // Need to use atomic instructions for read barrier. 485#endif 486 eor w11, w10, w9 // Prepare the value to store if simply locked 487 // (mostly 0s, and preserved read barrier bits), 488 // or prepare to compare thread id for recursive lock check 489 // (lock_word.ThreadId() ^ self->ThreadId()). 490 tst w11, #LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED // Test the non-gc bits. 491 b.ne 2f // Locked recursively or by other thread? 492 // Transition to unlocked. 493#ifndef USE_READ_BARRIER 494 stlr w11, [x8] 495#else 496 stlxr w10, w11, [x8] // Need to use atomic instructions for read barrier. 497 cbnz w10, 1b // If the store failed, retry. 498#endif 499 ret 5002: 501 // Check lock word state and thread id together. 502 tst w11, #(LOCK_WORD_STATE_MASK_SHIFTED | LOCK_WORD_THIN_LOCK_OWNER_MASK_SHIFTED) 503 b.ne \slow_unlock 504 sub w11, w10, #LOCK_WORD_THIN_LOCK_COUNT_ONE // decrement count 505#ifndef USE_READ_BARRIER 506 str w11, [x8] 507#else 508 stxr w10, w11, [x8] // Need to use atomic instructions for read barrier. 509 cbnz w10, 1b // If the store failed, retry. 510#endif 511 ret 512.endm 513 514#endif // ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_S_ 515