使用 MinGW 的浮点值调用约定错误

Wrong calling conventions with float values with MinGW

我正在尝试使用我的汇编函数处理 C 代码,发现 MinGw 不遵循浮点值的调用约定,这与 mingw 的版本不同。

单函数测试文件test.c

#include <xmmintrin.h>

float vector_dot(__m128 v1, __m128 v2)
{
     __m128 resp = _mm_mul_ps(v1, v2);
     float res;
     _mm_store_ss(&res, resp);
     return res;
};

编译成程序集

gcc -O -S test.c -msse4.1
    .file   "test.c"
    .text
    .globl  _vector_dot
    .def    _vector_dot;    .scl    2;  .type   32; .endef
_vector_dot:
LFB503:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    , %esp
    mulps   %xmm1, %xmm0
    movss   %xmm0, 12(%esp)
    flds    12(%esp)
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE503:
    .ident  "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"

float 结果存储到 ST0 寄存器,而不是 xmm0,就像在 linux

上一样

但在不同版本的 MinGW 中:

    .file   "test.c"
    .text
    .globl  vector_dot
    .def    vector_dot; .scl    2;  .type   32; .endef
    .seh_proc   vector_dot
vector_dot:
    .seh_endprologue
    movaps  (%rdx), %xmm0
    mulps   (%rcx), %xmm0
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0"

只有 2 条指令,参数在 xmm0、xmm1 中,结果在 xmm0 中,正如预期的那样。

但是,对于这个 mingw,来自 C 代码的函数调用在 rax 和 rdx 寄存器中有错误的参数

我的assemble

vector_dot: /* vector xmm0, vector xmm1 -> float xmm0 */
  mulps  %xmm1,%xmm0 

vector_horizontal_sum: /* vector xmm0 -> float xmm0 (0 + 1 + 2 + 3) */
   movshdup  %xmm0, %xmm1
   addps        %xmm1, %xmm0
   movhlps     %xmm0, %xmm1
   addss        %xmm1, %xmm0
   ret

C 中的函数头文件

extern float vector_dot(__m128 vector_1, __m128 vector_2) asm("vector_dot");

正在调用我的函数

    float values1[] __attribute__((aligned(16))) = { 1.3f, 5.4f, -4.f, 5. } ;
    __m128 vec1 = _mm_load_ps(values1);

    float values2[] __attribute__((aligned(16))) = {0.5f, -43.5f, 0, 0 };
    __m128 vec2 = _mm_load_ps(values2);

    float dot = vector_dot(vec1, vec2);

函数调用程序集,编译器未将 xmm 寄存器用于 args,导致我的程序崩溃

0x401614  <+  180>        0f 28 45 e0                 movaps -0x20(%rbp),%xmm0
0x401618  <+  184>        0f 29 85 40 ff ff ff        movaps %xmm0,-0xc0(%rbp)
0x40161f  <+  191>        0f 28 45 d0                 movaps -0x30(%rbp),%xmm0
0x401623  <+  195>        0f 29 85 30 ff ff ff        movaps %xmm0,-0xd0(%rbp)
0x40162a  <+  202>        48 8d 95 30 ff ff ff        lea    -0xd0(%rbp),%rdx
0x401631  <+  209>        48 8d 85 40 ff ff ff        lea    -0xc0(%rbp),%rax
0x401638  <+  216>        48 89 c1                    mov    %rax,%rcx
0x40163b  <+  219>        e8 d4 29 00 00              callq  0x404014 <vector_dot>
0x401640  <+  224>        66 0f 7e c0                 movd   %xmm0,%eax
0x401644  <+  228>        89 45 cc                    mov    %eax,-0x34(%rbp)

我的代码有什么问题,是 MinGW 编译器错误吗?

比较 mingw 32 位和 mingw 64 位二进制文​​件是错误的,因此当使用最新的 mingw-w64 编译时,所有调用约定都符合预期。