Как заполнить регистр X86 XMM 4 одинаковыми числами из другой записи регистра XMM? - PullRequest
12 голосов
/ 06 января 2010

Я пытаюсь реализовать встроенный ассемблер (в коде C / C ++), чтобы использовать преимущества SSE. Я хотел бы скопировать и продублировать значения (из регистра XMM или из памяти) в другой регистр XMM. Например, предположим, у меня есть некоторые значения {1, 2, 3, 4} в памяти. Я хотел бы скопировать эти значения так, чтобы xmm1 заполнялся {1, 1, 1, 1}, xmm2 - {2, 2, 2, 2} и т. Д. И т.

Просматривая справочные руководства Intel, я не смог найти инструкцию для этого. Мне просто нужно использовать комбинацию повторяющихся MOVSS и вращений (через PSHUFD?)?

Ответы [ 3 ]

15 голосов
/ 06 января 2010

Есть два способа:

  1. Использование shufps исключительно:

    __m128 first = ...;
    __m128 xxxx = _mm_shuffle_ps(first, first, 0x00); // _MM_SHUFFLE(0, 0, 0, 0)
    __m128 yyyy = _mm_shuffle_ps(first, first, 0x55); // _MM_SHUFFLE(1, 1, 1, 1)
    __m128 zzzz = _mm_shuffle_ps(first, first, 0xAA); // _MM_SHUFFLE(2, 2, 2, 2)
    __m128 wwww = _mm_shuffle_ps(first, first, 0xFF); // _MM_SHUFFLE(3, 3, 3, 3)
    
  2. Пусть компилятор выберет лучший способ, используя _mm_set1_ps и _mm_cvtss_f32:

    __m128 first = ...;
    __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
    

Обратите внимание, что 2-й метод будет выдавать ужасный код в MSVC, , как обсуждено здесь , и будет производить только 'xxxx' как результат, в отличие от первого варианта.

Я пытаюсь реализовать некоторые inline ассемблер (в коде C / C ++) взять преимущество SSE

Это очень непереносимо. Используйте встроенные функции.

6 голосов
/ 06 января 2010

Переместить источник в регистр dest. Используйте 'shufps' и просто дважды используйте новый регистр dest, а затем выберите соответствующую маску.

В следующем примере значения XMM2.x передаются в XMM0.xyzw

MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
1 голос
/ 06 января 2010

Если ваши значения выровнены в памяти на 16 байт:

movdqa    (mem),    %xmm1
pshufd    $0xff,    %xmm1,    %xmm4
pshufd    $0xaa,    %xmm1,    %xmm3
pshufd    $0x55,    %xmm1,    %xmm2
pshufd    $0x00,    %xmm1,    %xmm1

Если нет, вы можете выполнить не выровненную нагрузку или четыре скалярных нагрузки. На новых платформах невыровненная нагрузка должна быть быстрее; на старых платформах скалярные нагрузки могут выиграть.

Как уже отмечали другие, вы также можете использовать shufps.

...