xref: /rk3399_ARM-atf/include/arch/aarch32/asm_macros.S (revision 2c746960ee9d97fc1e124099fd19e51f4cf0f546)
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