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