Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _SELFTESTS_POWERPC_BASIC_ASM_H
0003 #define _SELFTESTS_POWERPC_BASIC_ASM_H
0004 
0005 #include <ppc-asm.h>
0006 #include <asm/unistd.h>
0007 
0008 #ifdef __powerpc64__
0009 #define PPC_LL      ld
0010 #define PPC_STL     std
0011 #define PPC_STLU    stdu
0012 #else
0013 #define PPC_LL      lwz
0014 #define PPC_STL     stw
0015 #define PPC_STLU    stwu
0016 #endif
0017 
0018 #define LOAD_REG_IMMEDIATE(reg, expr) \
0019     lis reg, (expr)@highest;    \
0020     ori reg, reg, (expr)@higher;    \
0021     rldicr  reg, reg, 32, 31;   \
0022     oris    reg, reg, (expr)@high;  \
0023     ori reg, reg, (expr)@l;
0024 
0025 /*
0026  * Note: These macros assume that variables being stored on the stack are
0027  * sizeof(long), while this is usually the case it may not always be the
0028  * case for each use case.
0029  */
0030 #ifdef  __powerpc64__
0031 
0032 // ABIv2
0033 #if defined(_CALL_ELF) && _CALL_ELF == 2
0034 #define STACK_FRAME_MIN_SIZE 32
0035 #define STACK_FRAME_TOC_POS  24
0036 #define __STACK_FRAME_PARAM(_param)  (32 + ((_param)*8))
0037 #define __STACK_FRAME_LOCAL(_num_params, _var_num)  \
0038     ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8))
0039 
0040 #else // ABIv1 below
0041 #define STACK_FRAME_MIN_SIZE 112
0042 #define STACK_FRAME_TOC_POS  40
0043 #define __STACK_FRAME_PARAM(i)  (48 + ((i)*8))
0044 
0045 /*
0046  * Caveat: if a function passed more than 8 doublewords, the caller will have
0047  * made more space... which would render the 112 incorrect.
0048  */
0049 #define __STACK_FRAME_LOCAL(_num_params, _var_num)  \
0050     (112 + ((_var_num)*8))
0051 
0052 
0053 #endif // ABIv2
0054 
0055 // Common 64-bit
0056 #define STACK_FRAME_LR_POS   16
0057 #define STACK_FRAME_CR_POS   8
0058 
0059 #else // 32-bit below
0060 
0061 #define STACK_FRAME_MIN_SIZE 16
0062 #define STACK_FRAME_LR_POS   4
0063 
0064 #define __STACK_FRAME_PARAM(_param)  (STACK_FRAME_MIN_SIZE + ((_param)*4))
0065 #define __STACK_FRAME_LOCAL(_num_params, _var_num)  \
0066     ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*4))
0067 
0068 #endif // __powerpc64__
0069 
0070 /* Parameter x saved to the stack */
0071 #define STACK_FRAME_PARAM(var)    __STACK_FRAME_PARAM(var)
0072 
0073 /* Local variable x saved to the stack after x parameters */
0074 #define STACK_FRAME_LOCAL(num_params, var)    \
0075     __STACK_FRAME_LOCAL(num_params, var)
0076 
0077 /*
0078  * It is very important to note here that _extra is the extra amount of
0079  * stack space needed. This space can be accessed using STACK_FRAME_PARAM()
0080  * or STACK_FRAME_LOCAL() macros.
0081  *
0082  * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp
0083  * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence
0084  * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets
0085  * preprocessed incorrectly, hence r0.
0086  */
0087 #define PUSH_BASIC_STACK(_extra) \
0088     mflr     r0; \
0089     PPC_STL  r0, STACK_FRAME_LR_POS(%r1); \
0090     PPC_STLU %r1, -(((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE)(%r1);
0091 
0092 #define POP_BASIC_STACK(_extra) \
0093     addi    %r1, %r1, (((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE); \
0094     PPC_LL  r0, STACK_FRAME_LR_POS(%r1); \
0095     mtlr    r0;
0096 
0097 .macro OP_REGS op, reg_width, start_reg, end_reg, base_reg, base_reg_offset=0, skip=0
0098     .set i, \start_reg
0099     .rept (\end_reg - \start_reg + 1)
0100     \op i, (\reg_width * (i - \skip) + \base_reg_offset)(\base_reg)
0101     .set i, i + 1
0102     .endr
0103 .endm
0104 
0105 #endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */