[s390x] Add missing condition code clobbers to inline assembly For x86, GCC will assume that any inline assembly instruction clobbers the condition code and so it is not necessary to explicitly include "cc" within the clobber list. For s390x, GCC will assume that the condition code is preserved unless explicitly clobbered. It is extremely rare for GCC to emit code that actually relies upon this behaviour, but it has been observed to happen within a series of memcpy() calls with condition-dependent source addresses. Fix by adding "cc" to the clobber list on all inline assembly blocks where the condition code is not guaranteed to be preserved. It would be possible to use "=@cc" as an output constraint to obtain the carry result from bigint_add() and bigint_subtract(), but the instructions generated by GCC to extract the condition code end up being larger than the single "alcr"/"slbr" that we currently use to obtain the carry result. Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/arch/s390x/core/facility.c b/src/arch/s390x/core/facility.c index d3ab6b4..0d169e7 100644 --- a/src/arch/s390x/core/facility.c +++ b/src/arch/s390x/core/facility.c
@@ -46,7 +46,7 @@ memset ( &facilities, 0, sizeof ( facilities ) ); max = ( ( sizeof ( facilities.mask ) / sizeof ( facilities.mask[0] ) ) - 1 ); - __asm__ ( "stfle %0" : "=R" ( facilities ), "+r" ( max ) ); + __asm__ ( "stfle %0" : "=R" ( facilities ), "+r" ( max ) : : "cc" ); DBGC ( &facilities, "FACILITY %016llx:%016llx:%016llx:%016llx\n", facilities.mask[0], facilities.mask[1], facilities.mask[2], facilities.mask[3] );
diff --git a/src/arch/s390x/core/prno.c b/src/arch/s390x/core/prno.c index 75e6b7c..79b81c1 100644 --- a/src/arch/s390x/core/prno.c +++ b/src/arch/s390x/core/prno.c
@@ -69,7 +69,8 @@ "=a" ( dummy2 ), "=m" ( params ) : "0" ( PRNO_FN_QUERY ), - "1" ( ¶ms ) ); + "1" ( ¶ms ) + : "cc" ); if ( ! prno_is_supported ( ¶ms.supported, PRNO_FN_TRNG ) ) { DBGC ( colour, "PRNO does not support TRNG (%016llx:%016llx)\n", params.supported.mask[0], params.supported.mask[1] ); @@ -111,7 +112,8 @@ "+a" ( raw ), "+a" ( conditioned ), "=m" ( *noise ) - : "0" ( PRNO_FN_TRNG ) ); + : "0" ( PRNO_FN_TRNG ) + : "cc" ); return 0; }
diff --git a/src/arch/s390x/include/bits/bigint.h b/src/arch/s390x/include/bits/bigint.h index 57d6483..db8356e 100644 --- a/src/arch/s390x/include/bits/bigint.h +++ b/src/arch/s390x/include/bits/bigint.h
@@ -46,7 +46,8 @@ "=&r" ( index_carry ), "+S" ( *value ) : "S" ( *addend ), - "2" ( size ) ); + "2" ( size ) + : "cc" ); return index_carry; } @@ -86,7 +87,8 @@ "=&r" ( index_borrow ), "+S" ( *value ) : "S" ( *subtrahend ), - "2" ( size ) ); + "2" ( size ) + : "cc" ); return ( -index_borrow ); } @@ -122,7 +124,8 @@ "+S" ( *value ) : "0" ( 0UL ), "2" ( size ), - "3" ( 0U ) ); + "3" ( 0U ) + : "cc" ); return carry; } @@ -155,7 +158,8 @@ "=&r" ( carry ), "+S" ( *value ) : "0" ( sizeof ( *value ) ), - "2" ( 0 ) ); + "2" ( 0 ) + : "cc" ); return ( carry & 1 ); } @@ -183,7 +187,8 @@ "mvcle %0, %1, 0\n\t" "jo 1b\n\t" : "+r" ( dpair ), "+r" ( spair ), "=m" ( *dest ) - : "m" ( *source ) ); + : "m" ( *source ) + : "cc" ); } /** @@ -209,7 +214,8 @@ "mvcle %0, %1, 0\n\t" "jo 1b\n\t" : "+r" ( dpair ), "+r" ( spair ), "=m" ( *dest ) - : "m" ( *source ) ); + : "m" ( *source ) + : "cc" ); } /** @@ -242,7 +248,8 @@ "+T" ( *result ), "+r" ( *carry ) : "r" ( multiplicand ), - "r" ( multiplier ) ); + "r" ( multiplier ) + : "cc" ); } #endif /* _BITS_BIGINT_H */
diff --git a/src/arch/s390x/include/bits/bitops.h b/src/arch/s390x/include/bits/bitops.h index 2065ddb..d7c7662 100644 --- a/src/arch/s390x/include/bits/bitops.h +++ b/src/arch/s390x/include/bits/bitops.h
@@ -29,7 +29,8 @@ __asm__ __volatile__ ( "lao %0, %2, %1" : "=r" ( old ), "+S" ( *word ) - : "r" ( mask ) ); + : "r" ( mask ) + : "cc" ); return ( !! ( old & mask ) ); } @@ -51,7 +52,8 @@ __asm__ __volatile__ ( "lan %0, %2, %1" : "=r" ( old ), "+S" ( *word ) - : "r" ( ~mask ) ); + : "r" ( ~mask ) + : "cc" ); return ( !! ( old & mask ) ); }
diff --git a/src/arch/s390x/include/bits/profile.h b/src/arch/s390x/include/bits/profile.h index b679343..cf2ac68 100644 --- a/src/arch/s390x/include/bits/profile.h +++ b/src/arch/s390x/include/bits/profile.h
@@ -21,7 +21,7 @@ uint64_t cycles; /* Read timestamp counter */ - __asm__ ( "stckf %0" : "=Q" ( cycles ) ); + __asm__ ( "stckf %0" : "=Q" ( cycles ) : : "cc" ); return cycles; }
diff --git a/src/arch/s390x/include/bits/string.h b/src/arch/s390x/include/bits/string.h index 235a878..b11e611 100644 --- a/src/arch/s390x/include/bits/string.h +++ b/src/arch/s390x/include/bits/string.h
@@ -34,21 +34,24 @@ /* Constant small length, zeroing: use XOR-in-place */ __asm__ ( "xc %O0(%1, %R0), %0" : "=Q" ( *dmem ) - : "i" ( len ) ); + : "i" ( len ) + : "cc" ); } else if ( __builtin_constant_p ( character ) ) { /* Constant fill character: use "mvcle" with an immediate */ __asm__ ( "\n1:\n\t" "mvcle %0, %2, %3\n\t" "jo 1b\n\t" : "+r" ( dpair ), "=m" ( *dmem ) - : "r" ( spair ), "i" ( character ) ); + : "r" ( spair ), "i" ( character ) + : "cc" ); } else { /* Variable fill character: use "mvcle" with a register */ __asm__ ( "\n1:\n\t" "mvcle %0, %2, 0(%3)\n\t" "jo 1b\n\t" : "+r" ( dpair ), "=m" ( *dmem ) - : "r" ( spair ), "a" ( character ) ); + : "r" ( spair ), "a" ( character ) + : "cc" ); } return dest; @@ -82,7 +85,8 @@ "mvcle %0, %1, 0\n\t" "jo 1b\n\t" : "+r" ( dpair ), "+r" ( spair ), "=m" ( *dmem ) - : "m" ( *smem ) ); + : "m" ( *smem ) + : "cc" ); } return dest;
diff --git a/src/arch/s390x/include/bits/strings.h b/src/arch/s390x/include/bits/strings.h index 6fbe0e8..4893828 100644 --- a/src/arch/s390x/include/bits/strings.h +++ b/src/arch/s390x/include/bits/strings.h
@@ -22,7 +22,7 @@ value &= -value; /* Count number of leading zeros before LSB */ - __asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) ); + __asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) : "cc" ); return ( 64 - pair.even ); } @@ -48,7 +48,7 @@ struct s390x_scalar_pair pair; /* Count leading zeros */ - __asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) ); + __asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) : "cc" ); return ( 64 - pair.even ); }
diff --git a/src/arch/s390x/include/bits/tcpip.h b/src/arch/s390x/include/bits/tcpip.h index 423b1a1..b4f7734 100644 --- a/src/arch/s390x/include/bits/tcpip.h +++ b/src/arch/s390x/include/bits/tcpip.h
@@ -33,7 +33,8 @@ "alcr %0, %N1\n\t" : "=&r" ( cksum ), "+r" ( pair ) - : "0" ( ~partial ) ); + : "0" ( ~partial ) + : "cc" ); return ~cksum; }
diff --git a/src/arch/s390x/include/ipxe/tod.h b/src/arch/s390x/include/ipxe/tod.h index 55c7ff5..73e0eb5 100644 --- a/src/arch/s390x/include/ipxe/tod.h +++ b/src/arch/s390x/include/ipxe/tod.h
@@ -63,7 +63,7 @@ union tod_extended tod; /* Read clock */ - __asm__ ( "stcke %0" : "=R" ( tod ) ); + __asm__ ( "stcke %0" : "=R" ( tod ) : : "cc" ); return tod.ticks; }