more gcc asm inline x86 help

Kanoj Sarcar (kanoj@babylon.engr.sgi.com)
Mon, 12 Oct 1998 15:03:45 -0700 (PDT)


Having gone thru Colin Plumb's/Alan Modra's material at

http://www.linuxhq.com/lnxlists/linux-kernel/lk_9804_03/msg01083.html

I have a few questions.

I am focusing on the section that says:

"& says that an output operand is written to before the inputs are
read, so this output must not be the same register as any input.
Without this, gcc may place an output and an input in the same
register even if not required by a "0" constraint. This is very
useful, but is mentioned here because it's specific to an alternative.
Unlike = and %, but like ?, you have to include it with each
alternative to which it applies."

Here' some example code that will run into problems when compiled
-O2:

static __inline__ int
addnew(int in1, int in2)
{
int out;

__asm__ __volatile__(
"movl $0, %0\n\t"
"addl %1, %0\n\t"
"addl %2, %0\n\t"
:"=r" (out)
:"r" (in1), "r" (in2));
return(out);
}

If you are not allowed to change the code in the asm block, the only
way to make this work would be to replace the output with
:"=&r" (out)
(gcc ends up picking eax to hold out and in1 otherwise).

I am confused about the algorithm that gcc follows to do register
allocation in asm blocks.

For example, in

asm("foo %1,%0" : "=r" (output) : "r" (input1), "0" (input2));

does gcc look at the output section first, input section first,
or at both? What about the clobber list? It has been pointed out
to me that a register can not be in the clobber list and in the
input or output list - but will a register in the clobber list
ever be picked to hold an input or output? In the above example,
is it legal for gcc to look at the output clause, assign %eax to
hold output, then scan the input clause, reassing %eax to hold
input1 (since there is no & modifier in the output clause, it
thinks it is free to do that), and seeing the "0" for input2,
again assign %eax to hold input2? Or does gcc go thru the input
clause first, making sure that input1 and input2 are in seperate
registers if their values are different, then assign the same
register for input2 to output? Or does gcc follow a more complex
multipass algorithm over the imput/output/clobber list? What about
registers that the programmer hard codes in to hold specific input/
output?

Not knowing the answers to the above questions, I am confused by
Colin Plumb's example towards the end of his mail, archived at

http://www.linuxhq.com/lnxlists/linux-kernel/lk_9804_03/msg01083.html

#define _set_tssldt_desc(n,addr,limit,type) \
__asm__ __volatile__ ("movw %w2,%0\n\t" \
"movw %w1,2+%0\n\t" \
"rorl $16,%1\n\t" \
"movb %b1,4+%0\n\t" \
"movb %3,5+%0\n\t" \
"movb $0,6+%0\n\t" \
"movb %h1,7+%0\n\t" \
"rorl $16,%1" \
: "=o"(*(n)) : "q" (addr), "ri"(limit), "i"(type))

What is the guarantee that the address "n" is not placed in register
%eax, and the input "addr" is also placed in the same register? Or
what is the guarantee that "n" does not collide with "limit" during
register assignment?

If anyone on the linux-kernel mailing list is responding, please
make sure your response is cross posted to gnu.gcc.help, or send
me a copy at kanoj@sgi.com, since I am not on the linux-kernel
list.

Thanks a lot for your time!!

Kanoj
kanoj@sgi.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/