Messages in this thread | | | Date | Mon, 12 Oct 1998 15:03:45 -0700 (PDT) | From | (Kanoj Sarcar) | Subject | more gcc asm inline x86 help |
| |
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/
| |