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