Skip to contentSkip to conversation

inline assembly

DISCUSSION Kevin Diggs 3 participants 4 messages Jun 4, 2008 – Jun 5, 2008

lore
Share & tools
lore
#0 lore raw

Hi,

When doing inline assembly, is there a way to get the compiler to
assign "extra" (one not specified for inputs and outputs) registers? In the following:

                __asm__ __volatile__ (
                        "addi 5,%1,-1\n"
                        "andc 5,%1,5\n"
                        "cntlzw 5,5\n"
                        "subfic %0,5,31":
                        "=r"(j):
                        "r"(i)
                );

Can I get the compiler to choose a register for r5?

kevin

#1 lore raw
Quoted 14 lines · Kevin Diggs

Hi,

When doing inline assembly, is there a way to get the compiler to
assign "extra" (one not specified for inputs and outputs) registers? In the following:

                __asm__ __volatile__ (
                        "addi 5,%1,-1\n"
                        "andc 5,%1,5\n"
                        "cntlzw 5,5\n"
                        "subfic %0,5,31":
                        "=r"(j):
                        "r"(i)
                );
Quoted 1 line

Can I get the compiler to choose a register for r5?

Yes, like this:

int tmp;

asm volatile("addi %1, %2, -1;"

             "andc %1, %2, %1;"
             "cntlzw %1, %1;"
             "subfic %0, %1, 31" : "=r" (j), "=&r" (tmp) : "r" (i));

However, it'd be better to let the compiler do more, by just using the existing cntlzw() function.

-Scott

#2 lore raw
Quoted 6 lines · Scott Wood

int tmp;

asm volatile("addi %1, %2, -1;"

             "andc %1, %2, %1;"
             "cntlzw %1, %1;"
             "subfic %0, %1, 31" : "=r" (j), "=&r" (tmp) : "r" (i));

Registers are usually assumed to be 'long' in size, so I'd recommend using that rather than 'int' for tmp, though I suspect it'll make little difference (except, perhaps on x86 where you can partially use registers).

Quoted 2 lines

However, it'd be better to let the compiler do more, by just using the existing cntlzw() function.

Look in include/asm-powerpc/bitops.h. There are examples of the things you're trying to do:

	static __inline__ __attribute__((const))
	int __ilog2(unsigned long x)
	{
		int lz;

		asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
		return BITS_PER_LONG - 1 - lz;
	}

	static __inline__ int __ffs(unsigned long x)
	{
		return __ilog2(x & -x);
	}

Where:

asm-compat.h:79:#define PPC_CNTLZL stringify_in_c(cntlzd)
asm-compat.h:100:#define PPC_CNTLZL stringify_in_c(cntlzw)

Depending on whether you're in 32-bit mode or 64-bit mode.

David

#3 lore raw
Quoted 4 lines · David Howells
Quoted 2 lines · Scott Wood

int tmp;

Quoted 8 lines
Quoted 4 lines

asm volatile("addi %1, %2, -1;"

             "andc %1, %2, %1;"
             "cntlzw %1, %1;"
             "subfic %0, %1, 31" : "=r" (j), "=&r" (tmp) : "r" (i));

Registers are usually assumed to be 'long' in size, so I'd recommend using that rather than 'int' for tmp, though I suspect it'll make little difference (except, perhaps on x86 where you can partially use registers).

I had originally written that as long, but I changed it since the asm code is explicitly assuming 32-bit. It's more documentation than anything else.

-Scott