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#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 38// Marking Register, holding Thread::Current()->GetIsGcMarking(). 39// Only used with the Concurrent Copying (CC) garbage 40// collector, with the Baker read barrier configuration. 41#define wMR w20 42#endif 43 44.macro CFI_EXPRESSION_BREG n, b, offset 45 .if (-0x40 <= (\offset)) && ((\offset) < 0x40) 46 CFI_EXPRESSION_BREG_1(\n, \b, \offset) 47 .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000) 48 CFI_EXPRESSION_BREG_2(\n, \b, \offset) 49 .else 50 .error "Unsupported offset" 51 .endif 52.endm 53 54.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size 55 .if ((\size) < 0) 56 .error "Size should be positive" 57 .endif 58 .if (((\offset) < -0x40) || ((\offset) >= 0x40)) 59 .error "Unsupported offset" 60 .endif 61 .if ((\size) < 0x80) 62 CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size) 63 .elseif ((\size) < 0x4000) 64 CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size) 65 .else 66 .error "Unsupported size" 67 .endif 68.endm 69 70.macro ENTRY_ALIGNED name, alignment 71 .type \name, #function 72 .hidden \name // Hide this as a global symbol, so we do not incur plt calls. 73 .global \name 74 // ART-compiled functions have OatQuickMethodHeader but assembly funtions do not. 75 // Prefix the assembly code with 0xFFs, which means there is no method header. 76 .byte 0xFF, 0xFF, 0xFF, 0xFF 77 // Cache alignment for function entry. 78 // NB: 0xFF because there is a bug in balign where 0x00 creates nop instructions. 79 .balign \alignment, 0xFF 80\name: 81 .cfi_startproc 82.endm 83 84.macro ENTRY name 85 ENTRY_ALIGNED \name, 16 86.endm 87 88.macro END name 89 .cfi_endproc 90 .size \name, .-\name 91.endm 92 93.macro UNIMPLEMENTED name 94 ENTRY \name 95 brk 0 96 END \name 97.endm 98 99// Macro to poison (negate) the reference for heap poisoning. 100.macro POISON_HEAP_REF rRef 101#ifdef USE_HEAP_POISONING 102 neg \rRef, \rRef 103#endif // USE_HEAP_POISONING 104.endm 105 106// Macro to unpoison (negate) the reference for heap poisoning. 107.macro UNPOISON_HEAP_REF rRef 108#ifdef USE_HEAP_POISONING 109 neg \rRef, \rRef 110#endif // USE_HEAP_POISONING 111.endm 112 113.macro INCREASE_FRAME frame_adjustment 114 sub sp, sp, #(\frame_adjustment) 115 .cfi_adjust_cfa_offset (\frame_adjustment) 116.endm 117 118.macro DECREASE_FRAME frame_adjustment 119 add sp, sp, #(\frame_adjustment) 120 .cfi_adjust_cfa_offset -(\frame_adjustment) 121.endm 122 123.macro SAVE_REG reg, offset 124 str \reg, [sp, #(\offset)] 125 .cfi_rel_offset \reg, (\offset) 126.endm 127 128.macro RESTORE_REG_BASE base, reg, offset 129 ldr \reg, [\base, #(\offset)] 130 .cfi_restore \reg 131.endm 132 133.macro RESTORE_REG reg, offset 134 RESTORE_REG_BASE sp, \reg, \offset 135.endm 136 137.macro SAVE_TWO_REGS_BASE base, reg1, reg2, offset 138 stp \reg1, \reg2, [\base, #(\offset)] 139 .cfi_rel_offset \reg1, (\offset) 140 .cfi_rel_offset \reg2, (\offset) + 8 141.endm 142 143.macro SAVE_TWO_REGS reg1, reg2, offset 144 SAVE_TWO_REGS_BASE sp, \reg1, \reg2, \offset 145.endm 146 147.macro RESTORE_TWO_REGS_BASE base, reg1, reg2, offset 148 ldp \reg1, \reg2, [\base, #(\offset)] 149 .cfi_restore \reg1 150 .cfi_restore \reg2 151.endm 152 153.macro RESTORE_TWO_REGS reg1, reg2, offset 154 RESTORE_TWO_REGS_BASE sp, \reg1, \reg2, \offset 155.endm 156 157.macro LOAD_RUNTIME_INSTANCE reg 158#if __has_feature(hwaddress_sanitizer) && __clang_major__ >= 10 159 adrp \reg, :pg_hi21_nc:_ZN3art7Runtime9instance_E 160#else 161 adrp \reg, _ZN3art7Runtime9instance_E 162#endif 163 ldr \reg, [\reg, #:lo12:_ZN3art7Runtime9instance_E] 164.endm 165 166// Macro to refresh the Marking Register (W20). 167// 168// This macro must be called at the end of functions implementing 169// entrypoints that possibly (directly or indirectly) perform a 170// suspend check (before they return). 171.macro REFRESH_MARKING_REGISTER 172#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 173 ldr wMR, [xSELF, #THREAD_IS_GC_MARKING_OFFSET] 174#endif 175.endm 176 177 /* 178 * Macro that sets up the callee save frame to conform with 179 * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly). 180 */ 181.macro SETUP_SAVE_REFS_ONLY_FRAME 182 // art::Runtime* xIP0 = art::Runtime::instance_; 183 // Our registers aren't intermixed - just spill in order. 184 LOAD_RUNTIME_INSTANCE xIP0 185 186 // ArtMethod* xIP0 = Runtime::instance_->callee_save_methods_[kSaveRefOnly]; 187 ldr xIP0, [xIP0, RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET] 188 189 INCREASE_FRAME 96 190 191 // Ugly compile-time check, but we only have the preprocessor. 192#if (FRAME_SIZE_SAVE_REFS_ONLY != 96) 193#error "FRAME_SIZE_SAVE_REFS_ONLY(ARM64) size not as expected." 194#endif 195 196 // GP callee-saves. 197 // x20 paired with ArtMethod* - see below. 198 SAVE_TWO_REGS x21, x22, 16 199 SAVE_TWO_REGS x23, x24, 32 200 SAVE_TWO_REGS x25, x26, 48 201 SAVE_TWO_REGS x27, x28, 64 202 SAVE_TWO_REGS x29, xLR, 80 203 204 // Store ArtMethod* Runtime::callee_save_methods_[kSaveRefsOnly]. 205 // Note: We could avoid saving X20 in the case of Baker read 206 // barriers, as it is overwritten by REFRESH_MARKING_REGISTER 207 // later; but it's not worth handling this special case. 208 stp xIP0, x20, [sp] 209 .cfi_rel_offset x20, 8 210 211 // Place sp in Thread::Current()->top_quick_frame. 212 mov xIP0, sp 213 str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET] 214.endm 215 216// TODO: Probably no need to restore registers preserved by aapcs64. 217.macro RESTORE_SAVE_REFS_ONLY_FRAME 218 // Callee-saves. 219 // Note: Likewise, we could avoid restoring X20 in the case of Baker 220 // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER 221 // later; but it's not worth handling this special case. 222 RESTORE_REG x20, 8 223 RESTORE_TWO_REGS x21, x22, 16 224 RESTORE_TWO_REGS x23, x24, 32 225 RESTORE_TWO_REGS x25, x26, 48 226 RESTORE_TWO_REGS x27, x28, 64 227 RESTORE_TWO_REGS x29, xLR, 80 228 229 DECREASE_FRAME 96 230.endm 231 232.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL base 233 // Ugly compile-time check, but we only have the preprocessor. 234#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 224) 235#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(ARM64) size not as expected." 236#endif 237 238 // Stack alignment filler [\base, #8]. 239 // FP args. 240 stp d0, d1, [\base, #16] 241 stp d2, d3, [\base, #32] 242 stp d4, d5, [\base, #48] 243 stp d6, d7, [\base, #64] 244 245 // Core args. 246 SAVE_TWO_REGS_BASE \base, x1, x2, 80 247 SAVE_TWO_REGS_BASE \base, x3, x4, 96 248 SAVE_TWO_REGS_BASE \base, x5, x6, 112 249 250 // x7, Callee-saves. 251 // Note: We could avoid saving X20 in the case of Baker read 252 // barriers, as it is overwritten by REFRESH_MARKING_REGISTER 253 // later; but it's not worth handling this special case. 254 SAVE_TWO_REGS_BASE \base, x7, x20, 128 255 SAVE_TWO_REGS_BASE \base, x21, x22, 144 256 SAVE_TWO_REGS_BASE \base, x23, x24, 160 257 SAVE_TWO_REGS_BASE \base, x25, x26, 176 258 SAVE_TWO_REGS_BASE \base, x27, x28, 192 259 260 // x29(callee-save) and LR. 261 SAVE_TWO_REGS_BASE \base, x29, xLR, 208 262.endm 263 264// TODO: Probably no need to restore registers preserved by aapcs64. (That would require 265// auditing all users to make sure they restore aapcs64 callee-save registers they clobber.) 266.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL base 267 // FP args. 268 ldp d0, d1, [\base, #16] 269 ldp d2, d3, [\base, #32] 270 ldp d4, d5, [\base, #48] 271 ldp d6, d7, [\base, #64] 272 273 // Core args. 274 RESTORE_TWO_REGS_BASE \base, x1, x2, 80 275 RESTORE_TWO_REGS_BASE \base, x3, x4, 96 276 RESTORE_TWO_REGS_BASE \base, x5, x6, 112 277 278 // x7, Callee-saves. 279 // Note: Likewise, we could avoid restoring X20 in the case of Baker 280 // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER 281 // later; but it's not worth handling this special case. 282 RESTORE_TWO_REGS_BASE \base, x7, x20, 128 283 RESTORE_TWO_REGS_BASE \base, x21, x22, 144 284 RESTORE_TWO_REGS_BASE \base, x23, x24, 160 285 RESTORE_TWO_REGS_BASE \base, x25, x26, 176 286 RESTORE_TWO_REGS_BASE \base, x27, x28, 192 287 288 // x29(callee-save) and LR. 289 RESTORE_TWO_REGS_BASE \base, x29, xLR, 208 290.endm 291 292.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME 293 RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL sp 294 DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 295.endm 296 297.macro SAVE_ALL_CALLEE_SAVES offset 298 // FP callee-saves. 299 stp d8, d9, [sp, #(0 + \offset)] 300 stp d10, d11, [sp, #(16 + \offset)] 301 stp d12, d13, [sp, #(32 + \offset)] 302 stp d14, d15, [sp, #(48 + \offset)] 303 304 // GP callee-saves 305 SAVE_TWO_REGS x19, x20, (64 + \offset) 306 SAVE_TWO_REGS x21, x22, (80 + \offset) 307 SAVE_TWO_REGS x23, x24, (96 + \offset) 308 SAVE_TWO_REGS x25, x26, (112 + \offset) 309 SAVE_TWO_REGS x27, x28, (128 + \offset) 310 SAVE_TWO_REGS x29, xLR, (144 + \offset) 311.endm 312 313 /* 314 * Macro that sets up the callee save frame to conform with 315 * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves) 316 */ 317.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME 318 // art::Runtime* xIP0 = art::Runtime::instance_; 319 // Our registers aren't intermixed - just spill in order. 320 LOAD_RUNTIME_INSTANCE xIP0 321 322 // ArtMethod* xIP0 = Runtime::instance_->callee_save_methods_[kSaveAllCalleeSaves]; 323 ldr xIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET] 324 325 INCREASE_FRAME 176 326 327 // Ugly compile-time check, but we only have the preprocessor. 328#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 176) 329#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(ARM64) size not as expected." 330#endif 331 332 // Stack alignment filler [sp, #8]. 333 SAVE_ALL_CALLEE_SAVES 16 334 335 // Store ArtMethod* Runtime::callee_save_methods_[kSaveAllCalleeSaves]. 336 str xIP0, [sp] 337 // Place sp in Thread::Current()->top_quick_frame. 338 mov xIP0, sp 339 str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET] 340.endm 341 342 /* 343 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 344 * exception is Thread::Current()->exception_ when the runtime method frame is ready. 345 */ 346.macro DELIVER_PENDING_EXCEPTION_FRAME_READY 347 mov x0, xSELF 348 349 // Point of no return. 350 bl artDeliverPendingExceptionFromCode // artDeliverPendingExceptionFromCode(Thread*) 351 brk 0 // Unreached 352.endm 353 354 /* 355 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 356 * exception is Thread::Current()->exception_. 357 */ 358.macro DELIVER_PENDING_EXCEPTION 359 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME 360 DELIVER_PENDING_EXCEPTION_FRAME_READY 361.endm 362 363.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg 364 ldr \reg, [xSELF, # THREAD_EXCEPTION_OFFSET] // Get exception field. 365 cbnz \reg, 1f 366 ret 3671: 368 DELIVER_PENDING_EXCEPTION 369.endm 370 371.macro RETURN_OR_DELIVER_PENDING_EXCEPTION 372 RETURN_OR_DELIVER_PENDING_EXCEPTION_REG xIP0 373.endm 374 375#endif // ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_S_ 376