RFC: New mechanism for hard reg operands to inline asm
Andreas Krebbel
krebbel@linux.ibm.com
Fri Jun 4 18:02:27 GMT 2021
Hi,
I wonder if we could replace the register asm construct for
inline assemblies with something a bit nicer and more obvious.
E.g. turning this (real world example from IBM Z kernel code):
int diag8_response(int cmdlen, char *response, int *rlen)
{
register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
register unsigned long reg3 asm ("3") = (addr_t) response;
register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
register unsigned long reg5 asm ("5") = *rlen; /* <-- */
asm volatile(
" diag %2,%0,0x8\n"
" brc 8,1f\n"
" agr %1,%4\n"
"1:\n"
: "+d" (reg4), "+d" (reg5)
: "d" (reg2), "d" (reg3), "d" (*rlen): "cc");
*rlen = reg5;
return reg4;
}
into this:
int diag8_response(int cmdlen, char *response, int *rlen)
{
unsigned long len = cmdlen | 0x40000000L;
asm volatile(
" diag %2,%0,0x8\n"
" brc 8,1f\n"
" agr %1,%4\n"
"1:\n"
: "+{r4}" (len), "+{r5}" (*rlen)
: "{r2}" ((addr_t)cpcmd_buf), "{r3}" ((addr_t)response), "d" (*rlen): "cc");
return len;
}
Apart from being much easier to read because the hard regs become part
of the inline assembly it solves also a couple of other issues:
- function calls might clobber register asm variables see BZ100908
- the constraints for the register asm operands are superfluous
- one register asm variable cannot be used for 2 different inline
assemblies if the value is expected in different hard regs
I've started with a hackish implementation for IBM Z using the
TARGET_MD_ASM_ADJUST hook and let all the places parsing constraints
skip over the {} parts. But perhaps it would be useful to make this a
generic mechanism for all targets?!
Andreas
More information about the Gcc
mailing list