xref: /rk3399_ARM-atf/include/arch/aarch32/asm_macros.S (revision ccfb5c81349c3a10ac78741e598e80e416a811c3)
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>
1009d40e0eSAntonio Nino Diaz#include <common/asm_macros_common.S>
1109d40e0eSAntonio 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	/*
986bc24382SMadhukar Pappireddy	 * Macro for mitigating against speculative execution.
99f5478dedSAntonio Nino Diaz	 * ARMv7 cores without Virtualization extension do not support the
100f5478dedSAntonio Nino Diaz	 * eret instruction.
101f5478dedSAntonio Nino Diaz	 */
1026bc24382SMadhukar Pappireddy	.macro exception_return
103f5478dedSAntonio Nino Diaz	movs	pc, lr
1046bc24382SMadhukar Pappireddy	dsb	nsh
1056bc24382SMadhukar Pappireddy	isb
1066bc24382SMadhukar Pappireddy	.endm
1076bc24382SMadhukar Pappireddy
1086bc24382SMadhukar Pappireddy#else
1096bc24382SMadhukar Pappireddy	/*
1106bc24382SMadhukar Pappireddy	 * Macro for mitigating against speculative execution beyond ERET.
111*ccfb5c81SMadhukar Pappireddy	 * If possible use Speculation Barrier instruction defined in ARMv8.5
1126bc24382SMadhukar Pappireddy	 */
1136bc24382SMadhukar Pappireddy	.macro exception_return
1146bc24382SMadhukar Pappireddy	eret
115*ccfb5c81SMadhukar Pappireddy#if ARM_ARCH_AT_LEAST(8, 5)
116*ccfb5c81SMadhukar Pappireddy	sb
117*ccfb5c81SMadhukar Pappireddy#else
1186bc24382SMadhukar Pappireddy	dsb	nsh
1196bc24382SMadhukar Pappireddy	isb
120*ccfb5c81SMadhukar Pappireddy#endif
121f5478dedSAntonio Nino Diaz	.endm
122f5478dedSAntonio Nino Diaz#endif
123f5478dedSAntonio Nino Diaz
124f5478dedSAntonio Nino Diaz#if (ARM_ARCH_MAJOR == 7)
125f5478dedSAntonio Nino Diaz	/* ARMv7 does not support stl instruction */
126f5478dedSAntonio Nino Diaz	.macro stl _reg, _write_lock
127f5478dedSAntonio Nino Diaz	dmb
128f5478dedSAntonio Nino Diaz	str	\_reg, \_write_lock
129f5478dedSAntonio Nino Diaz	dsb
130f5478dedSAntonio Nino Diaz	.endm
131f5478dedSAntonio Nino Diaz#endif
132f5478dedSAntonio Nino Diaz
133f5478dedSAntonio Nino Diaz	/*
134f5478dedSAntonio Nino Diaz	 * Helper macro to generate the best mov/movw/movt combinations
135f5478dedSAntonio Nino Diaz	 * according to the value to be moved.
136f5478dedSAntonio Nino Diaz	 */
137f5478dedSAntonio Nino Diaz	.macro mov_imm _reg, _val
138f5478dedSAntonio Nino Diaz		.if ((\_val) & 0xffff0000) == 0
139f5478dedSAntonio Nino Diaz			mov	\_reg, #(\_val)
140f5478dedSAntonio Nino Diaz		.else
141f5478dedSAntonio Nino Diaz			movw	\_reg, #((\_val) & 0xffff)
142f5478dedSAntonio Nino Diaz			movt	\_reg, #((\_val) >> 16)
143f5478dedSAntonio Nino Diaz		.endif
144f5478dedSAntonio Nino Diaz	.endm
145f5478dedSAntonio Nino Diaz
146f5478dedSAntonio Nino Diaz	/*
147f5478dedSAntonio Nino Diaz	 * Macro to mark instances where we're jumping to a function and don't
148f5478dedSAntonio Nino Diaz	 * expect a return. To provide the function being jumped to with
149f5478dedSAntonio Nino Diaz	 * additional information, we use 'bl' instruction to jump rather than
150f5478dedSAntonio Nino Diaz	 * 'b'.
151f5478dedSAntonio Nino Diaz         *
152f5478dedSAntonio Nino Diaz	 * Debuggers infer the location of a call from where LR points to, which
153f5478dedSAntonio Nino Diaz	 * is usually the instruction after 'bl'. If this macro expansion
154f5478dedSAntonio Nino Diaz	 * happens to be the last location in a function, that'll cause the LR
155f5478dedSAntonio Nino Diaz	 * to point a location beyond the function, thereby misleading debugger
156f5478dedSAntonio Nino Diaz	 * back trace. We therefore insert a 'nop' after the function call for
157f5478dedSAntonio Nino Diaz	 * debug builds, unless 'skip_nop' parameter is non-zero.
158f5478dedSAntonio Nino Diaz	 */
159f5478dedSAntonio Nino Diaz	.macro no_ret _func:req, skip_nop=0
160f5478dedSAntonio Nino Diaz	bl	\_func
161f5478dedSAntonio Nino Diaz#if DEBUG
162f5478dedSAntonio Nino Diaz	.ifeq \skip_nop
163f5478dedSAntonio Nino Diaz	nop
164f5478dedSAntonio Nino Diaz	.endif
165f5478dedSAntonio Nino Diaz#endif
166f5478dedSAntonio Nino Diaz	.endm
167f5478dedSAntonio Nino Diaz
168f5478dedSAntonio Nino Diaz	/*
169f5478dedSAntonio Nino Diaz	 * Reserve space for a spin lock in assembly file.
170f5478dedSAntonio Nino Diaz	 */
171f5478dedSAntonio Nino Diaz	.macro define_asm_spinlock _name:req
172f5478dedSAntonio Nino Diaz	.align	SPINLOCK_ASM_ALIGN
173f5478dedSAntonio Nino Diaz	\_name:
174f5478dedSAntonio Nino Diaz	.space	SPINLOCK_ASM_SIZE
175f5478dedSAntonio Nino Diaz	.endm
176f5478dedSAntonio Nino Diaz
177f5478dedSAntonio Nino Diaz	/*
178f5478dedSAntonio Nino Diaz	 * Helper macro to OR the bottom 32 bits of `_val` into `_reg_l`
179f5478dedSAntonio Nino Diaz	 * and the top 32 bits of `_val` into `_reg_h`.  If either the bottom
180f5478dedSAntonio Nino Diaz	 * or top word of `_val` is zero, the corresponding OR operation
181f5478dedSAntonio Nino Diaz	 * is skipped.
182f5478dedSAntonio Nino Diaz	 */
183f5478dedSAntonio Nino Diaz	.macro orr64_imm _reg_l, _reg_h, _val
184f5478dedSAntonio Nino Diaz		.if (\_val >> 32)
185f5478dedSAntonio Nino Diaz			orr \_reg_h, \_reg_h, #(\_val >> 32)
186f5478dedSAntonio Nino Diaz		.endif
187f5478dedSAntonio Nino Diaz		.if (\_val & 0xffffffff)
188f5478dedSAntonio Nino Diaz			orr \_reg_l, \_reg_l, #(\_val & 0xffffffff)
189f5478dedSAntonio Nino Diaz		.endif
190f5478dedSAntonio Nino Diaz	.endm
191f5478dedSAntonio Nino Diaz
192f5478dedSAntonio Nino Diaz	/*
193f5478dedSAntonio Nino Diaz	 * Helper macro to bitwise-clear bits in `_reg_l` and
194f5478dedSAntonio Nino Diaz	 * `_reg_h` given a 64 bit immediate `_val`.  The set bits
195f5478dedSAntonio Nino Diaz	 * in the bottom word of `_val` dictate which bits from
196f5478dedSAntonio Nino Diaz	 * `_reg_l` should be cleared.  Similarly, the set bits in
197f5478dedSAntonio Nino Diaz	 * the top word of `_val` dictate which bits from `_reg_h`
198f5478dedSAntonio Nino Diaz	 * should be cleared.  If either the bottom or top word of
199f5478dedSAntonio Nino Diaz	 * `_val` is zero, the corresponding BIC operation is skipped.
200f5478dedSAntonio Nino Diaz	 */
201f5478dedSAntonio Nino Diaz	.macro bic64_imm _reg_l, _reg_h, _val
202f5478dedSAntonio Nino Diaz		.if (\_val >> 32)
203f5478dedSAntonio Nino Diaz			bic \_reg_h, \_reg_h, #(\_val >> 32)
204f5478dedSAntonio Nino Diaz		.endif
205f5478dedSAntonio Nino Diaz		.if (\_val & 0xffffffff)
206f5478dedSAntonio Nino Diaz			bic \_reg_l, \_reg_l, #(\_val & 0xffffffff)
207f5478dedSAntonio Nino Diaz		.endif
208f5478dedSAntonio Nino Diaz	.endm
209f5478dedSAntonio Nino Diaz
210a5aa25afSUsama Arif	/*
211a5aa25afSUsama Arif	 * Helper macro for carrying out division in software when
212a5aa25afSUsama Arif	 * hardware division is not suported. \top holds the dividend
213a5aa25afSUsama Arif	 * in the function call and the remainder after
214a5aa25afSUsama Arif	 * the function is executed. \bot holds the divisor. \div holds
215a5aa25afSUsama Arif	 * the quotient and \temp is a temporary registed used in calcualtion.
216a5aa25afSUsama Arif	 * The division algorithm has been obtained from:
217a5aa25afSUsama Arif	 * http://www.keil.com/support/man/docs/armasm/armasm_dom1359731155623.htm
218a5aa25afSUsama Arif	 */
219a5aa25afSUsama Arif	.macro	softudiv	div:req,top:req,bot:req,temp:req
220a5aa25afSUsama Arif
221a5aa25afSUsama Arif	mov     \temp, \bot
222a5aa25afSUsama Arif	cmp     \temp, \top, lsr #1
223a5aa25afSUsama Arifdiv1:
224a5aa25afSUsama Arif	movls   \temp, \temp, lsl #1
225a5aa25afSUsama Arif	cmp     \temp, \top, lsr #1
226a5aa25afSUsama Arif	bls     div1
227a5aa25afSUsama Arif	mov     \div, #0
228a5aa25afSUsama Arif
229a5aa25afSUsama Arifdiv2:
230a5aa25afSUsama Arif	cmp     \top, \temp
231a5aa25afSUsama Arif	subcs   \top, \top,\temp
232a5aa25afSUsama Arif	ADC     \div, \div, \div
233a5aa25afSUsama Arif	mov     \temp, \temp, lsr #1
234a5aa25afSUsama Arif	cmp     \temp, \bot
235a5aa25afSUsama Arif	bhs     div2
236a5aa25afSUsama Arif	.endm
237f5478dedSAntonio Nino Diaz#endif /* ASM_MACROS_S */
238