Pb with G++ 3.4.2 MinGW and inline assembly V2

Studious Apprentice apprentice_99@hotmail.com
Sat Feb 11 11:36:00 GMT 2006


Thanks a lot John! You have been of great help and answered all my questions 
;-) Regarding the "st" flag, I think you are right and this is for the FPU 
(I found it in code for fast float to int conversion). I am going to improve 
my code right now ;-)

It's really tricky not to reuse the register names but reference them by 
their numbers in the input zone (in the end, it should mean the same thing 
for the compiler), I dont think I would ever have thought of it ;-)

Thanks again,

Charles

>From: "John Yates" <jyates@netezza.com>
>To: "Studious Apprentice" 
><apprentice_99@hotmail.com>,<gcc-help@gcc.gnu.org>
>Subject: RE: Pb with G++ 3.4.2 MinGW and inline assembly V2
>Date: Fri, 10 Feb 2006 11:47:39 -0500
>
>Caveat.  I am still stuck with gcc 2.96.  I dug this out of something I
>wrote a few years back.  The main difference from your code is that I
>do not explicitly load esi, edi and ecx.  I get gcc's operand loading
>to do it.  The virtue is that gcc then can see those instructions and
>schedule them.  The key to achieving this is the decimal digit input
>operand constraint which says place the input operand in the same
>location as the N-th (0-based) output operand.
>
>inline void copy_foo(foo const* lhs, foo const* rhs)
>{
>     void*    discard_edi;
>     void*    discard_esi;
>     unsigned discard_ecx;
>
>     __asm__ __volatile__
>     (
>	"rep\n\t"
>	"movsl"
>
>     : "=D" (discard_edi)
>     , "=S" (discard_esi)
>     , "=c" (discard_ecx)
>
>     :  "0" (lhs)
>     ,  "1" (rhs)
>     ,  "2" (sizeof(foo)/4)
>
>     : "memory"
>     );
>  }
>
>You need to include "cc" in the clobber list if you include ANY
>instruction that modifies ANY condition code bit.  (I do not
>know whether that includes the x87 FP status bits.)  I am not
>familiar with "st" as a clobbered object.  Might it be the x87
>FPU's stack of 8 floating point temporaries?
>
>I have never worried about the DF.  I have just assumed that it is
>reset and that on exit from any asm that I write I must leave it in
>that state.
>
>/john
>
>-----Original Message-----
>From: Studious Apprentice [mailto:apprentice_99@hotmail.com]
>Sent: Thursday, February 09, 2006 9:27 AM
>To: gcc-help@gcc.gnu.org
>Subject: Pb with G++ 3.4.2 MinGW and inline assembly V2
>
>
>Thanks a lot for your answer John! Since then I managed to get this code
>working but I still have a few questions, for you or others ;-) :
>
>1.- Is there an official help for the clobbered register list and its use ?
>I could not find any relevant section in the GCC manual
>2.- Is there a place where I could find up to date examples (all example
>around the web I could find use registers in both input and clobbered list,
>which GCC no longer supports as far as I understand, and results in the
>compilation error  : can't find a register in class `CREG' while reloading
>`asm')
>3.- What is the difference in the clobber list between "cc" and "st"? When
>do I have to use them ? Only when I modified the flag registers and intend
>to read them thereafter or as soon as I use an instruction which might
>modify them ?
>4.- Is using "cld" or "std" instructions considered modifying the flags
>register ?
>5.- Is the proposed snippet I wrote below as good as it can be ?
>
>Thanks in advance,
>
>Charles
>
>
>I have made several versions of my assembly code until I got one perfectly
>working. I went through several pitfalls :
>- an early clobbered registers is not considered as clobbered register... 
>This
>means that though I put an ampersand in front of an input operant, GCC 
>would
>use it as if it had not changed thereafter...
>- an asm block which provides no output variable is optimized away by the
>compiler with the -O2 flag. This happens, even when the "memory" clobber is
>used... You have to use the __volatile__ keyword additionally...
>
>Here is the working version :
>{
>	uint32 dummy_ecx;
>	uint32 dummy_esi;
>	uint32 dummy_edi;
>	__asm__ __volatile__
>		(
>		"cld\n\t"
>		"movl %3, %%esi\n\t"
>		"movl %4, %%edi\n\t"
>		"movl %5, %%ecx\n\t"
>		"rep\n\t"
>		"movsl"
>		: "=&c"(dummy_ecx), "=&S"(dummy_esi), "=&D"(dummy_edi)
>		: "g"(from), "g"(where), "g"(times)
>		: "memory"
>		);
>}
>
>And here is all the snippets I tried :
>////First version (no clobber)
>//{
>//	__asm__ __volatile__
>//		(
>//		"cld\n\t"
>//		"rep\n\t"
>//		"movsl"
>//		:
>//	: "S"(from), "D"(where), "c"(times)
>//		: "memory"
>//		);
>//}
>//Version 2 (cant remember what happened on this one)
>//{
>//	std::size_t ecx_dummy;
>//	std::size_t esi_dummy;
>//	std::size_t edi_dummy;
>//	__asm__ __volatile__
>//		(
>//		"cld\n\t"
>//		"rep\n\t"
>//		"movsl"
>//		: "=S"(esi_dummy), "=D"(edi_dummy), "=c"(ecx_dummy)
>//		: "S"(from), "D"(where), "c"(times)
>//		: "memory"
>//		);
>//}
>//Version 3 (early clobber)
>//{
>//	__asm__
>//		(
>//		"cld\n\t"
>//		"movl %0, %%esi\n\t"
>//		"movl %1, %%edi\n\t"
>//		"movl %2, %%ecx\n\t"
>//		"rep\n\t"
>//		"movsl"
>//		:
>//		: "g"(from), "g"(where), "g"(times)
>//		: "%esi", "%edi", "%ecx", "memory"
>//		);
>//}
>//Version 4 (lacking volatile... should never had suppressed it...)
>//{
>//	uint32 dummy_ecx;
>//	uint32 dummy_esi;
>//	uint32 dummy_edi;
>//	__asm__
>//		(
>//		"cld\n\t"
>//		"movl %3, %%esi\n\t"
>//		"movl %4, %%edi\n\t"
>//		"movl %5, %%ecx\n\t"
>//		"rep\n\t"
>//		"movsl"
>//		: "=&c"(dummy_ecx), "=&S"(dummy_esi), "=&D"(dummy_edi)
>//		: "g"(from), "g"(where), "g"(times)
>//		: "memory"
>//		);
>//}
>//Version 5 (does not compile)
>//{
>//	uint32 dummy_ecx;
>//	uint32 dummy_esi;
>//	uint32 dummy_edi;
>//	__asm__ __volatile__
>//		(
>//		"cld\n\t"
>//		"rep\n\t"
>//		"movsl"
>//		: "=&c"(dummy_ecx), "=&S"(dummy_esi), "=&D"(dummy_edi)
>//		: "S"(from), "D"(where), "c"(times)
>//		: "memory"
>//		);
>//}
>
>




More information about the Gcc-help mailing list