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