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