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.01 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.