Author: Dieter Buerssner
Date: 04:20:11 02/20/04
Go up one level in this thread
On February 19, 2004 at 22:39:47, Robert Hyatt wrote: >On February 19, 2004 at 16:44:38, Dieter Buerssner wrote: > >>On February 19, 2004 at 16:16:23, Robert Hyatt wrote: >> >>>I looked at my old inline asm docs, and I found the following statement, >>>paraphrased: >>> >>>"you don't need to put gcc-allocated registers on the clobber list, it knows you >>>are fooling with them." >> >>That's news to me. I cannot find it in my gcc manual (and I know, that it did >>not work with earlier gcc versions). >> >>Some snippets of my gcc manual: >> >>--- >>The compiler cannot check whether the operands have data types that are >>reasonable for the instruction being executed. It does not parse the assembler >>instruction template and does not know what it means or even whether it is valid >>assembler input. >> >>[...] >> Some instructions clobber specific hard registers. To describe this, > ^^^^^^^^^^^^^^^ > >I am keying on that in your quote. "hard register" as opposed to "dynamically >assigned register"... I won't say that is a correct interpretation, of course. >The syntax is not horrible for inline asm, but the documentation leaves a lot to >be desired, clarity-wise... To me, it looks rather clear, that you must notify the compiler, if you modify an input operand. Later in the Gcc manula, it is also explicetly mentioned, that they are assumed as read only operands. It is also mentioned, that it does not try at all, to understand the inline assembler, it just puts in the real operands instead of the %0/1/2... A little test case. Your popcount slightly modified, so that the input will be used later (it might happen similarily in real code when inlining). int bob(unsigned long a, unsigned long b) { /* r0=result, %1=tmp, %2=first input, %3=second input */ long dummy, dummy2; asm(" xorl %0, %0" "\n\t" " testl %2, %2" "\n\t" " jz 2f" "\n\t" "1: leal -1(%2), %1" "\n\t" " incl %0" "\n\t" " andl %1, %2" "\n\t" " jnz 1b" "\n\t" "2: testl %3, %3" "\n\t" " jz 4f" "\n\t" "3: leal -1(%3), %1" "\n\t" " incl %0" "\n\t" " andl %1, %3" "\n\t" " jnz 3b" "\n\t" "4:" "\n\t" : "=&q" (dummy), "=&q" (dummy2) : "q" (a), "q" (b) : "cc"); return dummy+a+b; } /* Too lazy, to format nicely, also really untested */ int dieter(unsigned long a, unsigned long b) { int tmp, tmp2, n; __asm__ __volatile__( "movl %3, %1 \n\t" "xorl %0, %0 \n\t" "testl %1, %1 \n\t" "je 1f \n\t" "0: incl %0 \n\t" "leal -1(%1), %2 \n\t" "andl %2, %1 \n\t" "jne 0b \n\t" "1: movl %4, %1 \n\t" "testl %1, %1 \n\t" "je 3f \n\t" "2: incl %0 \n\t" "leal -1(%1), %2 \n\t" "andl %2, %1 \n\t" "jne 2b \n\t" "3:" : "=r&" (n), "=r&" (tmp), "=r&" (tmp2) : "g" (a), "g" (b) : "cc" /* Flags "condition code" changed */); return n+a+b; } gcc -O -S produces (I added some ; comments): .file "bob.c" .section .text .p2align 1 .globl _bob _bob: pushl %ebp movl %esp, %ebp pushl %ebx movl 8(%ebp), %edx ; a to edx movl 12(%ebp), %ecx ; b to ecx /APP xorl %eax, %eax testl %edx, %edx jz 2f 1: leal -1(%edx), %ebx incl %eax andl %ebx, %edx ; edx modified jnz 1b 2: testl %ecx, %ecx jz 4f 3: leal -1(%ecx), %ebx incl %eax andl %ebx, %ecx ; ecx modified jnz 3b 4: /NO_APP addl %edx, %eax ; oops using edx again, thinking it is not modified addl %ecx, %eax ; ditto ecx popl %ebx popl %ebp ret .p2align 1 .globl _dieter _dieter: pushl %ebp movl %esp, %ebp pushl %esi pushl %ebx movl 8(%ebp), %edx movl 12(%ebp), %ecx /APP movl %edx, %esi xorl %eax, %eax testl %esi, %esi je 1f 0: incl %eax leal -1(%esi), %ebx andl %ebx, %esi jne 0b 1: movl %ecx, %esi testl %esi, %esi je 3f 2: incl %eax leal -1(%esi), %ebx andl %ebx, %esi jne 2b 3: /NO_APP ; using unmodified a and b here addl %edx, %eax addl %ecx, %eax popl %ebx popl %esi popl %ebp ret .ident "GCC: (GNU) 3.2" Regards, Dieter
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.