Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
---|---|
2 | #ifndef _SELFTESTS_POWERPC_BASIC_ASM_H |
3 | #define _SELFTESTS_POWERPC_BASIC_ASM_H |
4 | |
5 | #include <ppc-asm.h> |
6 | #include <asm/unistd.h> |
7 | |
8 | #ifdef __powerpc64__ |
9 | #define PPC_LL ld |
10 | #define PPC_STL std |
11 | #define PPC_STLU stdu |
12 | #else |
13 | #define PPC_LL lwz |
14 | #define PPC_STL stw |
15 | #define PPC_STLU stwu |
16 | #endif |
17 | |
18 | #define LOAD_REG_IMMEDIATE(reg, expr) \ |
19 | lis reg, (expr)@highest; \ |
20 | ori reg, reg, (expr)@higher; \ |
21 | rldicr reg, reg, 32, 31; \ |
22 | oris reg, reg, (expr)@high; \ |
23 | ori reg, reg, (expr)@l; |
24 | |
25 | /* |
26 | * Note: These macros assume that variables being stored on the stack are |
27 | * sizeof(long), while this is usually the case it may not always be the |
28 | * case for each use case. |
29 | */ |
30 | #ifdef __powerpc64__ |
31 | |
32 | // ABIv2 |
33 | #if defined(_CALL_ELF) && _CALL_ELF == 2 |
34 | #define STACK_FRAME_MIN_SIZE 32 |
35 | #define STACK_FRAME_TOC_POS 24 |
36 | #define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8)) |
37 | #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ |
38 | ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8)) |
39 | |
40 | #else // ABIv1 below |
41 | #define STACK_FRAME_MIN_SIZE 112 |
42 | #define STACK_FRAME_TOC_POS 40 |
43 | #define __STACK_FRAME_PARAM(i) (48 + ((i)*8)) |
44 | |
45 | /* |
46 | * Caveat: if a function passed more than 8 doublewords, the caller will have |
47 | * made more space... which would render the 112 incorrect. |
48 | */ |
49 | #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ |
50 | (112 + ((_var_num)*8)) |
51 | |
52 | |
53 | #endif // ABIv2 |
54 | |
55 | // Common 64-bit |
56 | #define STACK_FRAME_LR_POS 16 |
57 | #define STACK_FRAME_CR_POS 8 |
58 | |
59 | #else // 32-bit below |
60 | |
61 | #define STACK_FRAME_MIN_SIZE 16 |
62 | #define STACK_FRAME_LR_POS 4 |
63 | |
64 | #define __STACK_FRAME_PARAM(_param) (STACK_FRAME_MIN_SIZE + ((_param)*4)) |
65 | #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ |
66 | ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*4)) |
67 | |
68 | #endif // __powerpc64__ |
69 | |
70 | /* Parameter x saved to the stack */ |
71 | #define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var) |
72 | |
73 | /* Local variable x saved to the stack after x parameters */ |
74 | #define STACK_FRAME_LOCAL(num_params, var) \ |
75 | __STACK_FRAME_LOCAL(num_params, var) |
76 | |
77 | /* |
78 | * It is very important to note here that _extra is the extra amount of |
79 | * stack space needed. This space can be accessed using STACK_FRAME_PARAM() |
80 | * or STACK_FRAME_LOCAL() macros. |
81 | * |
82 | * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp |
83 | * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence |
84 | * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets |
85 | * preprocessed incorrectly, hence r0. |
86 | */ |
87 | #define PUSH_BASIC_STACK(_extra) \ |
88 | mflr r0; \ |
89 | PPC_STL r0, STACK_FRAME_LR_POS(%r1); \ |
90 | PPC_STLU %r1, -(((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE)(%r1); |
91 | |
92 | #define POP_BASIC_STACK(_extra) \ |
93 | addi %r1, %r1, (((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE); \ |
94 | PPC_LL r0, STACK_FRAME_LR_POS(%r1); \ |
95 | mtlr r0; |
96 | |
97 | .macro OP_REGS op, reg_width, start_reg, end_reg, base_reg, base_reg_offset=0, skip=0 |
98 | .set i, \start_reg |
99 | .rept (\end_reg - \start_reg + 1) |
100 | \op i, (\reg_width * (i - \skip) + \base_reg_offset)(\base_reg) |
101 | .set i, i + 1 |
102 | .endr |
103 | .endm |
104 | |
105 | #endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */ |
106 |
Warning: This file is not a C or C++ file. It does not have highlighting.