Please help. extended asm syntax unclearly documented.
Carlo Wood
carlo@alinoe.com
Mon Dec 16 05:12:00 GMT 2002
Hi,
I am having a very hard time understanding "extended asm" documentation.
I've studied it several days now and it seems that information missing;
things remain unclear :(.
For example, I still have the following questions:
1) Is it possible to defined a __asm__ definition that
specifies what will be the value of a certain (output)
register afterwards? And if is, how?
My guess is that this is not possible, but that would
a missing feature then imho.
Example:
__asm__ ("rep; stosl", ...
The use of 'rep' garantees that after this assembly code
%ecx equals to 0. But how to tell gcc that?
Same thing when we do:
__asm__ ("xorl %%eax,%%eax; rep; stosl", ...
One can add "%eax" to the clobber list, but how to tell
gcc that after this asm the value of %eax equals 0?
Often, in this case, %eax is passed as input:
"a" (0)
causing gcc to generate the leading 'xorl %%eax,%%eax'
itself, and hence knowing that eax is (still) zero
after the instruction if you don't specify it as output,
but that prefends using %eax as input register.
2) How to specify the clobber of a region of memory?
From the documentation is seems that this is not
possible but I am not sure.
For example, lets use the asm code that sets a given
memory range to zero:
int __d0, __d1;
__asm__ __volatile__
("cld ; rep ; stosl"
: "=c" (__d0),
"=D" (__d1),
: "a" (0),
"0" (count),
"1" (address)
: "memory", "cc"
);
this is the best I can make of it. It will fill
*address and up (in total 'count' integers) with 0.
It does NOT tell gcc that after this, ecx will be
0, edi will be address + count and that the memory
clobber is limited to the range [address, address + count>.
How can I tell gcc that only that specific range is
clobbered?
That this is unclearly documented might also show
from the fact that even the linux kernel contains
questionable code. For example, from
include/asm-i386/posix_types.h (kernel 2.4.18):
define __FD_ZERO(fdsetp) \
do { \
int __d0, __d1; \
__asm__ __volatile__("cld ; rep ; stosl" \
:"=m" (*(__kernel_fd_set *) (fdsetp)), \
"=&c" (__d0), "=&D" (__d1) \
:"a" (0), "1" (__FDSET_LONGS), \
"2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
} while (0)
It seems that they forgot to add "cc", and I don't understand
why they added the '&' in "=&c" and "=&D" in this case :(.
More importantly however - they added an output:
"=m" (*(__kernel_fd_set *) (fdsetp))
which seems totally redudant together with the "memory" as clobber.
Besides, that is only a single 32bit word in memory and not the
whole range :/.
Consider the actual documentation of gcc info:
"If your assembler instruction modifies memory in an unpredictable
fashion, add `memory' to the list of clobbered registers. This will
cause GCC to not keep memory values cached in registers across the
assembler instruction."
That seems clear so far. Then we get:
"You will also want to add the volatile keyword if the memory affected
is not listed in the inputs or outputs of the asm, as the `memory'
clobber does not count as a side-effect of the asm."
I am totally lost here. Add the volatile where? And why does it make
a difference if the memory is or is not listed as input/output?
Can someone please explain this last sentence to me with examples?
--
Carlo Wood <carlo@alinoe.com>
PS Please CC me, I am not subbed to this list.
More information about the Gcc
mailing list