Несоответствие соглашения о вызовах для функций с плавающей запятой x64

У меня странная ошибка. У меня есть один модуль, скомпилированный одним компилятором (в данном случае msvc), который вызывает код, загруженный из другого модуля, скомпилированного отдельным компилятором (TCC).

Код tcc предоставляет функцию обратного вызова, которая для обоих модулей определяется следующим образом:

typedef float( * ScaleFunc)(float value, float _min, float _max);

Код MSVC вызывает код следующим образом:

    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

и функция, скомпилированная TCC, выглядит так:

    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

Кажется, что TCC ожидает аргументов в целочисленных регистрах от r6 до r8, в то время как msvc помещает их в регистры sse. Я думал, что x64 (на окнах) определяет одно общее соглашение о вызовах? Что именно здесь происходит, и как я могу применить одну и ту же модель на обеих платформах?

Этот же код работает правильно в 32-битном режиме. Как ни странно, в OSX (где другой код компилируется с помощью llvm) он работает в обоих режимах (32 и 64-битный). Я посмотрю, смогу ли я получить какое-то собрание оттуда позже.

—- редактировать —-

Я создал рабочее решение. Тем не менее, это, без сомнения, самый грязный хак, который я когда-либо делал (панель сомнительной встроенной сборки, к сожалению, она недоступна на 64-битном MSVC :)).

// passes first three floating point arguments in r6 to 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);
}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]