gcc-4 inline assembler question (no register in class 'GENERAL_REGS' error)

Enrico Scholz enrico.scholz at informatik.tu-chemnitz.de
Sun May 1 13:00:00 UTC 2005


Hello,

while trying to build qemu, I see errors in the inline
assembler. Investigating it shows that the problem is caused by code
like:


-----
typedef unsigned int	size_t;

#define offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
#define Xoffsetof(TYPE, MEMBER) (*(unsigned char*)offsetof(TYPE, MEMBER))

typedef struct {
    unsigned long regs[8];
} CPUState;

int foo()
{
  
  asm("    fs movl %0, %%eax\n"
      "    fs movl %1, %%ebx\n"
      "    fs movl %2, %%ecx\n"
      "    fs movl %3, %%edx\n"
      "    fs movl %4, %%esp\n"
      "    fs movl %5, %%ebp\n"
      "    fs movl %6, %%esi\n"   // **
      :
      : "m" (Xoffsetof(CPUState, regs[0])),
	"m" (Xoffsetof(CPUState, regs[1])),
	"m" (Xoffsetof(CPUState, regs[2])),
	"m" (Xoffsetof(CPUState, regs[3])),
	"m" (Xoffsetof(CPUState, regs[4])),
	"m" (Xoffsetof(CPUState, regs[5])), // **
	"m" (Xoffsetof(CPUState, regs[6]))
    );
}
-------

| $ gcc -c foo.c
| foo.c: In function 'foo':
| foo.c:11: error: can't find a register in class 'GENERAL_REGS' while reloading 'asm'


gcc32 does not have problems with it and generates code like:

| $ gcc32 -c foo.c
| $ objdump -d foo.o
| 00000000 <foo>:
|    0:   55                      push   %ebp
|    1:   89 e5                   mov    %esp,%ebp
|    3:   64 a1 00 00 00 00       mov    %fs:0x0,%eax
|    9:   64 8b 1d 04 00 00 00    mov    %fs:0x4,%ebx
|   10:   64 8b 0d 08 00 00 00    mov    %fs:0x8,%ecx
|   17:   64 8b 15 0c 00 00 00    mov    %fs:0xc,%edx
|   1e:   64 8b 25 10 00 00 00    mov    %fs:0x10,%esp
|   25:   64 8b 2d 14 00 00 00    mov    %fs:0x14,%ebp
|   2c:   64 8b 35 18 00 00 00    mov    %fs:0x18,%esi
|   33:   c9                      leave  
|   34:   c3                      ret   


Further investigations show that the removal of the lines marked with '**'
lets it succeed with gcc-4 also, and generates correct but ineffizient
code:

| $ gcc -c foo.c
| $ objdump -d foo.o
| 00000000 <foo>:
|    0:   55                      push   %ebp
|    1:   89 e5                   mov    %esp,%ebp
|    3:   57                      push   %edi
|    4:   56                      push   %esi
|    5:   53                      push   %ebx
|    6:   bf 00 00 00 00          mov    $0x0,%edi
|    b:   bb 04 00 00 00          mov    $0x4,%ebx
|   10:   be 08 00 00 00          mov    $0x8,%esi
|   15:   b9 0c 00 00 00          mov    $0xc,%ecx
|   1a:   ba 10 00 00 00          mov    $0x10,%edx
|   1f:   b8 18 00 00 00          mov    $0x18,%eax
|   24:   64 8b 07                mov    %fs:(%edi),%eax
|   27:   64 8b 1b                mov    %fs:(%ebx),%ebx
|   2a:   64 8b 0e                mov    %fs:(%esi),%ecx
|   2d:   64 8b 11                mov    %fs:(%ecx),%edx
|   30:   64 8b 22                mov    %fs:(%edx),%esp
|   33:   64 8b 28                mov    %fs:(%eax),%ebp
|   36:   5b                      pop    %ebx
|   37:   5e                      pop    %esi
|   38:   5f                      pop    %edi
|   39:   c9                      leave  
|   3a:   c3                      ret    


This explains why gcc-4 complains about the missing regs: it tries to
load the immediate offset values into general regs first and accesses
the memory based on them then. With more than 6 variables there are not
enough regs available.

Now my question: what is the correct way to achieve the first object
code with inline assembler? Using the specific registers as machine
constraints does not work as the posted assembly block happens within
more complex code in the real qemu code.

I tried things like

| asm("fs movl (%0),%%ebx" : : "i"(offsetof(CPUState, regs[1])))

already but it generates the wrong code ('mov    %fs:0x0,%ebx').




Enrico
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 480 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/fedora-devel-list/attachments/20050501/fe3d5b2c/attachment.sig>


More information about the fedora-devel-list mailing list