diff options
author | Heiko Carstens <hca@linux.ibm.com> | 2024-11-07 16:11:32 +0100 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2024-11-13 14:31:31 +0100 |
commit | e7583c5f8d0e0aa34178b6f34a89f81090393c64 (patch) | |
tree | 4af412cccd0484a6ba0ed7ce4aa3a15a75c4281a | |
parent | 2f4b3b83b8c6e798a2e581521f00933d0f9ec777 (diff) | |
download | linux-stable-e7583c5f8d0e0aa34178b6f34a89f81090393c64.tar.gz linux-stable-e7583c5f8d0e0aa34178b6f34a89f81090393c64.tar.bz2 linux-stable-e7583c5f8d0e0aa34178b6f34a89f81090393c64.zip |
s390/asm: Helper macros for flag output operand handling
Since gcc supports flag out operands for inline assemblies there is always
the question when this feature should be used and if it is worth all the
ifdefs that come with that.
In order to avoid that provide similar macros like x86 which can be used
for all inline assemblies which extract the condition code. Depending on
compiler features the generated code will either always contain an ipm+srl
instruction pair, which extracts the condition code, or alternatively let
the compiler handle this completely.
Suggested-by: Juergen Christ <jchrist@linux.ibm.com>
Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-rw-r--r-- | arch/s390/Kconfig | 7 | ||||
-rw-r--r-- | arch/s390/include/asm/asm.h | 43 |
2 files changed, 48 insertions, 2 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8109446f7b24..0270c9046f6b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -52,6 +52,13 @@ config KASAN_SHADOW_OFFSET depends on KASAN default 0x1C000000000000 +config GCC_ASM_FLAG_OUTPUT_BROKEN + def_bool CC_IS_GCC && GCC_VERSION < 140200 + help + GCC versions before 14.2.0 may die with an internal + compiler error in some configurations if flag output + operands are used within inline assemblies. + config S390 def_bool y # diff --git a/arch/s390/include/asm/asm.h b/arch/s390/include/asm/asm.h index bea9dcf9e70e..ec011b94af2a 100644 --- a/arch/s390/include/asm/asm.h +++ b/arch/s390/include/asm/asm.h @@ -2,11 +2,50 @@ #ifndef _ASM_S390_ASM_H #define _ASM_S390_ASM_H -/* GCC versions before 14.2.0 may die with an ICE in some configurations. */ -#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_IS_GCC) && (GCC_VERSION < 140200)) +#include <linux/stringify.h> + +/* + * Helper macros to be used for flag output operand handling. + * Inline assemblies must use four of the five supplied macros: + * + * Use CC_IPM(sym) at the end of the inline assembly; this extracts the + * condition code and program mask with the ipm instruction and writes it to + * the variable with symbolic name [sym] if the compiler has no support for + * flag output operands. If the compiler has support for flag output operands + * this generates no code. + * + * Use CC_OUT(sym, var) at the output operand list of an inline assembly. This + * defines an output operand with symbolic name [sym] for the variable + * [var]. [var] must be an int variable and [sym] must be identical with [sym] + * used with CC_IPM(). + * + * Use either CC_CLOBBER or CC_CLOBBER_LIST() for the clobber list. Use + * CC_CLOBBER if the clobber list contains only "cc", otherwise use + * CC_CLOBBER_LIST() and add all clobbers as argument to the macro. + * + * Use CC_TRANSFORM() to convert the variable [var] which contains the + * extracted condition code. If the condition code is extracted with ipm, the + * [var] also contains the program mask. CC_TRANSFORM() moves the condition + * code to the two least significant bits and sets all other bits to zero. + */ +#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_GCC_ASM_FLAG_OUTPUT_BROKEN)) #define __HAVE_ASM_FLAG_OUTPUTS__ +#define CC_IPM(sym) +#define CC_OUT(sym, var) "=@cc" (var) +#define CC_TRANSFORM(cc) ({ cc; }) +#define CC_CLOBBER +#define CC_CLOBBER_LIST(...) __VA_ARGS__ + +#else + +#define CC_IPM(sym) " ipm %[" __stringify(sym) "]\n" +#define CC_OUT(sym, var) [sym] "=d" (var) +#define CC_TRANSFORM(cc) ({ (cc) >> 28; }) +#define CC_CLOBBER "cc" +#define CC_CLOBBER_LIST(...) "cc", __VA_ARGS__ + #endif #endif /* _ASM_S390_ASM_H */ |