* Segher Boessenkool: > On Wed, Jan 29, 2020 at 06:02:34PM +0100, Florian Weimer wrote: >> * Segher Boessenkool: >> >> > On Wed, Jan 29, 2020 at 05:19:19PM +0100, Florian Weimer wrote: >> >> * Segher Boessenkool: >> >> >> But GCC doesn't expose them as integers to C code, so you can't do much >> >> >> without them. >> >> > >> >> > Sure, it doesn't expose any other registers directly, either. >> >> >> >> I can use r0 & 1 with a register variable r0 to check a bit. >> > >> > That is not reliable, or supported, and it *will* break. This is >> > explicit for local register asm, and global register asm is >> > underdefined. >> >> Ugh. I did not know that. And neither did the person who wrote >> powerpc64/sysdep.h because it uses register variables in regular C >> expressions. 8-( Other architectures are affected as well. > > Where? I don't see any? Ah, the other one, heh (there are two). > > No, that *is* supported: as input to or output from an asm, a local > register asm variable *is* guaranteed to live in the specified register. > This is the *only* supported use. Other uses may sometimes still work, > but they never worked reliably, and it cannot be made reliable; it has > been documented as not supported since ages, and it will not work at all > anymore some day.
I must say I find this situation *very* confusing. You said that r0 & 1 is undefined. I *assumed* that I would still get the value of r0 (the register) from the associated extended asm in this expression, even if it may now be a different register. Your comment made me think that this is undefined. But then the syscall wrappers use this construct: __asm__ __volatile__ \ ("sc\n\t" \ "mfcr %0\n\t" \ "0:" \ : "=&r" (r0), \ "=&r" (r3), "=&r" (r4), "=&r" (r5), \ "=&r" (r6), "=&r" (r7), "=&r" (r8) \ : ASM_INPUT_##nr \ : "r9", "r10", "r11", "r12", \ "cr0", "ctr", "memory"); \ err = r0; \ r3; \ That lone r3 at the end would be equally undefined because it is not used in an input or output operand of an extended asm statement. The GCC documentation has this warning: | _Warning:_ In the above example, be aware that a register (for | example 'r0') can be call-clobbered by subsequent code, including | function calls and library calls for arithmetic operators on other | variables (for example the initialization of 'p2'). On POWER, the LOADARGS macros attempt to deal with this by using non-register temporaries. However, I don't know how effective this is if the compiler really doesn't deal with call-clobbered registers properly. For the extended asm use case (to express register assignments that cannot be listed in constraints), I would expect that these variables retain their values according to the C specification (so they are never clobbered by calls), but that they only reside in their designated registers when used as input or output operands in extended asm statements. However, this is incompatible with other (ab)uses of local and global register variables, which may well expect that they are clobbered by calls. It looks like GCC uses the same construct for two unrelated things. Thanks, Florian