Search code examples
assemblygccx86inline-assemblycpu-registers

GCC inline assembler, mixing register sizes (x86)


Does anyone know how I can get rid of the following assembler warning?

Code is x86, 32 bit:

int test (int x)
{
  int y;
  // do a bit-rotate by 8 on the lower word. leave upper word intact.
  asm ("rorw $8, %0\n\t": "=q"(y) :"0"(x));
  return y;
}

If I compile it I get the following (very valid) warning:

Warning: using `%ax' instead of `%eax' due to `w' suffix

What I'm looking for is a way to tell the compiler/assembler that I want to access the lower 16 bit sub-register of %0. Accessing the byte sub-registers (in this case AL and AH) would be nice to know as well.

I've already chosen the "q" modifier, so the compiler is forced to use EAX, EBX, ECX or EDX. I've made sure the compiler has to pick a register that has sub-registers.

I know that I can force the asm-code to use a specific register (and its sub-registers), but I want to leave the register-allocation job up to the compiler.


Solution

  • You can use %w0 if I remember right. I just tested it, too. :-)

    int
    test(int x)
    {
        int y;
        asm ("rorw $8, %w0" : "=q" (y) : "0" (x));
        return y;
    }
    

    Edit: In response to the OP, yes, you can do the following too:

    int
    test(int x)
    {
        int y;
        asm ("xchg %b0, %h0" : "=Q" (y) : "0" (x));
        return y;
    }
    

    For x86 it's documented in the x86 Operand Modifiers section of the Extended Asm part of the manual.

    For non-x86 instruction sets, you may have to dig through their .md files in the GCC source. For example, gcc/config/i386/i386.md was the only place to find this before it was officially documented.

    (Related: In GNU C inline asm, what are the size-override modifiers for xmm/ymm/zmm for a single operand? for vector registers.)