Advertisement

Native calling convention support for mingw x64

Started by August 11, 2011 07:11 PM
44 comments, last by WitchLord 13 years, 3 months ago
Unfortunately, your version produces the following error:
../../source/as_callfunc_x64_mingw.cpp:111:3: error: can't find a register in class 'GENERAL_REGS' while reloading 'asm'
../../source/as_callfunc_x64_mingw.cpp:111:3: error: 'asm' operand has impossible constraints
[/quote]
I'll try to fix it..

EDIT:
Ok, using -fomit-frame-pointer fixed that, however the proposed template produces offending code:
as_callfunc_x64_mingw.s: Assembler messages:
as_callfunc_x64_mingw.s:130: Error: unsupported for `mov'
[/quote]

...<------>movl<-->112(%rsp), %ebp
...
# Make room for at least 4 arguments even if there are less. When
# the compiler does optimizations for speed it may use these for.
# temporary storage.
mov %ebp,%rdi


Obviously, one can't mov ebp to rdi.. I wonder what msvc does in this case..
Ok, using g constraint for 'paramSize' somewhat worked but the produced code crashes without passing even a single test and looks quite suboptimal: http://e4m5.net/as_c...unc_x64_mingw.s

On a side note, just wanted to mention that I'm using the MSVC version of CallSystemFunctionNative
Advertisement
This is likely going to require a few trial-and-error iterations before we get it right.

Moving ebp to rdi should be possible, it's just a copy of the value in the register. I guess the compiler is just complaining that it needs to know the size qualifier. Try changing the instruction to 'movq' instead, or 'movd' if that doesn't work.

Yes, you should be using the MSVC version of the CallSystemFunctionNative.

Instead of omitting the frame pointer, you could try changing the operands to the following:

__asm__ __volatile__ (
...
same as before
...
  "# Call function\n"
  " call *%%r14\n"
  " lea  %0, %%rbx\n"     // Load the address of the ret variable into rbx
  " movq %%rax,(%%rbx)\n" // Copy the returned value into the ret variable
  : // no output  
  : "m" (ret), "a" (args), "b" (floatArgs), "c" (paramSize), "d" (func)
  : "%r14", "%rdi", "%rsi", "%rsp", "%r11", "%r12", "%r8", "%r9", "r13", "r15"
With this, you'll use one less register as the operands, as ret is accessed directly on the stack, and you'll also specify explicitly that the other 4 arguments will be passed in the rax, rbx, rcx, and rdx registers.

[EDIT] After re-reading the article I noticed I had forgotten the % on the registers in the clobber list. I'm not sure if it actually makes a difference, but it is probably best to add it, just in case.

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

Well, how would it know how exactly the value should be copied? it's a 32bit (since paramSize is declared as int) to 64bit copying.. so it's kinda logical that it fails on that instruction. and btw, neither of the movq variations work..
Any success with the other suggestion, i.e. changing to explicitly name the registers to use? That would make the copy be 'mov %rcx, %rdi', which should hopefully 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've actually changed it to %edi instead.. What IS suspicious is that %ebp register value is 0 at the time of the mov command..
The crash happens after the program leaves X64Call, with %rax register containing value '0x22f4a0'...

Btw, this prologue code looks weird to me:

subq $24, %rsp
.LCFI16:
movq rcx, 96(%rsp)
movq rdx, 104(%rsp)
movl r8d, 112(%rsp)
movq r9, 120(%rsp)
.LBB2:
.loc 2 47 0
movq 0, 8(%rsp)
.loc 2 113 0
movq 96(%rsp), %rax
movq 104(%rsp), %rbx
movl 112(%rsp), %ebp
movq 120(%rsp), %r10


wth is mingw trying to do there? :o
Advertisement
Another thing that bothers me is that even TestExecute now fails, when it's using MSVC's CallSystemFunctionNative.. With GCC's version at least THAT worked.
That EBP contains the value 0 at the time of the move command is correct. After all, the function that is being called has no parameters.



Here's my interpretation of the what the prologue does.


subq $24, %rsp // reserve 24 bytes on the stack
.LCFI16:
movq rcx, 96(%rsp) // backup the value of rcx on the stack -- args
movq rdx, 104(%rsp) // rdx -- floatArgs
movl r8d, 112(%rsp) // r8 (only 32 bits) -- paramSize
movq r9, 120(%rsp) // r9 -- func
.LBB2:
.loc 2 47 0
movq 0, 8(%rsp) // Move 0 into a local variable on the stack
.loc 2 113 0
movq 96(%rsp), %rax // read value previously stored in rcx into rax -- args
movq 104(%rsp), %rbx // rdx into rbx -- floatArgs
movl 112(%rsp), %ebp // r8 into ebp -- paramSize
movq 120(%rsp), %r10 // r9 into r10 -- func



The memory at offsets 96 to 120 is reserved already by the calling function.


I suggest you remove the -fomit-frame-pointer flag again. This might be what is causing the problems with the crashing after the call to X64Call.

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

It doesn't compile without -fomit-frame-pointer:
../../source/as_callfunc_x64_mingw.cpp:113:3: error: can't find a register in class 'GENERAL_REGS' while reloading 'asm'
../../source/as_callfunc_x64_mingw.cpp:113:3: error: 'asm' operand has impossible constraints
[/quote]

Frame pointers are only important for debugging anyway..

I think I'm going to abandon this soon, it isn't coding, it's messing around with stupid compiler settings, which ain't fun at all :/
I understand your position. It can be quite frustrating when no progress is made. I really don't think there is a lot of changes needed, but unfortunately I don't have the environment to do the testing myself.

I've gotten a lot of information out of this though. So if you do not wish to continue hopefully I will be able to arrange an environment sometime soon to make the changes myself. Or maybe someone else will pick up the challenge, and I'll be better positioned to guide him or her.

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