1/* 2 * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6#ifndef __ASM_MACROS_S__ 7#define __ASM_MACROS_S__ 8 9#include <arch.h> 10#include <asm_macros_common.S> 11#include <spinlock.h> 12 13 14 .macro func_prologue 15 stp x29, x30, [sp, #-0x10]! 16 mov x29,sp 17 .endm 18 19 .macro func_epilogue 20 ldp x29, x30, [sp], #0x10 21 .endm 22 23 24 .macro dcache_line_size reg, tmp 25 mrs \tmp, ctr_el0 26 ubfx \tmp, \tmp, #16, #4 27 mov \reg, #4 28 lsl \reg, \reg, \tmp 29 .endm 30 31 32 .macro icache_line_size reg, tmp 33 mrs \tmp, ctr_el0 34 and \tmp, \tmp, #0xf 35 mov \reg, #4 36 lsl \reg, \reg, \tmp 37 .endm 38 39 40 .macro smc_check label 41 mrs x0, esr_el3 42 ubfx x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH 43 cmp x0, #EC_AARCH64_SMC 44 b.ne $label 45 .endm 46 47 /* 48 * Declare the exception vector table, enforcing it is aligned on a 49 * 2KB boundary, as required by the ARMv8 architecture. 50 * Use zero bytes as the fill value to be stored in the padding bytes 51 * so that it inserts illegal AArch64 instructions. This increases 52 * security, robustness and potentially facilitates debugging. 53 */ 54 .macro vector_base label 55 .section .vectors, "ax" 56 .align 11, 0 57 \label: 58 .endm 59 60 /* 61 * Create an entry in the exception vector table, enforcing it is 62 * aligned on a 128-byte boundary, as required by the ARMv8 architecture. 63 * Use zero bytes as the fill value to be stored in the padding bytes 64 * so that it inserts illegal AArch64 instructions. This increases 65 * security, robustness and potentially facilitates debugging. 66 */ 67 .macro vector_entry label 68 .cfi_sections .debug_frame 69 .section .vectors, "ax" 70 .align 7, 0 71 .type \label, %function 72 .func \label 73 .cfi_startproc 74 \label: 75 .endm 76 77 /* 78 * This macro verifies that the given vector doesn't exceed the 79 * architectural limit of 32 instructions. This is meant to be placed 80 * immediately after the last instruction in the vector. It takes the 81 * vector entry as the parameter 82 */ 83 .macro check_vector_size since 84 .endfunc 85 .cfi_endproc 86 .if (. - \since) > (32 * 4) 87 .error "Vector exceeds 32 instructions" 88 .endif 89 .endm 90 91#if ENABLE_PLAT_COMPAT 92 /* 93 * This macro calculates the base address of an MP stack using the 94 * platform_get_core_pos() index, the name of the stack storage and 95 * the size of each stack 96 * In: X0 = MPIDR of CPU whose stack is wanted 97 * Out: X0 = physical address of stack base 98 * Clobber: X30, X1, X2 99 */ 100 .macro get_mp_stack _name, _size 101 bl platform_get_core_pos 102 ldr x2, =(\_name + \_size) 103 mov x1, #\_size 104 madd x0, x0, x1, x2 105 .endm 106#endif 107 108 /* 109 * This macro calculates the base address of the current CPU's MP stack 110 * using the plat_my_core_pos() index, the name of the stack storage 111 * and the size of each stack 112 * Out: X0 = physical address of stack base 113 * Clobber: X30, X1, X2 114 */ 115 .macro get_my_mp_stack _name, _size 116 bl plat_my_core_pos 117 ldr x2, =(\_name + \_size) 118 mov x1, #\_size 119 madd x0, x0, x1, x2 120 .endm 121 122 /* 123 * This macro calculates the base address of a UP stack using the 124 * name of the stack storage and the size of the stack 125 * Out: X0 = physical address of stack base 126 */ 127 .macro get_up_stack _name, _size 128 ldr x0, =(\_name + \_size) 129 .endm 130 131 /* 132 * Helper macro to generate the best mov/movk combinations according 133 * the value to be moved. The 16 bits from '_shift' are tested and 134 * if not zero, they are moved into '_reg' without affecting 135 * other bits. 136 */ 137 .macro _mov_imm16 _reg, _val, _shift 138 .if (\_val >> \_shift) & 0xffff 139 .if (\_val & (1 << \_shift - 1)) 140 movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift 141 .else 142 mov \_reg, \_val & (0xffff << \_shift) 143 .endif 144 .endif 145 .endm 146 147 /* 148 * Helper macro to load arbitrary values into 32 or 64-bit registers 149 * which generates the best mov/movk combinations. Many base addresses 150 * are 64KB aligned the macro will eliminate updating bits 15:0 in 151 * that case 152 */ 153 .macro mov_imm _reg, _val 154 .if (\_val) == 0 155 mov \_reg, #0 156 .else 157 _mov_imm16 \_reg, (\_val), 0 158 _mov_imm16 \_reg, (\_val), 16 159 _mov_imm16 \_reg, (\_val), 32 160 _mov_imm16 \_reg, (\_val), 48 161 .endif 162 .endm 163 164 /* 165 * Macro to mark instances where we're jumping to a function and don't 166 * expect a return. To provide the function being jumped to with 167 * additional information, we use 'bl' instruction to jump rather than 168 * 'b'. 169 * 170 * Debuggers infer the location of a call from where LR points to, which 171 * is usually the instruction after 'bl'. If this macro expansion 172 * happens to be the last location in a function, that'll cause the LR 173 * to point a location beyond the function, thereby misleading debugger 174 * back trace. We therefore insert a 'nop' after the function call for 175 * debug builds, unless 'skip_nop' parameter is non-zero. 176 */ 177 .macro no_ret _func:req, skip_nop=0 178 bl \_func 179#if DEBUG 180 .ifeq \skip_nop 181 nop 182 .endif 183#endif 184 .endm 185 186 /* 187 * Reserve space for a spin lock in assembly file. 188 */ 189 .macro define_asm_spinlock _name:req 190 .align SPINLOCK_ASM_ALIGN 191 \_name: 192 .space SPINLOCK_ASM_SIZE 193 .endm 194 195#endif /* __ASM_MACROS_S__ */ 196