Reputation: 597
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