Page 1 of 1
assembly inside C, an old code to a new code problem
Posted: Wed Oct 10, 2012 10:36 am
by Slex
Hello everyone, i'm new, and i'm working on a old kernel for a little resear and to learn something.
During build i have this problem:
Code: Select all
error: can’t find a register in class ‘CREG’ while reloading ‘asm’
error: ‘asm’ operand has impossible constraints
the code is:
Code: Select all
static __inline void
insw(u_short port, void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\tinsw" :
: "d" (port), "D" (addr), "c" (cnt) : "%edi", "%ecx");
}
static __inline void
outsw(u_short port, void *addr, int cnt)
{
__asm __volatile("cld\n\trepne\n\toutsw" :
: "d" (port), "S" (addr), "c" (cnt) : "%esi", "%ecx");
}
How to modernize it for actual gcc versions?
gcc version 4.6.3
Thank you
Re: assembly inside C, an old code to a new code problem
Posted: Wed Oct 10, 2012 10:44 am
by bluemoon
Try replace things like "%edi" with "edi".
Re: assembly inside C, an old code to a new code problem
Posted: Wed Oct 10, 2012 10:54 am
by Slex
doesn't work
Re: assembly inside C, an old code to a new code problem
Posted: Wed Oct 10, 2012 11:07 am
by bluemoon
In fact I compile your code with gcc 4.6.3 (both i586 and x86_64 cross-compilers) without any warning nor error (but replaced u_short to uint16_t).
You may need to tweak your toolchain a bit.
Re: assembly inside C, an old code to a new code problem
Posted: Wed Oct 10, 2012 11:19 am
by xenos
Try this:
Code: Select all
static __inline void
insw(u_short port, void *addr, int cnt)
{
int edi, ecx;
__asm __volatile("cld\n\trepne\n\tinsw" :
"=D" (edi), "=c" (ecx) : "d" (port), "D" (addr), "c" (cnt) );
}
static __inline void
outsw(u_short port, void *addr, int cnt)
{
int esi, ecx;
__asm __volatile("cld\n\trepne\n\toutsw" :
"=S" (esi), "=c" (ecx) : "d" (port), "S" (addr), "c" (cnt) );
}
The reason is that an input register cannot be in the clobber list (
http://gcc.gnu.org/ml/gcc/1999-10n/msg00488.html):
Note that GCC will not use a clobbered register for inputs or outputs. GCC 2.7 would let you do it anyway, specifying an input in class "a" and saying that "ax" is clobbered. GCC 2.8 and egcs are getting pickeri, and complaining that there are no free registers in class "a" available. This is not the way to do it. If you corrput an input register, include a dummy output in the same register, the value of which is never used. E.g.
Code: Select all
int dummy;
asm("munge %0" : "=r" (dummy) : "0" (input));
Re: assembly inside C, an old code to a new code problem
Posted: Wed Oct 10, 2012 11:29 am
by Slex
XenOS wrote:Try this:
Code: Select all
static __inline void
insw(u_short port, void *addr, int cnt)
{
int edi, ecx;
__asm __volatile("cld\n\trepne\n\tinsw" :
"=D" (edi), "=c" (ecx) : "d" (port), "D" (addr), "c" (cnt) );
}
static __inline void
outsw(u_short port, void *addr, int cnt)
{
int esi, ecx;
__asm __volatile("cld\n\trepne\n\toutsw" :
"=S" (esi), "=c" (ecx) : "d" (port), "S" (addr), "c" (cnt) );
}
The reason is that an input register cannot be in the clobber list (
http://gcc.gnu.org/ml/gcc/1999-10n/msg00488.html):
Note that GCC will not use a clobbered register for inputs or outputs. GCC 2.7 would let you do it anyway, specifying an input in class "a" and saying that "ax" is clobbered. GCC 2.8 and egcs are getting pickeri, and complaining that there are no free registers in class "a" available. This is not the way to do it. If you corrput an input register, include a dummy output in the same register, the value of which is never used. E.g.
Code: Select all
int dummy;
asm("munge %0" : "=r" (dummy) : "0" (input));
Thank you very much, this worked
Probably is a driver that i don't need, precisly a hp ethernet driver, form the comments:
Code: Select all
This driver is for the Hewlett Packard PC LAN (27***) plus ethercards.
These cards are sold under several model numbers, usually 2724*.
but blocked the buid, so when i got all the kernel capable to compile and boot, i will delete this driver from makefiles
EDIT: The source is dated: 1994