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
Attachment:
pgpFKKvy00DTk.pgp
Description: PGP signature
-- fedora-devel-list mailing list fedora-devel-list@xxxxxxxxxx http://www.redhat.com/mailman/listinfo/fedora-devel-list