1f5478dedSAntonio Nino Diaz/* 2007433d8SBoyan Karatotev * Copyright (c) 2016-2023, 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> 1009d40e0eSAntonio Nino Diaz#include <common/asm_macros_common.S> 11007433d8SBoyan Karatotev#include <lib/cpus/cpu_ops.h> 1209d40e0eSAntonio Nino Diaz#include <lib/spinlock.h> 13f5478dedSAntonio Nino Diaz 14f5478dedSAntonio Nino Diaz/* 15f5478dedSAntonio Nino Diaz * TLBI instruction with type specifier that implements the workaround for 16f5478dedSAntonio Nino Diaz * errata 813419 of Cortex-A57. 17f5478dedSAntonio Nino Diaz */ 18f5478dedSAntonio Nino Diaz#if ERRATA_A57_813419 19f5478dedSAntonio Nino Diaz#define TLB_INVALIDATE(_reg, _coproc) \ 20f5478dedSAntonio Nino Diaz stcopr _reg, _coproc; \ 21f5478dedSAntonio Nino Diaz dsb ish; \ 22f5478dedSAntonio Nino Diaz stcopr _reg, _coproc 23f5478dedSAntonio Nino Diaz#else 24f5478dedSAntonio Nino Diaz#define TLB_INVALIDATE(_reg, _coproc) \ 25f5478dedSAntonio Nino Diaz stcopr _reg, _coproc 26f5478dedSAntonio Nino Diaz#endif 27f5478dedSAntonio Nino Diaz 28f5478dedSAntonio Nino Diaz /* 29f5478dedSAntonio Nino Diaz * Co processor register accessors 30f5478dedSAntonio Nino Diaz */ 31f5478dedSAntonio Nino Diaz .macro ldcopr reg, coproc, opc1, CRn, CRm, opc2 32f5478dedSAntonio Nino Diaz mrc \coproc, \opc1, \reg, \CRn, \CRm, \opc2 33f5478dedSAntonio Nino Diaz .endm 34f5478dedSAntonio Nino Diaz 35f5478dedSAntonio Nino Diaz .macro ldcopr16 reg1, reg2, coproc, opc1, CRm 36f5478dedSAntonio Nino Diaz mrrc \coproc, \opc1, \reg1, \reg2, \CRm 37f5478dedSAntonio Nino Diaz .endm 38f5478dedSAntonio Nino Diaz 39f5478dedSAntonio Nino Diaz .macro stcopr reg, coproc, opc1, CRn, CRm, opc2 40f5478dedSAntonio Nino Diaz mcr \coproc, \opc1, \reg, \CRn, \CRm, \opc2 41f5478dedSAntonio Nino Diaz .endm 42f5478dedSAntonio Nino Diaz 43f5478dedSAntonio Nino Diaz .macro stcopr16 reg1, reg2, coproc, opc1, CRm 44f5478dedSAntonio Nino Diaz mcrr \coproc, \opc1, \reg1, \reg2, \CRm 45f5478dedSAntonio Nino Diaz .endm 46f5478dedSAntonio Nino Diaz 47f5478dedSAntonio Nino Diaz /* Cache line size helpers */ 48f5478dedSAntonio Nino Diaz .macro dcache_line_size reg, tmp 49f5478dedSAntonio Nino Diaz ldcopr \tmp, CTR 50f5478dedSAntonio Nino Diaz ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH 51007433d8SBoyan Karatotev mov \reg, #CPU_WORD_SIZE 52f5478dedSAntonio Nino Diaz lsl \reg, \reg, \tmp 53f5478dedSAntonio Nino Diaz .endm 54f5478dedSAntonio Nino Diaz 55f5478dedSAntonio Nino Diaz .macro icache_line_size reg, tmp 56f5478dedSAntonio Nino Diaz ldcopr \tmp, CTR 57f5478dedSAntonio Nino Diaz and \tmp, \tmp, #CTR_IMINLINE_MASK 58007433d8SBoyan Karatotev mov \reg, #CPU_WORD_SIZE 59f5478dedSAntonio Nino Diaz lsl \reg, \reg, \tmp 60f5478dedSAntonio Nino Diaz .endm 61f5478dedSAntonio Nino Diaz 62f5478dedSAntonio Nino Diaz /* 63f5478dedSAntonio Nino Diaz * Declare the exception vector table, enforcing it is aligned on a 64f5478dedSAntonio Nino Diaz * 32 byte boundary. 65f5478dedSAntonio Nino Diaz */ 66f5478dedSAntonio Nino Diaz .macro vector_base label 67f5478dedSAntonio Nino Diaz .section .vectors, "ax" 68f5478dedSAntonio Nino Diaz .align 5 69f5478dedSAntonio Nino Diaz \label: 70f5478dedSAntonio Nino Diaz .endm 71f5478dedSAntonio Nino Diaz 72f5478dedSAntonio Nino Diaz /* 73f5478dedSAntonio Nino Diaz * This macro calculates the base address of the current CPU's multi 74f5478dedSAntonio Nino Diaz * processor(MP) stack using the plat_my_core_pos() index, the name of 75f5478dedSAntonio Nino Diaz * the stack storage and the size of each stack. 76f5478dedSAntonio Nino Diaz * Out: r0 = physical address of stack base 77f5478dedSAntonio Nino Diaz * Clobber: r14, r1, r2 78f5478dedSAntonio Nino Diaz */ 79f5478dedSAntonio Nino Diaz .macro get_my_mp_stack _name, _size 80f5478dedSAntonio Nino Diaz bl plat_my_core_pos 81f5478dedSAntonio Nino Diaz ldr r2, =(\_name + \_size) 82f5478dedSAntonio Nino Diaz mov r1, #\_size 83f5478dedSAntonio Nino Diaz mla r0, r0, r1, r2 84f5478dedSAntonio Nino Diaz .endm 85f5478dedSAntonio Nino Diaz 86f5478dedSAntonio Nino Diaz /* 87f5478dedSAntonio Nino Diaz * This macro calculates the base address of a uniprocessor(UP) stack 88f5478dedSAntonio Nino Diaz * using the name of the stack storage and the size of the stack 89f5478dedSAntonio Nino Diaz * Out: r0 = physical address of stack base 90f5478dedSAntonio Nino Diaz */ 91f5478dedSAntonio Nino Diaz .macro get_up_stack _name, _size 92f5478dedSAntonio Nino Diaz ldr r0, =(\_name + \_size) 93f5478dedSAntonio Nino Diaz .endm 94f5478dedSAntonio Nino Diaz 95f5478dedSAntonio Nino Diaz#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) 96f5478dedSAntonio Nino Diaz /* 976bc24382SMadhukar Pappireddy * Macro for mitigating against speculative execution. 98f5478dedSAntonio Nino Diaz * ARMv7 cores without Virtualization extension do not support the 99f5478dedSAntonio Nino Diaz * eret instruction. 100f5478dedSAntonio Nino Diaz */ 1016bc24382SMadhukar Pappireddy .macro exception_return 102f5478dedSAntonio Nino Diaz movs pc, lr 1036bc24382SMadhukar Pappireddy dsb nsh 1046bc24382SMadhukar Pappireddy isb 1056bc24382SMadhukar Pappireddy .endm 1066bc24382SMadhukar Pappireddy 1076bc24382SMadhukar Pappireddy#else 1086bc24382SMadhukar Pappireddy /* 1094e04478aSChris Kay * Macro for mitigating against speculative execution beyond ERET. Uses the 1104e04478aSChris Kay * speculation barrier instruction introduced by FEAT_SB, if it's enabled. 1116bc24382SMadhukar Pappireddy */ 1126bc24382SMadhukar Pappireddy .macro exception_return 1136bc24382SMadhukar Pappireddy eret 1144e04478aSChris Kay#if ENABLE_FEAT_SB 115ccfb5c81SMadhukar Pappireddy sb 116ccfb5c81SMadhukar Pappireddy#else 1176bc24382SMadhukar Pappireddy dsb nsh 1186bc24382SMadhukar Pappireddy isb 119ccfb5c81SMadhukar Pappireddy#endif 120f5478dedSAntonio Nino Diaz .endm 121f5478dedSAntonio Nino Diaz#endif 122f5478dedSAntonio Nino Diaz 1236597fcf1SManish Pandey /* Macro for error synchronization */ 1246597fcf1SManish Pandey .macro synchronize_errors 1256597fcf1SManish Pandey /* Complete any stores that may return an abort */ 1266597fcf1SManish Pandey dsb sy 1276597fcf1SManish Pandey /* Synchronise the CPU context with the completion of the dsb */ 1286597fcf1SManish Pandey isb 1296597fcf1SManish Pandey .endm 1306597fcf1SManish Pandey 131f5478dedSAntonio Nino Diaz#if (ARM_ARCH_MAJOR == 7) 132f5478dedSAntonio Nino Diaz /* ARMv7 does not support stl instruction */ 133f5478dedSAntonio Nino Diaz .macro stl _reg, _write_lock 134f5478dedSAntonio Nino Diaz dmb 135f5478dedSAntonio Nino Diaz str \_reg, \_write_lock 136f5478dedSAntonio Nino Diaz dsb 137f5478dedSAntonio Nino Diaz .endm 138f5478dedSAntonio Nino Diaz#endif 139f5478dedSAntonio Nino Diaz 140f5478dedSAntonio Nino Diaz /* 141f5478dedSAntonio Nino Diaz * Helper macro to generate the best mov/movw/movt combinations 142f5478dedSAntonio Nino Diaz * according to the value to be moved. 143f5478dedSAntonio Nino Diaz */ 144f5478dedSAntonio Nino Diaz .macro mov_imm _reg, _val 145f5478dedSAntonio Nino Diaz .if ((\_val) & 0xffff0000) == 0 146f5478dedSAntonio Nino Diaz mov \_reg, #(\_val) 147f5478dedSAntonio Nino Diaz .else 148f5478dedSAntonio Nino Diaz movw \_reg, #((\_val) & 0xffff) 149f5478dedSAntonio Nino Diaz movt \_reg, #((\_val) >> 16) 150f5478dedSAntonio Nino Diaz .endif 151f5478dedSAntonio Nino Diaz .endm 152f5478dedSAntonio Nino Diaz 153f5478dedSAntonio Nino Diaz /* 154f5478dedSAntonio Nino Diaz * Macro to mark instances where we're jumping to a function and don't 155f5478dedSAntonio Nino Diaz * expect a return. To provide the function being jumped to with 156f5478dedSAntonio Nino Diaz * additional information, we use 'bl' instruction to jump rather than 157f5478dedSAntonio Nino Diaz * 'b'. 158f5478dedSAntonio Nino Diaz * 159f5478dedSAntonio Nino Diaz * Debuggers infer the location of a call from where LR points to, which 160f5478dedSAntonio Nino Diaz * is usually the instruction after 'bl'. If this macro expansion 161f5478dedSAntonio Nino Diaz * happens to be the last location in a function, that'll cause the LR 162f5478dedSAntonio Nino Diaz * to point a location beyond the function, thereby misleading debugger 163f5478dedSAntonio Nino Diaz * back trace. We therefore insert a 'nop' after the function call for 164f5478dedSAntonio Nino Diaz * debug builds, unless 'skip_nop' parameter is non-zero. 165f5478dedSAntonio Nino Diaz */ 166f5478dedSAntonio Nino Diaz .macro no_ret _func:req, skip_nop=0 167f5478dedSAntonio Nino Diaz bl \_func 168f5478dedSAntonio Nino Diaz#if DEBUG 169f5478dedSAntonio Nino Diaz .ifeq \skip_nop 170f5478dedSAntonio Nino Diaz nop 171f5478dedSAntonio Nino Diaz .endif 172f5478dedSAntonio Nino Diaz#endif 173f5478dedSAntonio Nino Diaz .endm 174f5478dedSAntonio Nino Diaz 175f5478dedSAntonio Nino Diaz /* 176f5478dedSAntonio Nino Diaz * Reserve space for a spin lock in assembly file. 177f5478dedSAntonio Nino Diaz */ 178f5478dedSAntonio Nino Diaz .macro define_asm_spinlock _name:req 179f5478dedSAntonio Nino Diaz .align SPINLOCK_ASM_ALIGN 180f5478dedSAntonio Nino Diaz \_name: 181f5478dedSAntonio Nino Diaz .space SPINLOCK_ASM_SIZE 182f5478dedSAntonio Nino Diaz .endm 183f5478dedSAntonio Nino Diaz 184f5478dedSAntonio Nino Diaz /* 185f5478dedSAntonio Nino Diaz * Helper macro to OR the bottom 32 bits of `_val` into `_reg_l` 186f5478dedSAntonio Nino Diaz * and the top 32 bits of `_val` into `_reg_h`. If either the bottom 187f5478dedSAntonio Nino Diaz * or top word of `_val` is zero, the corresponding OR operation 188f5478dedSAntonio Nino Diaz * is skipped. 189f5478dedSAntonio Nino Diaz */ 190f5478dedSAntonio Nino Diaz .macro orr64_imm _reg_l, _reg_h, _val 191f5478dedSAntonio Nino Diaz .if (\_val >> 32) 192f5478dedSAntonio Nino Diaz orr \_reg_h, \_reg_h, #(\_val >> 32) 193f5478dedSAntonio Nino Diaz .endif 194f5478dedSAntonio Nino Diaz .if (\_val & 0xffffffff) 195f5478dedSAntonio Nino Diaz orr \_reg_l, \_reg_l, #(\_val & 0xffffffff) 196f5478dedSAntonio Nino Diaz .endif 197f5478dedSAntonio Nino Diaz .endm 198f5478dedSAntonio Nino Diaz 199f5478dedSAntonio Nino Diaz /* 200f5478dedSAntonio Nino Diaz * Helper macro to bitwise-clear bits in `_reg_l` and 201f5478dedSAntonio Nino Diaz * `_reg_h` given a 64 bit immediate `_val`. The set bits 202f5478dedSAntonio Nino Diaz * in the bottom word of `_val` dictate which bits from 203f5478dedSAntonio Nino Diaz * `_reg_l` should be cleared. Similarly, the set bits in 204f5478dedSAntonio Nino Diaz * the top word of `_val` dictate which bits from `_reg_h` 205f5478dedSAntonio Nino Diaz * should be cleared. If either the bottom or top word of 206f5478dedSAntonio Nino Diaz * `_val` is zero, the corresponding BIC operation is skipped. 207f5478dedSAntonio Nino Diaz */ 208f5478dedSAntonio Nino Diaz .macro bic64_imm _reg_l, _reg_h, _val 209f5478dedSAntonio Nino Diaz .if (\_val >> 32) 210f5478dedSAntonio Nino Diaz bic \_reg_h, \_reg_h, #(\_val >> 32) 211f5478dedSAntonio Nino Diaz .endif 212f5478dedSAntonio Nino Diaz .if (\_val & 0xffffffff) 213f5478dedSAntonio Nino Diaz bic \_reg_l, \_reg_l, #(\_val & 0xffffffff) 214f5478dedSAntonio Nino Diaz .endif 215f5478dedSAntonio Nino Diaz .endm 216f5478dedSAntonio Nino Diaz 217a5aa25afSUsama Arif /* 218a5aa25afSUsama Arif * Helper macro for carrying out division in software when 219a5aa25afSUsama Arif * hardware division is not suported. \top holds the dividend 220a5aa25afSUsama Arif * in the function call and the remainder after 221a5aa25afSUsama Arif * the function is executed. \bot holds the divisor. \div holds 222a5aa25afSUsama Arif * the quotient and \temp is a temporary registed used in calcualtion. 223a5aa25afSUsama Arif * The division algorithm has been obtained from: 224a5aa25afSUsama Arif * http://www.keil.com/support/man/docs/armasm/armasm_dom1359731155623.htm 225a5aa25afSUsama Arif */ 226a5aa25afSUsama Arif .macro softudiv div:req,top:req,bot:req,temp:req 227a5aa25afSUsama Arif 228a5aa25afSUsama Arif mov \temp, \bot 229a5aa25afSUsama Arif cmp \temp, \top, lsr #1 230a5aa25afSUsama Arifdiv1: 231a5aa25afSUsama Arif movls \temp, \temp, lsl #1 232a5aa25afSUsama Arif cmp \temp, \top, lsr #1 233a5aa25afSUsama Arif bls div1 234a5aa25afSUsama Arif mov \div, #0 235a5aa25afSUsama Arif 236a5aa25afSUsama Arifdiv2: 237a5aa25afSUsama Arif cmp \top, \temp 238a5aa25afSUsama Arif subcs \top, \top,\temp 239a5aa25afSUsama Arif ADC \div, \div, \div 240a5aa25afSUsama Arif mov \temp, \temp, lsr #1 241a5aa25afSUsama Arif cmp \temp, \bot 242a5aa25afSUsama Arif bhs div2 243a5aa25afSUsama Arif .endm 244*31857d4cSHsin-Hsiung Wang 245*31857d4cSHsin-Hsiung Wang /* 246*31857d4cSHsin-Hsiung Wang * Helper macro to instruction adr <reg>, <symbol> where <symbol> is 247*31857d4cSHsin-Hsiung Wang * within the range +/- 4 GB. 248*31857d4cSHsin-Hsiung Wang */ 249*31857d4cSHsin-Hsiung Wang .macro adr_l, dst, sym 250*31857d4cSHsin-Hsiung Wang adrp \dst, \sym 251*31857d4cSHsin-Hsiung Wang add \dst, \dst, :lo12:\sym 252*31857d4cSHsin-Hsiung Wang .endm 253f5478dedSAntonio Nino Diaz#endif /* ASM_MACROS_S */ 254