Cecil Ward
Cecil Ward

Reputation: 597

In GCC inline asm, how do I allocate and reserve a register? (x86, GDC)

In GDC x86 in-line asm, I want to reserve a register that is going to be written to so that it does not clash with any other registers written to. (1) How should I do this? The code below works, so it appears, but I get the unpleasant feeling that this is only by good fortunate. (2) Is that so? (3) The xchg instruction does not really want to exchange a register with itself, so how do I ensure that I avoid that by reserving a distinct different register? 4) I feel almost like asking for "allocate register != rbx ? Or in fact more precisely != ( rax|rbx|rcx|rdx )) 5) Do I need to define an unused extra output?

asm pure nothrow @nogc {

    ".intel_syntax     " ~ "\n\t" ~

    "mov    %[save], rbx    \n\t" ~ /* save rbx optionally before cpuid trashes it, saved because the GDC compiler prefers it to be so */
    "cpuid                  \n\t" ~ /* writes to rax, rbx, rcx, rdx - and GDC is unhappy about bx */
    "xchg   rbx, %[save]    \n\t" ~ /* restore rbx, the cpuid output rbx value is now returned in save reg */
    
    ".att_syntax        \n"
    : /* outputs : */
            "=a"    ( ret.eax ),        // an lhs ref, write-only
      [ save ]  "=&r"   ( cpuid_rbx_out ),  /* =save - switched over to use (eg rsi) as an output */
                            /* instead of actual rbx */
            "=c"    ( ret.ecx ),
            "=d"    ( ret.edx )
    :   /* inputs : */
            "a"  ( in_eax )     // read
        // no ecx input in this variant
    :   /* no other clobbers */  /* does cpuid set flags? - think not, so no "cc" clobber reqd */
    ;
    }

The purpose of this snippet is to simply wrap the cpuid instruction, but also preserve rbx since the compiler is happier that way. If I omit this and merely mark rbx as an output then nothing goes wrong because the compiler does a push rbx / pop rbx outside the asm section. But I thought that a slightly faster trick might be to save rbx in a spare register assuming that there are some free, and return the rbx result from cpuid still but in a different register.

Upvotes: 0

Views: 130

Answers (0)

Related Questions