Re: Inline assembly and clobbered registers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



ludo@xxxxxxx (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



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux