Skip to content

Commit e7583c5

Browse files
committed
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 <[email protected]> Reviewed-by: Juergen Christ <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent 2f4b3b8 commit e7583c5

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

arch/s390/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ config KASAN_SHADOW_OFFSET
5252
depends on KASAN
5353
default 0x1C000000000000
5454

55+
config GCC_ASM_FLAG_OUTPUT_BROKEN
56+
def_bool CC_IS_GCC && GCC_VERSION < 140200
57+
help
58+
GCC versions before 14.2.0 may die with an internal
59+
compiler error in some configurations if flag output
60+
operands are used within inline assemblies.
61+
5562
config S390
5663
def_bool y
5764
#

arch/s390/include/asm/asm.h

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,50 @@
22
#ifndef _ASM_S390_ASM_H
33
#define _ASM_S390_ASM_H
44

5-
/* GCC versions before 14.2.0 may die with an ICE in some configurations. */
6-
#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_IS_GCC) && (GCC_VERSION < 140200))
5+
#include <linux/stringify.h>
6+
7+
/*
8+
* Helper macros to be used for flag output operand handling.
9+
* Inline assemblies must use four of the five supplied macros:
10+
*
11+
* Use CC_IPM(sym) at the end of the inline assembly; this extracts the
12+
* condition code and program mask with the ipm instruction and writes it to
13+
* the variable with symbolic name [sym] if the compiler has no support for
14+
* flag output operands. If the compiler has support for flag output operands
15+
* this generates no code.
16+
*
17+
* Use CC_OUT(sym, var) at the output operand list of an inline assembly. This
18+
* defines an output operand with symbolic name [sym] for the variable
19+
* [var]. [var] must be an int variable and [sym] must be identical with [sym]
20+
* used with CC_IPM().
21+
*
22+
* Use either CC_CLOBBER or CC_CLOBBER_LIST() for the clobber list. Use
23+
* CC_CLOBBER if the clobber list contains only "cc", otherwise use
24+
* CC_CLOBBER_LIST() and add all clobbers as argument to the macro.
25+
*
26+
* Use CC_TRANSFORM() to convert the variable [var] which contains the
27+
* extracted condition code. If the condition code is extracted with ipm, the
28+
* [var] also contains the program mask. CC_TRANSFORM() moves the condition
29+
* code to the two least significant bits and sets all other bits to zero.
30+
*/
31+
#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_GCC_ASM_FLAG_OUTPUT_BROKEN))
732

833
#define __HAVE_ASM_FLAG_OUTPUTS__
934

35+
#define CC_IPM(sym)
36+
#define CC_OUT(sym, var) "=@cc" (var)
37+
#define CC_TRANSFORM(cc) ({ cc; })
38+
#define CC_CLOBBER
39+
#define CC_CLOBBER_LIST(...) __VA_ARGS__
40+
41+
#else
42+
43+
#define CC_IPM(sym) " ipm %[" __stringify(sym) "]\n"
44+
#define CC_OUT(sym, var) [sym] "=d" (var)
45+
#define CC_TRANSFORM(cc) ({ (cc) >> 28; })
46+
#define CC_CLOBBER "cc"
47+
#define CC_CLOBBER_LIST(...) "cc", __VA_ARGS__
48+
1049
#endif
1150

1251
#endif /* _ASM_S390_ASM_H */

0 commit comments

Comments
 (0)