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 :lol: