Неправильные соглашения о вызовах с плавающими значениями в MinGW - PullRequest
1 голос
/ 16 мая 2019

Я пытаюсь использовать свои функции сборки для работы с кодом 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    $16, %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

Моя сборка

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 регистры для аргументов, причина сбоя моей программы

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?

...