1f5478dedSAntonio Nino Diaz/* 2f5478dedSAntonio Nino Diaz * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. 3f5478dedSAntonio Nino Diaz * 4f5478dedSAntonio Nino Diaz * SPDX-License-Identifier: BSD-3-Clause 5f5478dedSAntonio Nino Diaz */ 6f5478dedSAntonio Nino Diaz#ifndef ASM_MACROS_S 7f5478dedSAntonio Nino Diaz#define ASM_MACROS_S 8f5478dedSAntonio Nino Diaz 9f5478dedSAntonio Nino Diaz#include <arch.h> 10*09d40e0eSAntonio Nino Diaz#include <common/asm_macros_common.S> 11*09d40e0eSAntonio Nino Diaz#include <lib/spinlock.h> 12f5478dedSAntonio Nino Diaz 13f5478dedSAntonio Nino Diaz/* 14f5478dedSAntonio Nino Diaz * TLBI instruction with type specifier that implements the workaround for 15f5478dedSAntonio Nino Diaz * errata 813419 of Cortex-A57. 16f5478dedSAntonio Nino Diaz */ 17f5478dedSAntonio Nino Diaz#if ERRATA_A57_813419 18f5478dedSAntonio Nino Diaz#define TLB_INVALIDATE(_reg, _coproc) \ 19f5478dedSAntonio Nino Diaz stcopr _reg, _coproc; \ 20f5478dedSAntonio Nino Diaz dsb ish; \ 21f5478dedSAntonio Nino Diaz stcopr _reg, _coproc 22f5478dedSAntonio Nino Diaz#else 23f5478dedSAntonio Nino Diaz#define TLB_INVALIDATE(_reg, _coproc) \ 24f5478dedSAntonio Nino Diaz stcopr _reg, _coproc 25f5478dedSAntonio Nino Diaz#endif 26f5478dedSAntonio Nino Diaz 27f5478dedSAntonio Nino Diaz#define WORD_SIZE 4 28f5478dedSAntonio Nino Diaz 29f5478dedSAntonio Nino Diaz /* 30f5478dedSAntonio Nino Diaz * Co processor register accessors 31f5478dedSAntonio Nino Diaz */ 32f5478dedSAntonio Nino Diaz .macro ldcopr reg, coproc, opc1, CRn, CRm, opc2 33f5478dedSAntonio Nino Diaz mrc \coproc, \opc1, \reg, \CRn, \CRm, \opc2 34f5478dedSAntonio Nino Diaz .endm 35f5478dedSAntonio Nino Diaz 36f5478dedSAntonio Nino Diaz .macro ldcopr16 reg1, reg2, coproc, opc1, CRm 37f5478dedSAntonio Nino Diaz mrrc \coproc, \opc1, \reg1, \reg2, \CRm 38f5478dedSAntonio Nino Diaz .endm 39f5478dedSAntonio Nino Diaz 40f5478dedSAntonio Nino Diaz .macro stcopr reg, coproc, opc1, CRn, CRm, opc2 41f5478dedSAntonio Nino Diaz mcr \coproc, \opc1, \reg, \CRn, \CRm, \opc2 42f5478dedSAntonio Nino Diaz .endm 43f5478dedSAntonio Nino Diaz 44f5478dedSAntonio Nino Diaz .macro stcopr16 reg1, reg2, coproc, opc1, CRm 45f5478dedSAntonio Nino Diaz mcrr \coproc, \opc1, \reg1, \reg2, \CRm 46f5478dedSAntonio Nino Diaz .endm 47f5478dedSAntonio Nino Diaz 48f5478dedSAntonio Nino Diaz /* Cache line size helpers */ 49f5478dedSAntonio Nino Diaz .macro dcache_line_size reg, tmp 50f5478dedSAntonio Nino Diaz ldcopr \tmp, CTR 51f5478dedSAntonio Nino Diaz ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH 52f5478dedSAntonio Nino Diaz mov \reg, #WORD_SIZE 53f5478dedSAntonio Nino Diaz lsl \reg, \reg, \tmp 54f5478dedSAntonio Nino Diaz .endm 55f5478dedSAntonio Nino Diaz 56f5478dedSAntonio Nino Diaz .macro icache_line_size reg, tmp 57f5478dedSAntonio Nino Diaz ldcopr \tmp, CTR 58f5478dedSAntonio Nino Diaz and \tmp, \tmp, #CTR_IMINLINE_MASK 59f5478dedSAntonio Nino Diaz mov \reg, #WORD_SIZE 60f5478dedSAntonio Nino Diaz lsl \reg, \reg, \tmp 61f5478dedSAntonio Nino Diaz .endm 62f5478dedSAntonio Nino Diaz 63f5478dedSAntonio Nino Diaz /* 64f5478dedSAntonio Nino Diaz * Declare the exception vector table, enforcing it is aligned on a 65f5478dedSAntonio Nino Diaz * 32 byte boundary. 66f5478dedSAntonio Nino Diaz */ 67f5478dedSAntonio Nino Diaz .macro vector_base label 68f5478dedSAntonio Nino Diaz .section .vectors, "ax" 69f5478dedSAntonio Nino Diaz .align 5 70f5478dedSAntonio Nino Diaz \label: 71f5478dedSAntonio Nino Diaz .endm 72f5478dedSAntonio Nino Diaz 73f5478dedSAntonio Nino Diaz /* 74f5478dedSAntonio Nino Diaz * This macro calculates the base address of the current CPU's multi 75f5478dedSAntonio Nino Diaz * processor(MP) stack using the plat_my_core_pos() index, the name of 76f5478dedSAntonio Nino Diaz * the stack storage and the size of each stack. 77f5478dedSAntonio Nino Diaz * Out: r0 = physical address of stack base 78f5478dedSAntonio Nino Diaz * Clobber: r14, r1, r2 79f5478dedSAntonio Nino Diaz */ 80f5478dedSAntonio Nino Diaz .macro get_my_mp_stack _name, _size 81f5478dedSAntonio Nino Diaz bl plat_my_core_pos 82f5478dedSAntonio Nino Diaz ldr r2, =(\_name + \_size) 83f5478dedSAntonio Nino Diaz mov r1, #\_size 84f5478dedSAntonio Nino Diaz mla r0, r0, r1, r2 85f5478dedSAntonio Nino Diaz .endm 86f5478dedSAntonio Nino Diaz 87f5478dedSAntonio Nino Diaz /* 88f5478dedSAntonio Nino Diaz * This macro calculates the base address of a uniprocessor(UP) stack 89f5478dedSAntonio Nino Diaz * using the name of the stack storage and the size of the stack 90f5478dedSAntonio Nino Diaz * Out: r0 = physical address of stack base 91f5478dedSAntonio Nino Diaz */ 92f5478dedSAntonio Nino Diaz .macro get_up_stack _name, _size 93f5478dedSAntonio Nino Diaz ldr r0, =(\_name + \_size) 94f5478dedSAntonio Nino Diaz .endm 95f5478dedSAntonio Nino Diaz 96f5478dedSAntonio Nino Diaz#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) 97f5478dedSAntonio Nino Diaz /* 98f5478dedSAntonio Nino Diaz * ARMv7 cores without Virtualization extension do not support the 99f5478dedSAntonio Nino Diaz * eret instruction. 100f5478dedSAntonio Nino Diaz */ 101f5478dedSAntonio Nino Diaz .macro eret 102f5478dedSAntonio Nino Diaz movs pc, lr 103f5478dedSAntonio Nino Diaz .endm 104f5478dedSAntonio Nino Diaz#endif 105f5478dedSAntonio Nino Diaz 106f5478dedSAntonio Nino Diaz#if (ARM_ARCH_MAJOR == 7) 107f5478dedSAntonio Nino Diaz /* ARMv7 does not support stl instruction */ 108f5478dedSAntonio Nino Diaz .macro stl _reg, _write_lock 109f5478dedSAntonio Nino Diaz dmb 110f5478dedSAntonio Nino Diaz str \_reg, \_write_lock 111f5478dedSAntonio Nino Diaz dsb 112f5478dedSAntonio Nino Diaz .endm 113f5478dedSAntonio Nino Diaz#endif 114f5478dedSAntonio Nino Diaz 115f5478dedSAntonio Nino Diaz /* 116f5478dedSAntonio Nino Diaz * Helper macro to generate the best mov/movw/movt combinations 117f5478dedSAntonio Nino Diaz * according to the value to be moved. 118f5478dedSAntonio Nino Diaz */ 119f5478dedSAntonio Nino Diaz .macro mov_imm _reg, _val 120f5478dedSAntonio Nino Diaz .if ((\_val) & 0xffff0000) == 0 121f5478dedSAntonio Nino Diaz mov \_reg, #(\_val) 122f5478dedSAntonio Nino Diaz .else 123f5478dedSAntonio Nino Diaz movw \_reg, #((\_val) & 0xffff) 124f5478dedSAntonio Nino Diaz movt \_reg, #((\_val) >> 16) 125f5478dedSAntonio Nino Diaz .endif 126f5478dedSAntonio Nino Diaz .endm 127f5478dedSAntonio Nino Diaz 128f5478dedSAntonio Nino Diaz /* 129f5478dedSAntonio Nino Diaz * Macro to mark instances where we're jumping to a function and don't 130f5478dedSAntonio Nino Diaz * expect a return. To provide the function being jumped to with 131f5478dedSAntonio Nino Diaz * additional information, we use 'bl' instruction to jump rather than 132f5478dedSAntonio Nino Diaz * 'b'. 133f5478dedSAntonio Nino Diaz * 134f5478dedSAntonio Nino Diaz * Debuggers infer the location of a call from where LR points to, which 135f5478dedSAntonio Nino Diaz * is usually the instruction after 'bl'. If this macro expansion 136f5478dedSAntonio Nino Diaz * happens to be the last location in a function, that'll cause the LR 137f5478dedSAntonio Nino Diaz * to point a location beyond the function, thereby misleading debugger 138f5478dedSAntonio Nino Diaz * back trace. We therefore insert a 'nop' after the function call for 139f5478dedSAntonio Nino Diaz * debug builds, unless 'skip_nop' parameter is non-zero. 140f5478dedSAntonio Nino Diaz */ 141f5478dedSAntonio Nino Diaz .macro no_ret _func:req, skip_nop=0 142f5478dedSAntonio Nino Diaz bl \_func 143f5478dedSAntonio Nino Diaz#if DEBUG 144f5478dedSAntonio Nino Diaz .ifeq \skip_nop 145f5478dedSAntonio Nino Diaz nop 146f5478dedSAntonio Nino Diaz .endif 147f5478dedSAntonio Nino Diaz#endif 148f5478dedSAntonio Nino Diaz .endm 149f5478dedSAntonio Nino Diaz 150f5478dedSAntonio Nino Diaz /* 151f5478dedSAntonio Nino Diaz * Reserve space for a spin lock in assembly file. 152f5478dedSAntonio Nino Diaz */ 153f5478dedSAntonio Nino Diaz .macro define_asm_spinlock _name:req 154f5478dedSAntonio Nino Diaz .align SPINLOCK_ASM_ALIGN 155f5478dedSAntonio Nino Diaz \_name: 156f5478dedSAntonio Nino Diaz .space SPINLOCK_ASM_SIZE 157f5478dedSAntonio Nino Diaz .endm 158f5478dedSAntonio Nino Diaz 159f5478dedSAntonio Nino Diaz /* 160f5478dedSAntonio Nino Diaz * Helper macro to OR the bottom 32 bits of `_val` into `_reg_l` 161f5478dedSAntonio Nino Diaz * and the top 32 bits of `_val` into `_reg_h`. If either the bottom 162f5478dedSAntonio Nino Diaz * or top word of `_val` is zero, the corresponding OR operation 163f5478dedSAntonio Nino Diaz * is skipped. 164f5478dedSAntonio Nino Diaz */ 165f5478dedSAntonio Nino Diaz .macro orr64_imm _reg_l, _reg_h, _val 166f5478dedSAntonio Nino Diaz .if (\_val >> 32) 167f5478dedSAntonio Nino Diaz orr \_reg_h, \_reg_h, #(\_val >> 32) 168f5478dedSAntonio Nino Diaz .endif 169f5478dedSAntonio Nino Diaz .if (\_val & 0xffffffff) 170f5478dedSAntonio Nino Diaz orr \_reg_l, \_reg_l, #(\_val & 0xffffffff) 171f5478dedSAntonio Nino Diaz .endif 172f5478dedSAntonio Nino Diaz .endm 173f5478dedSAntonio Nino Diaz 174f5478dedSAntonio Nino Diaz /* 175f5478dedSAntonio Nino Diaz * Helper macro to bitwise-clear bits in `_reg_l` and 176f5478dedSAntonio Nino Diaz * `_reg_h` given a 64 bit immediate `_val`. The set bits 177f5478dedSAntonio Nino Diaz * in the bottom word of `_val` dictate which bits from 178f5478dedSAntonio Nino Diaz * `_reg_l` should be cleared. Similarly, the set bits in 179f5478dedSAntonio Nino Diaz * the top word of `_val` dictate which bits from `_reg_h` 180f5478dedSAntonio Nino Diaz * should be cleared. If either the bottom or top word of 181f5478dedSAntonio Nino Diaz * `_val` is zero, the corresponding BIC operation is skipped. 182f5478dedSAntonio Nino Diaz */ 183f5478dedSAntonio Nino Diaz .macro bic64_imm _reg_l, _reg_h, _val 184f5478dedSAntonio Nino Diaz .if (\_val >> 32) 185f5478dedSAntonio Nino Diaz bic \_reg_h, \_reg_h, #(\_val >> 32) 186f5478dedSAntonio Nino Diaz .endif 187f5478dedSAntonio Nino Diaz .if (\_val & 0xffffffff) 188f5478dedSAntonio Nino Diaz bic \_reg_l, \_reg_l, #(\_val & 0xffffffff) 189f5478dedSAntonio Nino Diaz .endif 190f5478dedSAntonio Nino Diaz .endm 191f5478dedSAntonio Nino Diaz 192f5478dedSAntonio Nino Diaz#endif /* ASM_MACROS_S */ 193