1/* 2 * Copyright (C) 2013 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_ARM_ASM_SUPPORT_ARM_S_ 18#define ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_S_ 19 20#include "asm_support_arm.h" 21#include "interpreter/cfi_asm_support.h" 22 23// Define special registers. 24 25// Register holding suspend check count down. 26#define rSUSPEND r4 27// Register holding Thread::Current(). 28#define rSELF r9 29 30#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 31// Marking Register, holding Thread::Current()->GetIsGcMarking(). 32// Only used with the Concurrent Copying (CC) garbage 33// collector, with the Baker read barrier configuration. 34#define rMR r8 35#endif 36 37.syntax unified 38.arch armv7-a 39.arch_extension idiv 40.thumb 41 42.macro CFI_EXPRESSION_BREG n, b, offset 43 .if (-0x40 <= (\offset)) && ((\offset) < 0x40) 44 CFI_EXPRESSION_BREG_1(\n, \b, \offset) 45 .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000) 46 CFI_EXPRESSION_BREG_2(\n, \b, \offset) 47 .else 48 .error "Unsupported offset" 49 .endif 50.endm 51 52.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size 53 .if ((\size) < 0) 54 .error "Size should be positive" 55 .endif 56 .if (((\offset) < -0x40) || ((\offset) >= 0x40)) 57 .error "Unsupported offset" 58 .endif 59 .if ((\size) < 0x80) 60 CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size) 61 .elseif ((\size) < 0x4000) 62 CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size) 63 .else 64 .error "Unsupported size" 65 .endif 66.endm 67 68// Macro to generate the value of Runtime::Current into rDest. As it uses labels 69// then the labels need to be unique. We bind these to the function name in the ENTRY macros. 70.macro RUNTIME_CURRENT name, num, rDest 71 .if .Lruntime_current\num\()_used 72 .error 73 .endif 74 .set .Lruntime_current\num\()_used, 1 75 ldr \rDest, .Lruntime_instance_\name\()_\num @ Load GOT_PREL offset of Runtime::instance_. 76.Lload_got_\name\()_\num\(): 77 add \rDest, pc @ Fixup GOT_PREL address. 78 ldr \rDest, [\rDest] @ Load address of Runtime::instance_. 79 ldr \rDest, [\rDest] @ Load Runtime::instance_. 80.endm 81 82// Common ENTRY declaration code for ARM and thumb, an ENTRY should always be paired with an END. 83// Declares the RUNTIME_CURRENT[123] macros that can be used within an ENTRY and will have literals 84// generated at END. 85.macro DEF_ENTRY thumb_or_arm, name, alignment 86 \thumb_or_arm 87// Clang ignores .thumb_func and requires an explicit .thumb. Investigate whether we should still 88// carry around the .thumb_func. 89 .ifc \thumb_or_arm, .thumb_func 90 .thumb 91 .endif 92 .type \name, #function 93 .hidden \name // Hide this as a global symbol, so we do not incur plt calls. 94 .global \name 95 // ART-compiled functions have OatQuickMethodHeader but assembly funtions do not. 96 // Prefix the assembly code with 0xFFs, which means there is no method header. 97 .byte 0xFF, 0xFF, 0xFF, 0xFF 98 // Cache alignment for function entry. 99 // NB: 0xFF because there is a bug in balign where 0x00 creates nop instructions. 100 .balign \alignment, 0xFF 101\name: 102 .cfi_startproc 103 .fnstart 104 // Track whether RUNTIME_CURRENT was used. 105 .set .Lruntime_current1_used, 0 106 .set .Lruntime_current2_used, 0 107 .set .Lruntime_current3_used, 0 108 // The RUNTIME_CURRENT macros that are bound to the \name argument of DEF_ENTRY to ensure 109 // that label names are unique. 110 .macro RUNTIME_CURRENT1 rDest 111 RUNTIME_CURRENT \name, 1, \rDest 112 .endm 113 .macro RUNTIME_CURRENT2 rDest 114 RUNTIME_CURRENT \name, 2, \rDest 115 .endm 116 .macro RUNTIME_CURRENT3 rDest 117 RUNTIME_CURRENT \name, 3, \rDest 118 .endm 119.endm 120 121// A thumb2 style ENTRY. 122.macro ENTRY name 123 DEF_ENTRY .thumb_func, \name, 16 124.endm 125.macro ENTRY_ALIGNED name, alignment 126 DEF_ENTRY .thumb_func, \name, \alignment 127.endm 128 129// A ARM style ENTRY. 130.macro ARM_ENTRY name 131 DEF_ENTRY .arm, \name, 16 132.endm 133 134// Terminate an ENTRY and generate GOT_PREL references. 135.macro END name 136 // Generate offsets of GOT and Runtime::instance_ used in RUNTIME_CURRENT. 137 .if .Lruntime_current1_used 138 .Lruntime_instance_\name\()_1: 139 .word _ZN3art7Runtime9instance_E(GOT_PREL)-(.Lload_got_\name\()_1+4) 140 .endif 141 .if .Lruntime_current2_used 142 .Lruntime_instance_\name\()_2: 143 .word _ZN3art7Runtime9instance_E(GOT_PREL)-(.Lload_got_\name\()_2+4) 144 .endif 145 .if .Lruntime_current3_used 146 .Lruntime_instance_\name\()_3: 147 .word _ZN3art7Runtime9instance_E(GOT_PREL)-(.Lload_got_\name\()_3+4) 148 .endif 149 // Remove the RUNTIME_CURRENTx macros so they get rebound in the next function entry. 150 .purgem RUNTIME_CURRENT1 151 .purgem RUNTIME_CURRENT2 152 .purgem RUNTIME_CURRENT3 153 .fnend 154 .cfi_endproc 155 .size \name, .-\name 156.endm 157 158// Declare an unimplemented ENTRY that will halt a debugger. 159.macro UNIMPLEMENTED name 160 ENTRY \name 161 bkpt 162 bkpt 163 END \name 164.endm 165 166// Macro to poison (negate) the reference for heap poisoning. 167.macro POISON_HEAP_REF rRef 168#ifdef USE_HEAP_POISONING 169 rsb \rRef, \rRef, #0 170#endif // USE_HEAP_POISONING 171.endm 172 173// Macro to unpoison (negate) the reference for heap poisoning. 174.macro UNPOISON_HEAP_REF rRef 175#ifdef USE_HEAP_POISONING 176 rsb \rRef, \rRef, #0 177#endif // USE_HEAP_POISONING 178.endm 179 180.macro INCREASE_FRAME frame_adjustment 181 sub sp, sp, #(\frame_adjustment) 182 .cfi_adjust_cfa_offset (\frame_adjustment) 183.endm 184 185.macro DECREASE_FRAME frame_adjustment 186 add sp, sp, #(\frame_adjustment) 187 .cfi_adjust_cfa_offset -(\frame_adjustment) 188.endm 189 190// Macro to refresh the Marking Register (R8). 191// 192// This macro must be called at the end of functions implementing 193// entrypoints that possibly (directly or indirectly) perform a 194// suspend check (before they return). 195.macro REFRESH_MARKING_REGISTER 196#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 197 ldr rMR, [rSELF, #THREAD_IS_GC_MARKING_OFFSET] 198#endif 199.endm 200 201.macro CONDITIONAL_CBZ reg, reg_if, dest 202.ifc \reg, \reg_if 203 cbz \reg, \dest 204.endif 205.endm 206 207.macro CONDITIONAL_CMPBZ reg, reg_if, dest 208.ifc \reg, \reg_if 209 cmp \reg, #0 210 beq \dest 211.endif 212.endm 213 214// Use CBZ if the register is in {r0, r7} otherwise compare and branch. 215.macro SMART_CBZ reg, dest 216 CONDITIONAL_CBZ \reg, r0, \dest 217 CONDITIONAL_CBZ \reg, r1, \dest 218 CONDITIONAL_CBZ \reg, r2, \dest 219 CONDITIONAL_CBZ \reg, r3, \dest 220 CONDITIONAL_CBZ \reg, r4, \dest 221 CONDITIONAL_CBZ \reg, r5, \dest 222 CONDITIONAL_CBZ \reg, r6, \dest 223 CONDITIONAL_CBZ \reg, r7, \dest 224 CONDITIONAL_CMPBZ \reg, r8, \dest 225 CONDITIONAL_CMPBZ \reg, r9, \dest 226 CONDITIONAL_CMPBZ \reg, r10, \dest 227 CONDITIONAL_CMPBZ \reg, r11, \dest 228 CONDITIONAL_CMPBZ \reg, r12, \dest 229 CONDITIONAL_CMPBZ \reg, r13, \dest 230 CONDITIONAL_CMPBZ \reg, r14, \dest 231 CONDITIONAL_CMPBZ \reg, r15, \dest 232.endm 233 234 /* 235 * Macro that sets up the callee save frame to conform with 236 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs), except for storing the method. 237 */ 238.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY 239 // Note: We could avoid saving R8 in the case of Baker read 240 // barriers, as it is overwritten by REFRESH_MARKING_REGISTER 241 // later; but it's not worth handling this special case. 242 push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves and args. 243 .cfi_adjust_cfa_offset 40 244 .cfi_rel_offset r1, 0 245 .cfi_rel_offset r2, 4 246 .cfi_rel_offset r3, 8 247 .cfi_rel_offset r5, 12 248 .cfi_rel_offset r6, 16 249 .cfi_rel_offset r7, 20 250 .cfi_rel_offset r8, 24 251 .cfi_rel_offset r10, 28 252 .cfi_rel_offset r11, 32 253 .cfi_rel_offset lr, 36 254 vpush {s0-s15} @ 16 words of float args. 255 .cfi_adjust_cfa_offset 64 256 sub sp, #8 @ 2 words of space, alignment padding and Method* 257 .cfi_adjust_cfa_offset 8 258 // Ugly compile-time check, but we only have the preprocessor. 259#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 40 + 64 + 8) 260#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(ARM) size not as expected." 261#endif 262.endm 263 264.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME 265 add sp, #8 @ rewind sp 266 .cfi_adjust_cfa_offset -8 267 vpop {s0-s15} 268 .cfi_adjust_cfa_offset -64 269 // Note: Likewise, we could avoid restoring R8 in the case of Baker 270 // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER 271 // later; but it's not worth handling this special case. 272 pop {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves and args. 273 .cfi_restore r1 274 .cfi_restore r2 275 .cfi_restore r3 276 .cfi_restore r5 277 .cfi_restore r6 278 .cfi_restore r7 279 .cfi_restore r8 280 .cfi_restore r10 281 .cfi_restore r11 282 .cfi_restore lr 283 .cfi_adjust_cfa_offset -40 284.endm 285 286 /* 287 * Macro to spill the GPRs. 288 */ 289.macro SPILL_ALL_CALLEE_SAVE_GPRS 290 push {r4-r11, lr} @ 9 words (36 bytes) of callee saves. 291 .cfi_adjust_cfa_offset 36 292 .cfi_rel_offset r4, 0 293 .cfi_rel_offset r5, 4 294 .cfi_rel_offset r6, 8 295 .cfi_rel_offset r7, 12 296 .cfi_rel_offset r8, 16 297 .cfi_rel_offset r9, 20 298 .cfi_rel_offset r10, 24 299 .cfi_rel_offset r11, 28 300 .cfi_rel_offset lr, 32 301.endm 302 303 /* 304 * Macro that sets up the callee save frame to conform with 305 * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves) 306 */ 307.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME rTemp 308 SPILL_ALL_CALLEE_SAVE_GPRS @ 9 words (36 bytes) of callee saves. 309 vpush {s16-s31} @ 16 words (64 bytes) of floats. 310 .cfi_adjust_cfa_offset 64 311 sub sp, #12 @ 3 words of space, bottom word will hold Method* 312 .cfi_adjust_cfa_offset 12 313 RUNTIME_CURRENT1 \rTemp @ Load Runtime::Current into rTemp. 314 @ Load kSaveAllCalleeSaves Method* into rTemp. 315 ldr \rTemp, [\rTemp, #RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET] 316 str \rTemp, [sp, #0] @ Place Method* at bottom of stack. 317 str sp, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET] @ Place sp in Thread::Current()->top_quick_frame. 318 319 // Ugly compile-time check, but we only have the preprocessor. 320#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 36 + 64 + 12) 321#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(ARM) size not as expected." 322#endif 323.endm 324 325 /* 326 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 327 * exception is Thread::Current()->exception_ when the runtime method frame is ready. 328 */ 329.macro DELIVER_PENDING_EXCEPTION_FRAME_READY 330 mov r0, rSELF @ pass Thread::Current 331 bl artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*) 332.endm 333 334 /* 335 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 336 * exception is Thread::Current()->exception_. 337 */ 338.macro DELIVER_PENDING_EXCEPTION 339 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r0 @ save callee saves for throw 340 DELIVER_PENDING_EXCEPTION_FRAME_READY 341.endm 342 343.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg 344 ldr \reg, [rSELF, #THREAD_EXCEPTION_OFFSET] @ Get exception field. 345 cbnz \reg, 1f 346 bx lr 3471: 348 DELIVER_PENDING_EXCEPTION 349.endm 350 351.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_R1 352 RETURN_OR_DELIVER_PENDING_EXCEPTION_REG r1 353.endm 354 355.macro RETURN_OR_DELIVER_PENDING_EXCEPTION 356 ldr ip, [rSELF, #THREAD_EXCEPTION_OFFSET] @ Get exception field. 357 cmp ip, #0 358 bne 1f 359 bx lr 3601: 361 DELIVER_PENDING_EXCEPTION 362.endm 363 364 /* 365 * Macro that sets up the callee save frame to conform with 366 * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly). 367 */ 368.macro SETUP_SAVE_REFS_ONLY_FRAME rTemp 369 // Note: We could avoid saving R8 in the case of Baker read 370 // barriers, as it is overwritten by REFRESH_MARKING_REGISTER 371 // later; but it's not worth handling this special case. 372 push {r5-r8, r10-r11, lr} @ 7 words of callee saves 373 .cfi_adjust_cfa_offset 28 374 .cfi_rel_offset r5, 0 375 .cfi_rel_offset r6, 4 376 .cfi_rel_offset r7, 8 377 .cfi_rel_offset r8, 12 378 .cfi_rel_offset r10, 16 379 .cfi_rel_offset r11, 20 380 .cfi_rel_offset lr, 24 381 sub sp, #4 @ bottom word will hold Method* 382 .cfi_adjust_cfa_offset 4 383 RUNTIME_CURRENT2 \rTemp @ Load Runtime::Current into rTemp. 384 @ Load kSaveRefsOnly Method* into rTemp. 385 ldr \rTemp, [\rTemp, #RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET] 386 str \rTemp, [sp, #0] @ Place Method* at bottom of stack. 387 str sp, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET] @ Place sp in Thread::Current()->top_quick_frame. 388 389 // Ugly compile-time check, but we only have the preprocessor. 390#if (FRAME_SIZE_SAVE_REFS_ONLY != 28 + 4) 391#error "FRAME_SIZE_SAVE_REFS_ONLY(ARM) size not as expected." 392#endif 393.endm 394 395.macro RESTORE_SAVE_REFS_ONLY_FRAME 396 add sp, #4 @ bottom word holds Method* 397 .cfi_adjust_cfa_offset -4 398 // Note: Likewise, we could avoid restoring R8 in the case of Baker 399 // read barriers, as it is overwritten by REFRESH_MARKING_REGISTER 400 // later; but it's not worth handling this special case. 401 pop {r5-r8, r10-r11, lr} @ 7 words of callee saves 402 .cfi_restore r5 403 .cfi_restore r6 404 .cfi_restore r7 405 .cfi_restore r8 406 .cfi_restore r10 407 .cfi_restore r11 408 .cfi_restore lr 409 .cfi_adjust_cfa_offset -28 410.endm 411 412#endif // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_ 413