--- Andrew Haley <[EMAIL PROTECTED]> wrote:
> Etienne Lorrain writes:
> > > The correct version is I think,
> > >
> > > void longcpy(long* _dst, long* _src, unsigned _numwords)
> > > {
> > > asm volatile (
> > > "cld \n\t"
> > > "rep \n\t"
> > > "movsl \n\t"
> > > // Outputs (read/write)
> > > : "=S" (_src), "=D" (_dst), "=c" (_numwords)
> > > // Inputs - specify same registers as outputs
> > > : "0" (_src), "1" (_dst), "2" (_numwords)
> > > // Clobbers: direction flag, so "cc", and "memory"
> > > : "cc", "memory"
> > > );
> > > }
> >
> > I did not re-check with GCC-4.1.1, but I noticed problems with this
> > kind of "memory" clobber: when the source you are copying from is
> > not in memory but (is a structure) in the stack. I have to say that
> > I tend to use a form without "volatile" after the asm (one of the
> > result has to be used then).
> >
> > The usual symtom is that the memcopy is done, but the *content* of the
> > source structure is not updated *before* the memcopy: nothing in your
> > asm says that the content of your pointer has to be up-to-date.
> >
> > The "memory" says that main memory will be changed, not that it will be
> > used, and if you are memcopy-ing from a structure in stack - for instance
> > a structure which fit in a register - you may have problems.
>
> Why, exactly? the structure has its address taken, and therefore at
> the point at which the asm is invoked it'll be in memory.
Well, first I am not sure it is still happening with GCC-4.1.1, and two I
never got a reasonnable test case else you would have seen a bug report.
The last time I noticed it was when I had to modify my file xms.h from:
extern inline unsigned short
_XMS_move_memory (farptr entrypoint, XMS_EMM *emm_struct,
unsigned char *error)
{
unsigned short status;
asm volatile (" lcallw *%a4 # XMS entry point, _XMS_move_memory "
: "=a" (status), "=b" (*error)
: "a" (0x0B00), "S" (emm_struct) /* %ds:%si */,
"pr" (&entrypoint)
);
if (status == 0x0001)
return 0; /* OK */
else
return 1; /* failed */
}
to:
extern inline unsigned short
_XMS_move_memory (farptr entrypoint, XMS_EMM *emm_struct,
unsigned char *error)
{
unsigned short status;
asm volatile (" lcallw *%a4 # XMS entry point, _XMS_move_memory "
: "=a" (status), "=b" (*error)
: "a" (0x0B00), "S" (emm_struct) /* %ds:%si */,
"pr" (&entrypoint), "m" (*emm_struct)
);
if (status == 0x0001)
return 0; /* OK */
else
return 1; /* failed */
}
With the first version Gujin (at sourceforge) does not work, with the second
it does work - that function is inline in another big function so the assembler
is not easy to read. emm_struct is a resonnably complex structure in the stack.
I had to do this in few other include files with "m"(*ptr) or "X"(*ptr) for the
same project in v1.4.
> For sure,
> if you fail to use volatile the compiler may decide that the asm can
> be deleted. So use volatile: that's what it's for.
I do not want the asm to be deleted when it is used, but in some case the
compiler
sees that I am not using the result and so I want GCC to delete the asm.
Consider:
inline void longcpy(long* _dst, long* _src, unsigned _numwords);
inline void fct (long array[3], int doit)
{
long safe_copy[3];
longcpy(safe_copy, array, 3);
if (!doit)
return; /* safe_copy not used at all, remove the variable and the asm() */
....;
}
void fct2(void) { fct (x, 0); }
> If the compiler fails to write a struct to memory before the asm is
> executed, that's a bug in the compiler.
It you just said GCC that the pointer is read I am not sure it is assuming
that the content of this pointer is read - I may be wrong.
Etienne.
__________________________________________________
Do You Yahoo!?
En finir avec le spam? Yahoo! Mail vous offre la meilleure protection possible
contre les messages non sollicités
http://mail.yahoo.fr Yahoo! Mail