Hi, On 6/24/19 1:19 PM, Zdenek Sojka wrote: > how does gcc choose the register arguments of an inline assembler and what > can I assume about the "unused" bits? The choice is made by the register allocator. You can't assume anything about the "unused" bits. The "r" register constraint means you get a whole register to use, of the wordsize of the machine. > My questions target the 64bit x86 architecture; I assume the behavior is the > same for all target triplets x86_64-*-* > > 1) does gcc always use register of size matching the size of the variable? No. > 2) can I assume anything about the high-order bits of the register? can I > overwrite them freely? No; yes. > 2a) does gcc use the "high" 8bit registers (ah, bh, ch, dh) for variable > allocation? No. > 2b) can gcc allocate different 8bit variables in the "low" and "high" > registers (eg. al/ah, bl/bh, ...)? > > > For variables of type: > > uint8_t a8, b8; > uint16_t a16, b16; > ... I think not, but I'm unsure. > Enforcing same-sized arguments: > a) > __asm__ ("movb %b1, %b0" : "=r"(a8) : "r"(b8)); > or > __asm__ ("movq %q1, %q0" : "=r"(a8) : "r"(b8)); > is always safe to do? (eg. moving 56bits of garbage won't hurt anything) > OR might gcc assume something about the high-order 56bits (eg. zero, sign-/ > zero-extension of the lower 8 bits), which might get broken by the move? If you ask for a register with the "r" constraint, all of that register is yours to use. > Assuming zero-extension: > __asm__ ("movw %w1, %w0" : "=r"(a16) : "r"((uint8_t)b16)); > or > __asm__ ("movw %w1, %w0" : "=r"(a16) : "r"(b8)); > does not seem to work (high-order 8 bits of a16 are garbage) That's how x86 works. -- Andrew Haley (he/him) Java Platform Lead Engineer Red Hat UK Ltd. <https://www.redhat.com> https://keybase.io/andrewhaley EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671