Page 1 of 1

__constant_memcpy_fromfs function makes angry compiler

Posted: Wed Oct 08, 2008 6:12 pm
by piranha
I used (borrowed) some code from Linux-1.0, segment.h:

Code: Select all

static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n)
{
	switch (n) {
		case 0:
			return;
		case 1:
			*(char *)to = get_user_byte((const char *) from);
			return;
		case 2:
			*(short *)to = get_user_word((const short *) from);
			return;
		case 3:
			*(short *) to = get_user_word((const short *) from);
			*(char *) to = get_user_byte(2+(const char *) from);
			return;
		case 4:
			*(int *) to = get_user_long((const int *) from);
			return;
	}
#define COMMON(x) \
	__asm__("cld\n\t" \
	"rep ; fs ; movsl\n\t" \
	x \
	: /* no outputs*/  \
	:"c" (n/4),"D" ((long) to),"S" ((long) from) \
	:"cx","di","si","memory")

	switch (n % 4) {
		case 0:
			COMMON("");
			return;
		case 1:
			COMMON("fs ; movsb");
			return;
		case 2:
			COMMON("fs ; movsw");
			return;
		case 3:
			COMMON("fs ; movsw\n\tfs ; movsb");
			return;
	}
#undef COMMON
}
However, when I compile, I get:
include/segment.h: In function ‘__constant_memcpy_fromfs’:
include/segment.h:188: error: can't find a register in class ‘CREG’ while reloading ‘asm’
include/segment.h:191: error: can't find a register in class ‘CREG’ while reloading ‘asm’
include/segment.h:194: error: can't find a register in class ‘CREG’ while reloading ‘asm’
include/segment.h:197: error: can't find a register in class ‘CREG’ while reloading ‘asm’
include/segment.h:188: error: ‘asm’ operand has impossible constraints
include/segment.h:191: error: ‘asm’ operand has impossible constraints
include/segment.h:194: error: ‘asm’ operand has impossible constraints
include/segment.h:197: error: ‘asm’ operand has impossible constraints
Any idea why? I'm not that great with the asm, or gcc asm and such...
-JL

Re: __constant_memcpy_fromfs function makes angry compiler

Posted: Wed Oct 08, 2008 6:48 pm
by CodeCat
I just figured this one out today coincidentally.

The problem is that you're specifying "cx","di","si" as clobbered registers, but gcc assumes that the input registers are left untouched. So it gets stuck because it can't both assume a register is untouched and clobbered. The solution is to use a dummy output, like this:

Code: Select all

short d0, d1, d2;
   __asm__("cld\n\t" \
   "rep ; fs ; movsl\n\t" \
   x \
   :"=&c" (d0), "=&D" (d1), "=&S" (d2)  \
   :"0" (n/4),"1" ((long) to),"2" ((long) from) \
   :"memory")
Also don't forget to add "cc" to the clobber list, because you changed the flags (cld).

Re: __constant_memcpy_fromfs function makes angry compiler

Posted: Wed Oct 08, 2008 9:18 pm
by piranha
Thanks, that wokeded.

-JL