xref: /optee_os/core/arch/arm/include/arm64_macros.S (revision 9977404eea543dc76241d8da3a29ff140759f5c0)
1/*
2 * Copyright (c) 2015, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28	.altmacro
29
30	/*
31	 * This helper macro concatenates instr_prefix, instr_suffix, to
32	 * create a ldp/stp instruction. It also selects register name x/w
33	 * based on reg_bytes.
34	 */
35	.macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \
36			base_offs, reg0, reg1
37		.if \reg_bytes == 8
38			\instr_prefix\instr_suffix \
39				x\reg0, x\reg1, [\base_reg, #\base_offs]
40		.else
41			\instr_prefix\instr_suffix \
42				w\reg0, w\reg1, [\base_reg, #\base_offs]
43		.endif
44	.endm
45
46	/*
47	 * This helper macro concatenates instr_prefix, instr_suffix, to
48	 * create a ldr/str instruction. It also selects register name x/w
49	 * based on reg_bytes.
50	 */
51	.macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \
52			base_offs, reg
53		.if \reg_bytes == 8
54			\instr_prefix\instr_suffix \
55				x\reg, [\base_reg, #\base_offs]
56		.else
57			\instr_prefix\instr_suffix \
58				w\reg, [\base_reg, #\base_offs]
59		.endif
60	.endm
61
62	/*
63	 * This helper macro uses recursion to create a loop which will
64	 * start with generating instructions for register pairs and if
65	 * it's an odd number of registers end with a single load/store.
66	 */
67	.macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \
68			from_regnum, to_regnum
69		.if (\to_regnum - \from_regnum + 1) >= 2
70			__do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \
71				\base_offs, \from_regnum, %(\from_regnum + 1)
72		.else
73			__do_reg \instr_prefix, r, \reg_bytes, \base_reg, \
74				\base_offs, \from_regnum
75		.endif
76		.if (\to_regnum - \from_regnum + 1) > 2
77			_do_regs \instr_prefix, \reg_bytes, \base_reg, \
78				%(\base_offs + 2 * \reg_bytes), \
79				%(\from_regnum + 2), \to_regnum
80		.endif
81	.endm
82
83	/*
84	 * Stores registers x[from_regnum]..x[to_regnum] at
85	 * [base_reg, #base_offs]
86	 */
87	.macro store_xregs base_reg, base_offs, from_regnum, to_regnum
88		_do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum
89	.endm
90
91	/*
92	 * Stores registers w[from_regnum]..w[to_regnum] at
93	 * [base_reg, #base_offs]
94	 */
95	.macro store_wregs base_reg, base_offs, from_regnum, to_regnum
96		_do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum
97	.endm
98
99	/*
100	 * Loads registers x[from_regnum]..x[to_regnum] at
101	 * [base_reg, #base_offs]
102	 */
103	.macro load_xregs base_reg, base_offs, from_regnum, to_regnum
104		_do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum
105	.endm
106
107	/*
108	 * Loads registers w[from_regnum]..w[to_regnum] at
109	 * [base_reg, #base_offs]
110	 */
111	.macro load_wregs base_reg, base_offs, from_regnum, to_regnum
112		_do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum
113	.endm
114
115
116	/* Push register pair on stack */
117	.macro  push, r1, r2
118	stp     \r1, \r2, [sp, #-16]!
119	.endm
120
121	/* Pop register pair from stack */
122	.macro  pop, r1, r2
123	ldp     \r1, \r2, [sp], #16
124	.endm
125
126