MOVQ / PINSRQ против VMOV для заполнения XMM (один работает, другой нет) - PullRequest
0 голосов
/ 16 октября 2019

В процессе обучения я начал экспериментировать с инструкциями AVX и написал простое умножение массивов, чтобы все работало, очень просто. Первой проблемой было заполнение xmm0 и xmm1, поскольку nasm не принимает XMMWORD в качестве размера (yasm принимает его, но так как он больше не разрабатывается, я предпочитаю его не использовать), мне пришлось заполнять его двумя 64-битными шагами. Я нашел эту ветку , показывающую решение, которое работает для меня, используя MOVQ и PINSRQ. Код, который (вроде) работает:

section .data
array1: dd  1.0, 2.0, 3.0, 4.0  ; Declares 2 arrays of 16 bytes
array2: dd  2.0, 3.0, 4.0, 5.0

section .text
global _start
_start:

mov     r8, qword array1        ; Stores the address of the 1st element
mov     r9, qword array2        ; of each array in the registers
movq    xmm0, r8                ; Populates the first half of xmm0
pinsrq  xmm0, r8, 1             ; Populates the second half   
movq    xmm1, r9                ; The same for xmm1
pinsrq  xmm1, r9, 1
vmulps  xmm0, xmm1              ; Multiplies the arrays and save in xmm0

xor     ebx, ebx
mov     rax, 1
int     80h

Но прежде чем я нашел это решение, я пытался с:

vmovlps xmm0, qword [r8]
vmovhps xmm0, qword [r8 + 8]

Они должны заполнить младшие биты, а затем старшиебиты регистра xmm0, но программа вылетает в первый вмов. Итак, вы, ребята, можете объяснить, почему эта пара mov не работает, а пара movq / pinsrq работает нормально? Не стесняйтесь также давать советы, если есть что-то, что можно улучшить в этом простом процессе.

========= РЕДАКТИРОВАТЬ, ОБНОВИТЬ ========

И просто для того, чтобы попытаться поместить результат обратно в память, чтобы rdi указывал на первое из 4 32-битных значений, хранящихся в xmm0, на случай, если я захочу вернуть rdi, он собирается, но вывод (выводимый программой C ++)фигня, так что это явно неверный путь:

vmulps  xmm0, xmm1     ; Multiplies the arrays and save in xmm0
vmovdqa [rdi], xmm0    ; Assembles and doesn't crash, but no meaningful result

1 Ответ

1 голос
/ 23 октября 2019

Я просто хочу опубликовать код, который работает, после того, как вы немного прочтете документацию и не сделаете трудного пути:

global mul_array_float         ; mul_array_float(float &array1, float *array2)
mul_array_float:
    vmovups xmm0, [rdi]    ; populates xmm0 and xmm1 with rdi and rsi being
    vmovups xmm1, [rsi]    ; passed by the function call
    vmulps  xmm0, xmm1     ; multiply them and save result in xmm0
    vmovups [rdi], xmm0    ; return the result to rdi (being passed by reference)
    ret

Если функция передает массивы как выровненные, потери скорости не происходитс инструкциями "ups". Спасибо Питеру Кордесу и Шуту за их соображения.

...