0

我有一个奇怪的错误。我有一个由一个编译器(在本例中为 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(在 Windows 上)定义了一种常见的调用约定?这里到底发生了什么,我如何在两个平台上执行相同的模型?

相同的代码在 32 位模式下也能正常工作。奇怪的是,在 OSX(其他代码由 llvm 编译)上,它可以在两种模式(32 位和 64 位)下工作。稍后我会看看我是否可以从那里获取一些组件。

- - 编辑 - -

我创建了一个可行的解决方案。然而,毫无疑问,这是我做过的最肮脏的 hack(禁止有问题的内联汇编,不幸的是它在 msvc 64 位上不可用:))。

// 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);
    }
4

0 回答 0