1 /*
2  * Copyright (c) 2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #ifndef __TFM_AAPCS_LOCAL_H__
8 #define __TFM_AAPCS_LOCAL_H__
9 
10 #include <stdint.h>
11 
12 /*
13  * AAPCS: Procedure Call Standard for the Arm Architecture(IHI0042).
14  *
15  * This file complies with AAPCS rules for the local project(TF-M)
16  * convenience. Append a 'local' postfix here in case the toolchain
17  * makes 'AAPCS' as one built-in word.
18  */
19 
20 /*
21  * Returning values in multiple argument registers:
22  *
23  * If a caller in assembly code requires multiple return values from a
24  * callee, returning in argument registers is more convenient. This needs
25  * the callee to assemble multiple return values into one fundamental data
26  * type whose size exceeds the default data width, such as returning a 64-bit
27  * integer on a 32-bit system separates the 64-bit into two 32-bit values
28  * and gets returned in argument register 0 and 1.
29  *
30  * The following is the implementation for a generic 32-bit system. To
31  * be expanded when new systems get involved.
32  *
33  * Method (MACRO) uses 'a(x)', which stands for AAPCS 'argument register'.
34  * Implementation uses 'r(x)', which is the implementation name for
35  * 'a(x)' in the 32-bit system.
36  */
37 union u64_in_u32_regs_t {
38     struct {
39         uint32_t    r0;
40         uint32_t    r1;
41     } u32_regs;
42 
43     uint64_t        u64_val;
44 };
45 
46 #define AAPCS_DUAL_U32_T  union u64_in_u32_regs_t
47 
48 #define AAPCS_DUAL_U32_SET(v, a0, a1)                           \
49                         do {                                    \
50                             (v).u32_regs.r0 = (uint32_t)(a0);   \
51                             (v).u32_regs.r1 = (uint32_t)(a1);   \
52                         } while (0)
53 
54 #define AAPCS_DUAL_U32_SET_A0(v, a0)                            \
55                             (v).u32_regs.r0 = (uint32_t)(a0)
56 
57 #define AAPCS_DUAL_U32_SET_A1(v, a1)                            \
58                             (v).u32_regs.r1 = (uint32_t)(a1)
59 
60 #define AAPCS_DUAL_U32_AS_U64(v) (v).u64_val
61 
62 #endif /* __TFM_AAPCS_LOCAL_H__ */
63