xref: /optee_os/core/arch/arm/include/arm64_macros.S (revision 78b7c7c7653f8bff42fe44d31a79d7f6bbfd4d47)
1/* SPDX-License-Identifier: BSD-2-Clause */
2/*
3 * Copyright (c) 2015, Linaro Limited
4 * All rights reserved.
5 */
6
7	.altmacro
8
9	/*
10	 * This helper macro concatenates instr_prefix, instr_suffix, to
11	 * create a ldp/stp instruction. It also selects register name x/w
12	 * based on reg_bytes.
13	 */
14	.macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \
15			base_offs, reg0, reg1
16		.if \reg_bytes == 8
17			\instr_prefix\instr_suffix \
18				x\reg0, x\reg1, [\base_reg, #\base_offs]
19		.else
20			\instr_prefix\instr_suffix \
21				w\reg0, w\reg1, [\base_reg, #\base_offs]
22		.endif
23	.endm
24
25	/*
26	 * This helper macro concatenates instr_prefix, instr_suffix, to
27	 * create a ldr/str instruction. It also selects register name x/w
28	 * based on reg_bytes.
29	 */
30	.macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \
31			base_offs, reg
32		.if \reg_bytes == 8
33			\instr_prefix\instr_suffix \
34				x\reg, [\base_reg, #\base_offs]
35		.else
36			\instr_prefix\instr_suffix \
37				w\reg, [\base_reg, #\base_offs]
38		.endif
39	.endm
40
41	/*
42	 * This helper macro uses recursion to create a loop which will
43	 * start with generating instructions for register pairs and if
44	 * it's an odd number of registers end with a single load/store.
45	 */
46	.macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \
47			from_regnum, to_regnum
48		.if (\to_regnum - \from_regnum + 1) >= 2
49			__do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \
50				\base_offs, \from_regnum, %(\from_regnum + 1)
51		.else
52			__do_reg \instr_prefix, r, \reg_bytes, \base_reg, \
53				\base_offs, \from_regnum
54		.endif
55		.if (\to_regnum - \from_regnum + 1) > 2
56			_do_regs \instr_prefix, \reg_bytes, \base_reg, \
57				%(\base_offs + 2 * \reg_bytes), \
58				%(\from_regnum + 2), \to_regnum
59		.endif
60	.endm
61
62	/*
63	 * Stores registers x[from_regnum]..x[to_regnum] at
64	 * [base_reg, #base_offs]
65	 */
66	.macro store_xregs base_reg, base_offs, from_regnum, to_regnum
67		_do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum
68	.endm
69
70	/*
71	 * Stores registers w[from_regnum]..w[to_regnum] at
72	 * [base_reg, #base_offs]
73	 */
74	.macro store_wregs base_reg, base_offs, from_regnum, to_regnum
75		_do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum
76	.endm
77
78	/*
79	 * Loads registers x[from_regnum]..x[to_regnum] at
80	 * [base_reg, #base_offs]
81	 */
82	.macro load_xregs base_reg, base_offs, from_regnum, to_regnum
83		_do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum
84	.endm
85
86	/*
87	 * Loads registers w[from_regnum]..w[to_regnum] at
88	 * [base_reg, #base_offs]
89	 */
90	.macro load_wregs base_reg, base_offs, from_regnum, to_regnum
91		_do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum
92	.endm
93
94
95	/* Push register pair on stack */
96	.macro  push, r1, r2
97	stp     \r1, \r2, [sp, #-16]!
98	.endm
99
100	/* Pop register pair from stack */
101	.macro  pop, r1, r2
102	ldp     \r1, \r2, [sp], #16
103	.endm
104
105	.macro mov_imm _reg, _val
106	.if (((\_val) >> 31) == 0 || ((\_val) >> 31) == 0x1ffffffff)
107		movz    \_reg, :abs_g1_s:\_val
108	.else
109		.if (((\_val) >> 47) == 0 || ((\_val) >> 47) == 0x1ffff)
110			movz    \_reg, :abs_g2_s:\_val
111		.else
112			movz    \_reg, :abs_g3:\_val
113			movk    \_reg, :abs_g2_nc:\_val
114		.endif
115		movk    \_reg, :abs_g1_nc:\_val
116	.endif
117		movk    \_reg, :abs_g0_nc:\_val
118	.endm
119