Inline assembly and clobbered registers
Ian Lance Taylor
iant@google.com
Sat Oct 23 22:46:00 GMT 2010
ludo@gnu.org (Ludovic Courtès) writes:
> I’m trying to use ‘asm goto’ with GCC 4.5 to implement tagged integer
> arithmetic for Guile’s VM. For instance, the addition of X and Y looks
> like this:
>
> {
> SCM result = y;
> asm volatile goto ("add %0, %[result]; jo %l[slow_add]; "
> "sub %[tag], %[result]; "
> "test %[tag], %[result]; "
> "je %l[slow_add]; "
> "mov %[result], (%[vsp])\n"
> : /* no output */
> : "r" (x), [result] "r" (result),
> [vsp] "r" (sp), [tag] "i" (scm_tc2_int)
> : "memory"
> : slow_add);
> NEXT; /* Jump to the next virtual IP. */
> }
> slow_add:
> /* Add X and Y the slow way, using bignums if needed. */
>
> However, this doesn’t work because GCC doesn’t allocate any new register
> for ‘result’ (which it is allowed to do given that ‘result’ is an
> input), so the ‘test’ instruction modifies ‘y’, and we may jump to
> ‘slow_add’ with an erroneous value of ‘y’.
>
> I could add a clobber for a specific register and use that to store the
> intermediate result, but I’d rather let GCC choose a register for me.
> Unfortunately, only specific register names are allowed in the clobber
> list, so I can’t, e.g., use the ‘r’ constraint to achieve this.
>
> Any idea how I can work around this?
When your asm modifies a register, you need to tell gcc that that is
happening. E.g., list the value in the list of outputs and give it a +
constraint.
I don't see any reason to put the final mov in the asm, in which case
you don't have to clobber memory. I would go for something more like
this:
asm volatile goto ("add %[addend], %[result]; "
"jo %l[slow_add]; "
"test %[tag], %[result]; "
"je %l[slow_add]"
: [result] "+r" (result)
: [addend] "r" (x), [tag] "i" (scm_tc2_int)
: /* no clobbers */
: slow_add);
*vsp = result;
NEXT;
Ian
More information about the Gcc-help
mailing list