inline assembly & r0 SOS

6 messages, 5 authors, 2008-08-06 · open the first message on its own page

inline assembly & r0 SOS

From: Kevin Diggs <hidden>
Date: 2008-08-06 00:24:00

Hi,

If I have:

inline unsigned int get_PLL_range(unsigned int range, unsigned int
        config)
{
unsigned int ret;

        /*
         * Turn r3 (range) into a rotate count for the selected range.
         * 0 -> 23, 1 -> 31
         */
        __asm__ __volatile__ (  "slwi %0,%0,3\n"
                                "addi %0,%0,23\n"
                                "rlwnm %0,%1,%0,30,31\n":
                "=r"(ret):
                "r"(config),"0"(range)
        );

        return ret;
}

in a header and the resultant code generated is:

.L58:
        li 0,1   # ratio,
        mr 29,0  # ret, ratio
#APP
        slwi 29,29,3     # ret
addi 29,29,21    # ret
rlwnm 29,28,29,27,31     # ret, ret

        slwi 0,0,3       # ret
addi 0,0,23      # ret
rlwnm 0,28,0,30,31       # ret, ret

#NO_APP

thats bad right? Because the "addi 0, 0, 23" will not work as expected because of the "special property" of r0. FYI:  The first three lines after the "#APP" are from a similar function get_PLL_ratio().

4 more lines

Re: inline assembly & r0 SOS

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: 2008-08-06 00:35:24

On Tue, 2008-08-05 at 17:20 -0700, Kevin Diggs wrote:
Hi,
thats bad right? Because the "addi 0, 0, 23" will not work as expected 
because of the "special property" of r0. FYI:  The first three lines 
after the "#APP" are from a similar function get_PLL_ratio().

	Is there a way to blacklist r0?
Yes. Use "b" instead of "r" in the constraints to force the compiler
to avoid r0 when assigning a register.

Cheers,
Ben.

Re: inline assembly & r0 SOS

From: Jeremy Kerr <jk@ozlabs.org>
Date: 2008-08-06 00:41:50

Hi Kevin,
         /*
          * Turn r3 (range) into a rotate count for the selected
range. * 0 -> 23, 1 -> 31
          */
         __asm__ __volatile__ (  "slwi %0,%0,3\n"
                                 "addi %0,%0,23\n"
                                 "rlwnm %0,%1,%0,30,31\n":
                 "=r"(ret):
                 "r"(config),"0"(range)
         );
Wouldn't this be much simpler in plain C?

However, if you really do need to do this in inline asm, you can use 
the "b" modifier rather than "r" to avoid using r0.

Cheers,


Jeremy

Re: inline assembly & r0 SOS

From: Kevin Diggs <hidden>
Date: 2008-08-06 02:34:56

Jeremy Kerr wrote:
Hi Kevin,

quoted
        /*
         * Turn r3 (range) into a rotate count for the selected
range. * 0 -> 23, 1 -> 31
         */
        __asm__ __volatile__ (  "slwi %0,%0,3\n"
                                "addi %0,%0,23\n"
                                "rlwnm %0,%1,%0,30,31\n":
                "=r"(ret):
                "r"(config),"0"(range)
        );

Wouldn't this be much simpler in plain C?
I just knew someone was gonna try to rain on my rlwnm'in fun parade! Wonder if the C code can be made to compile down to 3 instructions?
However, if you really do need to do this in inline asm, you can use the "b" modifier rather than "r" to avoid using r0.
Oh cool! Thanks! You to Ben!
Cheers,


Jeremy
kevin

Re: inline assembly & r0 SOS

From: Andreas Schwab <hidden>
Date: 2008-08-06 08:49:55

Kevin Diggs [off-list ref] writes:
Jeremy Kerr wrote:
quoted
Hi Kevin,

quoted
        /*
         * Turn r3 (range) into a rotate count for the selected
range. * 0 -> 23, 1 -> 31
         */
        __asm__ __volatile__ (  "slwi %0,%0,3\n"
                                "addi %0,%0,23\n"
                                "rlwnm %0,%1,%0,30,31\n":
                "=r"(ret):
                "r"(config),"0"(range)
        );

Wouldn't this be much simpler in plain C?
I just knew someone was gonna try to rain on my rlwnm'in fun parade!
Wonder if the C code can be made to compile down to 3 instructions?
This will do:

unsigned int get_PLL_range(unsigned int range, unsigned int config)
{
  range = range * 8 + 23;
  return ((config << range) | (config >> (32 - range))) & 3;
}

The special pattern ((a << n) | (a >> (32 - n))) is recognized by gcc as
a rotate operation.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

Re: inline assembly & r0 SOS

From: Segher Boessenkool <hidden>
Date: 2008-08-06 14:39:44

quoted
quoted
quoted
unsigned int get_PLL_range(unsigned int range, unsigned int config)
{
  range = range * 8 + 23;
  return ((config << range) | (config >> (32 - range))) & 3;
}

The special pattern ((a << n) | (a >> (32 - n))) is recognized by gcc as
a rotate operation.
It's only valid for 1 <= n <= 31 though, so for input "range" 0 or 1. (*)
If that's the whole range needed, much simpler code is possible...


Segher

(*) or 0xffffffff or 0xfffffffe, but somehow I doubt that was intended.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help