c++ - Calling convention mismatch for x64 floating point functions -
i'm having weird error. have 1 module compiled 1 compiler (msvc in case), calls code loaded module compiled seperate compiler (tcc).
the tcc code provides callback function both modules defined this:
typedef float( * scalefunc)(float value, float _min, float _max);
the msvc code calls code this:
finalvalue = extscale(val, _min, _max); 000007feecafcf52 mov rax,qword ptr [this] 000007feecafcf5a movss xmm2,dword ptr [rax+0d0h] 000007feecafcf62 mov rax,qword ptr [this] 000007feecafcf6a movss xmm1,dword ptr [rax+0cch] 000007feecafcf72 movss xmm0,dword ptr [val] 000007feecafcf78 mov rax,qword ptr [this] 000007feecafcf80 call qword ptr [rax+0b8h] 000007feecafcf86 movss dword ptr [finalvalue],xmm0
and function compiled tcc looks this:
float linear_scale(float value, float _min, float _max) { return value * (_max - _min) + _min; } 0000000000503dc4 push rbp 0000000000503dc5 mov rbp,rsp 0000000000503dc8 sub rsp,0 0000000000503dcf mov qword ptr [rbp+10h],rcx 0000000000503dd3 mov qword ptr [rbp+18h],rdx 0000000000503dd7 mov qword ptr [rbp+20h],r8 0000000000503ddb movd xmm0,dword ptr [rbp+20h] 0000000000503de0 subss xmm0,dword ptr [rbp+18h] 0000000000503de5 movq xmm1,xmm0 0000000000503de9 movd xmm0,dword ptr [rbp+10h] 0000000000503dee mulss xmm0,xmm1 0000000000503df2 addss xmm0,dword ptr [rbp+18h] 0000000000503df7 jmp 0000000000503dfc 0000000000503dfc leave 0000000000503dfd ret
it seems tcc expects arguments in integer registers r6 r8, while msvc puts them in sse registers. thought x64 (on windows) defines 1 common calling convention? going on here, , how can enforce same model on both platforms?
the same code works correctly in 32-bit mode. weirdly enough, on osx (where other code compiled llvm) works in both modes (32 , 64-bit). ill see if can fetch assembly there, later.
---- edit ----
i have created working solution. however, without doubt, dirtiest hack i've ever made (bar questionable inline assembly, unfortunately isn't available on msvc 64-bit :)).
// passes first 3 floating point arguments in r6 r8 template<typename ssetype> ssetype tccassemblyhelper(scalefunc cb, ssetype val, ssetype _min, ssetype _max) { ssetype xmm0(val), xmm1(_min), xmm2(_max); long long rcx, rdx, r8; rcx = *(long long*)&xmm0; rdx = *(long long*)&xmm1; r8 = *(long long*)&xmm2; typedef float(*intermedfunc)(long long rcx, long long rdx, long long r8); intermedfunc helperfunc = reinterpret_cast<intermedfunc>(cb); return helperfunc(rcx, rdx, r8); }
Comments
Post a Comment