assembly inside C, an old code to a new code problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Slex
Posts: 3
Joined: Wed Oct 10, 2012 10:29 am

assembly inside C, an old code to a new code problem

Post 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
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: assembly inside C, an old code to a new code problem

Post by bluemoon »

Try replace things like "%edi" with "edi".
Slex
Posts: 3
Joined: Wed Oct 10, 2012 10:29 am

Re: assembly inside C, an old code to a new code problem

Post by Slex »

doesn't work :(
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: assembly inside C, an old code to a new code problem

Post 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.
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: assembly inside C, an old code to a new code problem

Post 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));
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Slex
Posts: 3
Joined: Wed Oct 10, 2012 10:29 am

Re: assembly inside C, an old code to a new code problem

Post 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:
Post Reply