RE: Pb with G++ 3.4.2 MinGW and inline assembly V2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx>
To: "Studious Apprentice" <apprentice_99@xxxxxxxxxxx>,<gcc-help@xxxxxxxxxxx>
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@xxxxxxxxxxx]
Sent: Thursday, February 09, 2006 9:27 AM
To: gcc-help@xxxxxxxxxxx
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"
//		);
//}





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux