xref: /optee_os/core/arch/arm/include/arm64_macros.S (revision 733655e63747d45db96414210cdd7aae468414ab)
11bb92983SJerome Forissier/* SPDX-License-Identifier: BSD-2-Clause */
2e0cbf7deSJens Wiklander/*
3e0cbf7deSJens Wiklander * Copyright (c) 2015, Linaro Limited
4e0cbf7deSJens Wiklander */
5e0cbf7deSJens Wiklander
6e0cbf7deSJens Wiklander	.altmacro
7e0cbf7deSJens Wiklander
8e0cbf7deSJens Wiklander	/*
9e0cbf7deSJens Wiklander	 * This helper macro concatenates instr_prefix, instr_suffix, to
10e0cbf7deSJens Wiklander	 * create a ldp/stp instruction. It also selects register name x/w
11e0cbf7deSJens Wiklander	 * based on reg_bytes.
12e0cbf7deSJens Wiklander	 */
13e0cbf7deSJens Wiklander	.macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \
14e0cbf7deSJens Wiklander			base_offs, reg0, reg1
15e0cbf7deSJens Wiklander		.if \reg_bytes == 8
16e0cbf7deSJens Wiklander			\instr_prefix\instr_suffix \
17e0cbf7deSJens Wiklander				x\reg0, x\reg1, [\base_reg, #\base_offs]
18e0cbf7deSJens Wiklander		.else
19e0cbf7deSJens Wiklander			\instr_prefix\instr_suffix \
20e0cbf7deSJens Wiklander				w\reg0, w\reg1, [\base_reg, #\base_offs]
21e0cbf7deSJens Wiklander		.endif
22e0cbf7deSJens Wiklander	.endm
23e0cbf7deSJens Wiklander
24e0cbf7deSJens Wiklander	/*
25e0cbf7deSJens Wiklander	 * This helper macro concatenates instr_prefix, instr_suffix, to
26e0cbf7deSJens Wiklander	 * create a ldr/str instruction. It also selects register name x/w
27e0cbf7deSJens Wiklander	 * based on reg_bytes.
28e0cbf7deSJens Wiklander	 */
29e0cbf7deSJens Wiklander	.macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \
30e0cbf7deSJens Wiklander			base_offs, reg
31e0cbf7deSJens Wiklander		.if \reg_bytes == 8
32e0cbf7deSJens Wiklander			\instr_prefix\instr_suffix \
33e0cbf7deSJens Wiklander				x\reg, [\base_reg, #\base_offs]
34e0cbf7deSJens Wiklander		.else
35e0cbf7deSJens Wiklander			\instr_prefix\instr_suffix \
36e0cbf7deSJens Wiklander				w\reg, [\base_reg, #\base_offs]
37e0cbf7deSJens Wiklander		.endif
38e0cbf7deSJens Wiklander	.endm
39e0cbf7deSJens Wiklander
40e0cbf7deSJens Wiklander	/*
41e0cbf7deSJens Wiklander	 * This helper macro uses recursion to create a loop which will
42e0cbf7deSJens Wiklander	 * start with generating instructions for register pairs and if
43e0cbf7deSJens Wiklander	 * it's an odd number of registers end with a single load/store.
44e0cbf7deSJens Wiklander	 */
45e0cbf7deSJens Wiklander	.macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \
46e0cbf7deSJens Wiklander			from_regnum, to_regnum
47e0cbf7deSJens Wiklander		.if (\to_regnum - \from_regnum + 1) >= 2
48e0cbf7deSJens Wiklander			__do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \
49e0cbf7deSJens Wiklander				\base_offs, \from_regnum, %(\from_regnum + 1)
50e0cbf7deSJens Wiklander		.else
51e0cbf7deSJens Wiklander			__do_reg \instr_prefix, r, \reg_bytes, \base_reg, \
52e0cbf7deSJens Wiklander				\base_offs, \from_regnum
53e0cbf7deSJens Wiklander		.endif
54e0cbf7deSJens Wiklander		.if (\to_regnum - \from_regnum + 1) > 2
55e0cbf7deSJens Wiklander			_do_regs \instr_prefix, \reg_bytes, \base_reg, \
56e0cbf7deSJens Wiklander				%(\base_offs + 2 * \reg_bytes), \
57e0cbf7deSJens Wiklander				%(\from_regnum + 2), \to_regnum
58e0cbf7deSJens Wiklander		.endif
59e0cbf7deSJens Wiklander	.endm
60e0cbf7deSJens Wiklander
61e0cbf7deSJens Wiklander	/*
62e0cbf7deSJens Wiklander	 * Stores registers x[from_regnum]..x[to_regnum] at
63e0cbf7deSJens Wiklander	 * [base_reg, #base_offs]
64e0cbf7deSJens Wiklander	 */
65e0cbf7deSJens Wiklander	.macro store_xregs base_reg, base_offs, from_regnum, to_regnum
66e0cbf7deSJens Wiklander		_do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum
67e0cbf7deSJens Wiklander	.endm
68e0cbf7deSJens Wiklander
69e0cbf7deSJens Wiklander	/*
70e0cbf7deSJens Wiklander	 * Stores registers w[from_regnum]..w[to_regnum] at
71e0cbf7deSJens Wiklander	 * [base_reg, #base_offs]
72e0cbf7deSJens Wiklander	 */
73e0cbf7deSJens Wiklander	.macro store_wregs base_reg, base_offs, from_regnum, to_regnum
74e0cbf7deSJens Wiklander		_do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum
75e0cbf7deSJens Wiklander	.endm
76e0cbf7deSJens Wiklander
77e0cbf7deSJens Wiklander	/*
78e0cbf7deSJens Wiklander	 * Loads registers x[from_regnum]..x[to_regnum] at
79e0cbf7deSJens Wiklander	 * [base_reg, #base_offs]
80e0cbf7deSJens Wiklander	 */
81e0cbf7deSJens Wiklander	.macro load_xregs base_reg, base_offs, from_regnum, to_regnum
82e0cbf7deSJens Wiklander		_do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum
83e0cbf7deSJens Wiklander	.endm
84e0cbf7deSJens Wiklander
85e0cbf7deSJens Wiklander	/*
86e0cbf7deSJens Wiklander	 * Loads registers w[from_regnum]..w[to_regnum] at
87e0cbf7deSJens Wiklander	 * [base_reg, #base_offs]
88e0cbf7deSJens Wiklander	 */
89e0cbf7deSJens Wiklander	.macro load_wregs base_reg, base_offs, from_regnum, to_regnum
90e0cbf7deSJens Wiklander		_do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum
91e0cbf7deSJens Wiklander	.endm
92e0cbf7deSJens Wiklander
93e0cbf7deSJens Wiklander
94e0cbf7deSJens Wiklander	/* Push register pair on stack */
95e0cbf7deSJens Wiklander	.macro  push, r1, r2
96e0cbf7deSJens Wiklander	stp     \r1, \r2, [sp, #-16]!
97e0cbf7deSJens Wiklander	.endm
98e0cbf7deSJens Wiklander
99e0cbf7deSJens Wiklander	/* Pop register pair from stack */
100e0cbf7deSJens Wiklander	.macro  pop, r1, r2
101e0cbf7deSJens Wiklander	ldp     \r1, \r2, [sp], #16
102e0cbf7deSJens Wiklander	.endm
103e0cbf7deSJens Wiklander
104bdc8a29dSJens Wiklander	.macro mov_imm _reg, _val
105bdc8a29dSJens Wiklander	.if (((\_val) >> 31) == 0 || ((\_val) >> 31) == 0x1ffffffff)
106bdc8a29dSJens Wiklander		movz    \_reg, :abs_g1_s:\_val
107bdc8a29dSJens Wiklander	.else
108bdc8a29dSJens Wiklander		.if (((\_val) >> 47) == 0 || ((\_val) >> 47) == 0x1ffff)
109bdc8a29dSJens Wiklander			movz    \_reg, :abs_g2_s:\_val
110bdc8a29dSJens Wiklander		.else
111bdc8a29dSJens Wiklander			movz    \_reg, :abs_g3:\_val
112bdc8a29dSJens Wiklander			movk    \_reg, :abs_g2_nc:\_val
113bdc8a29dSJens Wiklander		.endif
114bdc8a29dSJens Wiklander		movk    \_reg, :abs_g1_nc:\_val
115bdc8a29dSJens Wiklander	.endif
116bdc8a29dSJens Wiklander		movk    \_reg, :abs_g0_nc:\_val
117bdc8a29dSJens Wiklander	.endm
1187ff6724eSJerome Forissier
119*733655e6SJens Wiklander	.macro add_imm _reg, _val
120*733655e6SJens Wiklander	.if ((\_val) > 0xfff)
121*733655e6SJens Wiklander		add	\_reg, \_reg, ((\_val) >> 12), LSL #12
122*733655e6SJens Wiklander	.endif
123*733655e6SJens Wiklander	.if (((\_val) & 0xfff) > 0)
124*733655e6SJens Wiklander		add	\_reg, \_reg, ((\_val) & 0xfff)
125*733655e6SJens Wiklander	.endif
126*733655e6SJens Wiklander	.endm
127*733655e6SJens Wiklander
128*733655e6SJens Wiklander	.macro sub_imm _reg, _val
129*733655e6SJens Wiklander	.if ((\_val) > 0xfff)
130*733655e6SJens Wiklander		sub	\_reg, \_reg, ((\_val) >> 12), LSL #12
131*733655e6SJens Wiklander	.endif
132*733655e6SJens Wiklander	.if (((\_val) & 0xfff) > 0)
133*733655e6SJens Wiklander		sub	\_reg, \_reg, ((\_val) & 0xfff)
134*733655e6SJens Wiklander	.endif
135*733655e6SJens Wiklander	.endm
136*733655e6SJens Wiklander
1377ff6724eSJerome Forissier	/*
1387ff6724eSJerome Forissier	 * Load address of <sym> into <reg>, <sym> being in the range
1397ff6724eSJerome Forissier	 * +/- 4GB of the PC (note that 'adr reg, sym' is limited to +/- 1MB).
1407ff6724eSJerome Forissier	 */
1417ff6724eSJerome Forissier	.macro adr_l reg, sym
1427ff6724eSJerome Forissier	adrp	\reg, \sym
1437ff6724eSJerome Forissier	add	\reg, \reg, :lo12:\sym
1447ff6724eSJerome Forissier	.endm
1450c9404e1SJens Wiklander
1460c9404e1SJens Wiklander	.macro panic_at_smc_return
1470c9404e1SJens Wiklander#if defined(CFG_TEE_CORE_DEBUG)
1480c9404e1SJens Wiklander		bl	__panic_at_smc_return
1490c9404e1SJens Wiklander#else
1500c9404e1SJens Wiklander		b	.
1510c9404e1SJens Wiklander#endif
1520c9404e1SJens Wiklander	.endm
1532b06f9deSRuchika Gupta
1542b06f9deSRuchika Gupta	.macro read_apiakeylo reg
1552b06f9deSRuchika Gupta	mrs	\reg, S3_0_c2_c1_0
1562b06f9deSRuchika Gupta	.endm
1572b06f9deSRuchika Gupta
1582b06f9deSRuchika Gupta	.macro read_apiakeyhi reg
1592b06f9deSRuchika Gupta	mrs	\reg, S3_0_c2_c1_1
1602b06f9deSRuchika Gupta	.endm
1612b06f9deSRuchika Gupta
1622b06f9deSRuchika Gupta	.macro write_apiakeylo reg
1632b06f9deSRuchika Gupta	msr	S3_0_c2_c1_0, \reg
1642b06f9deSRuchika Gupta	.endm
1652b06f9deSRuchika Gupta
1662b06f9deSRuchika Gupta	.macro write_apiakeyhi reg
1672b06f9deSRuchika Gupta	msr	S3_0_c2_c1_1, \reg
1682b06f9deSRuchika Gupta	.endm
1696fa59c9aSSeonghyun Park
1706fa59c9aSSeonghyun Park	.macro write_pan reg
1716fa59c9aSSeonghyun Park	/* msr pan, \reg */
1726fa59c9aSSeonghyun Park	msr	S3_0_c4_c2_3, \reg
1736fa59c9aSSeonghyun Park	.endm
1746fa59c9aSSeonghyun Park
1756fa59c9aSSeonghyun Park	.macro write_pan_enable
1766fa59c9aSSeonghyun Park	/* msr pan, #1 */
1776fa59c9aSSeonghyun Park	msr	S0_0_c4_c1_4, xzr
1786fa59c9aSSeonghyun Park	.endm
1796fa59c9aSSeonghyun Park
1806fa59c9aSSeonghyun Park	.macro write_pan_disable
1816fa59c9aSSeonghyun Park	/* msr pan, #0 */
1826fa59c9aSSeonghyun Park	msr	S0_0_c4_c0_4, xzr
1836fa59c9aSSeonghyun Park	.endm
184