SOLVED: BUG: AngelScript 2.20.2 - Mac OS X - 64-bit compilation doesn't work - g++ 4.2.1

Started by
27 comments, last by kainjow 13 years, 1 month ago
as_callfunc_x64_gcc.cpp does not compile correctly.


The following output is produced using "angelscript/projects/gnuc macosx/makefile":
mkdir obj
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_atomic.o -c ../../source/as_atomic.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_builder.o -c ../../source/as_builder.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_bytecode.o -c ../../source/as_bytecode.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc.o -c ../../source/as_callfunc.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_arm.o -c ../../source/as_callfunc_arm.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_mips.o -c ../../source/as_callfunc_mips.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_ppc.o -c ../../source/as_callfunc_ppc.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_ppc_64.o -c ../../source/as_callfunc_ppc_64.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_sh4.o -c ../../source/as_callfunc_sh4.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_x86.o -c ../../source/as_callfunc_x86.cpp
c++ -g -Wall -fPIC -arch i386 -arch x86_64 -o obj/as_callfunc_x64_gcc.o -c ../../source/as_callfunc_x64_gcc.cpp
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:170:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:173:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:176:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:179:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:182:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:185:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:188:suffix or operands invalid for `movq'
/var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccQb3SXj.s:191:suffix or operands invalid for `movq'
lipo: can't open input file: /var/folders/iG/iGgRv-pOHVq8lMdjYzTz0E+++TI/-Tmp-//ccDlZLXb.out (No such file or directory)
make: *** [obj/as_callfunc_x64_gcc.o] Error 1



Which seems to correspond to the following lines in as_callfunc_x64_gcc.cpp
POP_LONG( "%xmm7" );
POP_LONG( "%xmm6" );
POP_LONG( "%xmm5" );
POP_LONG( "%xmm4" );
POP_LONG( "%xmm3" );
POP_LONG( "%xmm2" );
POP_LONG( "%xmm1" );
POP_LONG( "%xmm0" );


Moving from a general purpose register to an xmm register doesn't seem to be supported, only xmm to xmm, memory to xmm and xmm to memory. According to this

I'm by no means an assembly programmer but wouldn't it be possible to just use movq using the stack pointer to reference memory and then pop into rax after the move?
Maybe something like this?
#define POP_LONG( reg ) \
__asm__ __volatile__ ( \
"add %%rsp, 8\n" \
"movq (%%rsp), %" reg \
: \
: \
: reg \
)
Advertisement
I wish I could test this, but I don't have a 64bit mac.

Anyway the problem is most likely caused by the latest changes in the file. Can you help me determine which revision from the svn was the latest to still work?

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I'll try that and let you know.
r596 seems to be the latest one that compiles.

But both test_feature and test_performance fail.
Hmm. That version of the file is very old and is no longer compatible with the current library code. Version 640 was the one that introduced the new assembly code, and it was contributed by a Mac developer that couldn't compile the previous version.

I think the problem you're having is because of a difference in the compiler version that you use. I think it is necessary to write the assembly code slightly differently depending on the version of the compiler.

Which xcode version are you using, and which version of gcc is it using (it should hopefully appear in the build logs)?

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I'm using XCode 3.2.5 (1760) which has gcc 4.2.1 (Apple Inc. build 5664)

I did a little testing using nasm and otool. Here are the files I used:

Makefileall: libctest.o
gcc -m64 -mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk -o libctest libctest.o

libctest.o: libctest.asm
nasm -f macho64 -o libctest.o libctest.asm


libctest.asmsection .data
message: db 'xmm0 contents %016lx', 10, 0
messagelen: equ $ - message

section .bss
xmmcontents: resq 1

section .text
default rel

extern _printf
global _main

_main:
push qword rbp
mov rbp, rsp

mov rsi, 0xcafebabefeedface
movq xmm0, rsi
movq qword [xmmcontents], xmm0

mov rdi, qword message
mov rsi, qword [xmmcontents]
xor eax, eax
call _printf

mov eax, 0
leave
ret


And here is the disassembly from otool -tVlibctest:
(__TEXT,__text) section
start:
0000000100000ecc pushq $0x00
0000000100000ece movq %rsp,%rbp
0000000100000ed1 andq $0xf0,%rsp
0000000100000ed5 movq 0x08(%rbp),%rdi
0000000100000ed9 leaq 0x10(%rbp),%rsi
0000000100000edd movl %edi,%edx
0000000100000edf addl $0x01,%edx
0000000100000ee2 shll $0x03,%edx
0000000100000ee5 addq %rsi,%rdx
0000000100000ee8 movq %rdx,%rcx
0000000100000eeb jmp 0x100000ef1
0000000100000eed addq $0x08,%rcx
0000000100000ef1 cmpq $0x00,(%rcx)
0000000100000ef5 jne 0x200000eed
0000000100000ef7 addq $0x08,%rcx
0000000100000efb callq _main
0000000100000f00 movl %eax,%edi
0000000100000f02 callq 0x100000f5c ; symbol stub for: _exit
0000000100000f07 hlt
dyld_stub_binding_helper:
0000000100000f08 pushq %r11
0000000100000f0a leaq 0xfffff0ef(%rip),%r11
0000000100000f11 pushq %r11
0000000100000f13 jmp *0x000000e7(%rip)
0000000100000f19 nopl (%rax)
__dyld_func_lookup:
0000000100000f1c jmp *0x000000e6(%rip)
_main:
0000000100000f22 pushq %rbp
0000000100000f23 movq %rsp,%rbp
0000000100000f26 movq $0xcafebabefeedface,%rsi
0000000100000f30 movd %rsi,%xmm0
0000000100000f35 movq %xmm0,0x0000014d(%rip)
0000000100000f3d movq $message,%rdi
0000000100000f47 movq 0x0000013c(%rip),%rsi
0000000100000f4e xorl %eax,%eax
0000000100000f50 callq 0x100000f62 ; symbol stub for: _printf
0000000100000f55 movl $0x00000000,%eax
0000000100000f5a leave
0000000100000f5b ret


This will print out: xmm0 contents cafebabefeedface
So clearly all 64 bits are being moved into the xmmcontents variable.

According to the disassembly it seems that the correct instruction to move a qword from a general purpose register into an xmm register is not movq but movd.

This C code gives the same stdout printout as the above nasm code:#include <stdio.h>

#define PUSH_REGISTER( val ) \
__asm__ __volatile__ ( \
"movq %0, %%rax\n" \
"movd %%rax, %%xmm0" \
: \
: "m" ( val ) \
: "%rax", "%xmm0" \
)

#define POP_REGISTER( val ) \
__asm__ __volatile__ ( \
"movq %%xmm0, %0" \
: \
: "m" (val) \
)


long unsigned int g_mmxvalue = 0;

int main(int argc, char *argv[])
{
long unsigned int foo = 0xcafebabefeedfaceL;

PUSH_REGISTER(foo);
POP_REGISTER(g_mmxvalue);

printf("xmm0 contents %016lx\n", g_mmxvalue);

return 0;
}
Can you try the following code for the POP_LONG macro? It seems GNUC is doing some weirdness in order to keep backward compatibility. I suspect this has been changed for newer versions of GNUC, so I'll differentiate with the code for your version.


// While movq really should be used to move from general
// purpose register to xmm register, GNUC accepts movd for
// backward compatibility.
// http ://gcc.gnu.org/bugzilla/show_bug.cgi?id=43215
#if __GNUC__ <= 4 && __GNUC_MINOR__ <= 2
#define POP_LONG( reg ) \
__asm__ __volatile__ ( \
"popq %%rax\n" \
"movd %%rax, %" reg \
: \
: \
: "%rax", reg \
)
#else
#define POP_LONG( reg ) \
__asm__ __volatile__ ( \
"popq %%rax\n" \
"movq %%rax, %" reg \
: \
: \
: "%rax", reg \
)
#endif

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I got the same error, even with your changes.

However, using a test case I was able to get this to compile:

#define POP_LONG( reg ) \
__asm__ __volatile__ ( \
"popq %%rax\n" \
"movq %%rax, %" reg \
: \
: \
: "%rax", reg \
)

#define POP_LONG2( reg ) \
__asm__ __volatile__ ( \
"popq %%rax\n" \
"movd %%rax, %" reg \
: \
: \
: "%rax", reg \
)

int main(int argc, char *argv[])
{
POP_LONG("%r9");
POP_LONG2("%xmm0");
return 0;
}


It seems like it can't be movq or movd for both? My assembly knowledge is minimal so not even sure if this is right.

I'm wondering if there's some GCC setting that can be tweaked to make it work without the code change.
This POP_LONG macro works for the xmm registers but fails for the general purpose ones.
It seems that for general purpose -> xmm register the correct opcode is movd but for a general purpose -> general purpose register the correct opcode is movq.
I was reading the Intel opcode reference yesterday and the movq that does gp -> xmm is filed with movd but it's name is still given as movq.Clear as mud. rolleyes.gif
I think it is a bug in the version of GNUC that you're using that makes the movq not work with the xmm registers. This bug was fixed in a later version of GNUC, which is why others are able to compile the code just fine. According to the article I linked to they left the movd instruction for xmm registers for backwards compatibility, so it should be working even on the newer versions of GNUC.

Can you try kainjow's solution with two different versions of the POP_LONG macro, and then update the X64_CallFunction to use the right version with the right register?

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement