1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 215ec3997SSimon Guo #ifndef _SELFTESTS_POWERPC_BASIC_ASM_H 315ec3997SSimon Guo #define _SELFTESTS_POWERPC_BASIC_ASM_H 415ec3997SSimon Guo 515ec3997SSimon Guo #include <ppc-asm.h> 615ec3997SSimon Guo #include <asm/unistd.h> 715ec3997SSimon Guo 8bd4d3042SMichael Ellerman #ifdef __powerpc64__ 9bd4d3042SMichael Ellerman #define PPC_LL ld 10bd4d3042SMichael Ellerman #define PPC_STL std 11bd4d3042SMichael Ellerman #define PPC_STLU stdu 12bd4d3042SMichael Ellerman #else 13bd4d3042SMichael Ellerman #define PPC_LL lwz 14bd4d3042SMichael Ellerman #define PPC_STL stw 15bd4d3042SMichael Ellerman #define PPC_STLU stwu 16bd4d3042SMichael Ellerman #endif 17bd4d3042SMichael Ellerman 1815ec3997SSimon Guo #define LOAD_REG_IMMEDIATE(reg, expr) \ 1915ec3997SSimon Guo lis reg, (expr)@highest; \ 2015ec3997SSimon Guo ori reg, reg, (expr)@higher; \ 2115ec3997SSimon Guo rldicr reg, reg, 32, 31; \ 2215ec3997SSimon Guo oris reg, reg, (expr)@high; \ 2315ec3997SSimon Guo ori reg, reg, (expr)@l; 2415ec3997SSimon Guo 2515ec3997SSimon Guo /* 2615ec3997SSimon Guo * Note: These macros assume that variables being stored on the stack are 27bd4d3042SMichael Ellerman * sizeof(long), while this is usually the case it may not always be the 2815ec3997SSimon Guo * case for each use case. 2915ec3997SSimon Guo */ 30bd4d3042SMichael Ellerman #ifdef __powerpc64__ 31bd4d3042SMichael Ellerman 32bd4d3042SMichael Ellerman // ABIv2 3315ec3997SSimon Guo #if defined(_CALL_ELF) && _CALL_ELF == 2 3415ec3997SSimon Guo #define STACK_FRAME_MIN_SIZE 32 3515ec3997SSimon Guo #define STACK_FRAME_TOC_POS 24 3615ec3997SSimon Guo #define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8)) 3715ec3997SSimon Guo #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ 3815ec3997SSimon Guo ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8)) 39bd4d3042SMichael Ellerman 40bd4d3042SMichael Ellerman #else // ABIv1 below 4115ec3997SSimon Guo #define STACK_FRAME_MIN_SIZE 112 4215ec3997SSimon Guo #define STACK_FRAME_TOC_POS 40 4315ec3997SSimon Guo #define __STACK_FRAME_PARAM(i) (48 + ((i)*8)) 4415ec3997SSimon Guo 4515ec3997SSimon Guo /* 4615ec3997SSimon Guo * Caveat: if a function passed more than 8 doublewords, the caller will have 4715ec3997SSimon Guo * made more space... which would render the 112 incorrect. 4815ec3997SSimon Guo */ 4915ec3997SSimon Guo #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ 5015ec3997SSimon Guo (112 + ((_var_num)*8)) 51bd4d3042SMichael Ellerman 52bd4d3042SMichael Ellerman 53bd4d3042SMichael Ellerman #endif // ABIv2 54bd4d3042SMichael Ellerman 55bd4d3042SMichael Ellerman // Common 64-bit 56bd4d3042SMichael Ellerman #define STACK_FRAME_LR_POS 16 57bd4d3042SMichael Ellerman #define STACK_FRAME_CR_POS 8 58bd4d3042SMichael Ellerman 59bd4d3042SMichael Ellerman #else // 32-bit below 60bd4d3042SMichael Ellerman 61bd4d3042SMichael Ellerman #define STACK_FRAME_MIN_SIZE 16 62bd4d3042SMichael Ellerman #define STACK_FRAME_LR_POS 4 63bd4d3042SMichael Ellerman 64bd4d3042SMichael Ellerman #define __STACK_FRAME_PARAM(_param) (STACK_FRAME_MIN_SIZE + ((_param)*4)) 65bd4d3042SMichael Ellerman #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ 66bd4d3042SMichael Ellerman ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*4)) 67bd4d3042SMichael Ellerman 68bd4d3042SMichael Ellerman #endif // __powerpc64__ 6915ec3997SSimon Guo 7015ec3997SSimon Guo /* Parameter x saved to the stack */ 7115ec3997SSimon Guo #define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var) 7215ec3997SSimon Guo 7315ec3997SSimon Guo /* Local variable x saved to the stack after x parameters */ 7415ec3997SSimon Guo #define STACK_FRAME_LOCAL(num_params, var) \ 7515ec3997SSimon Guo __STACK_FRAME_LOCAL(num_params, var) 7615ec3997SSimon Guo 7715ec3997SSimon Guo /* 7815ec3997SSimon Guo * It is very important to note here that _extra is the extra amount of 7915ec3997SSimon Guo * stack space needed. This space can be accessed using STACK_FRAME_PARAM() 8015ec3997SSimon Guo * or STACK_FRAME_LOCAL() macros. 8115ec3997SSimon Guo * 8215ec3997SSimon Guo * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp 8315ec3997SSimon Guo * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence 8415ec3997SSimon Guo * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets 8515ec3997SSimon Guo * preprocessed incorrectly, hence r0. 8615ec3997SSimon Guo */ 8715ec3997SSimon Guo #define PUSH_BASIC_STACK(_extra) \ 8815ec3997SSimon Guo mflr r0; \ 89bd4d3042SMichael Ellerman PPC_STL r0, STACK_FRAME_LR_POS(%r1); \ 90bd4d3042SMichael Ellerman PPC_STLU %r1, -(((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE)(%r1); 9115ec3997SSimon Guo 9215ec3997SSimon Guo #define POP_BASIC_STACK(_extra) \ 93fd19a1f7SMichael Ellerman addi %r1, %r1, (((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE); \ 94bd4d3042SMichael Ellerman PPC_LL r0, STACK_FRAME_LR_POS(%r1); \ 9515ec3997SSimon Guo mtlr r0; 9615ec3997SSimon Guo 97*611e3850SMichael Ellerman .macro OP_REGS op, reg_width, start_reg, end_reg, base_reg, base_reg_offset=0, skip=0 98*611e3850SMichael Ellerman .set i, \start_reg 99*611e3850SMichael Ellerman .rept (\end_reg - \start_reg + 1) 100*611e3850SMichael Ellerman \op i, (\reg_width * (i - \skip) + \base_reg_offset)(\base_reg) 101*611e3850SMichael Ellerman .set i, i + 1 102*611e3850SMichael Ellerman .endr 103*611e3850SMichael Ellerman .endm 104*611e3850SMichael Ellerman 10515ec3997SSimon Guo #endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */ 106