[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" ( &params ) );
+		    "1" ( &params )
+		  : "cc" );
 	if ( ! prno_is_supported ( &params.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;
 }