Как Вы заполняете регистр x86 XMM с 4 идентичными плаваниями от другой записи регистра XMM?

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

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

12
задан jbl 6 January 2010 в 19:51
поделиться

3 ответа

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

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

    __m128 сначала = ;
    __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, 0xAAA); // _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 сначала = ;
    __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
    

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

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

Это очень непредсказуемо. Использовать intrinsics.

15
ответ дан 2 December 2019 в 07:02
поделиться

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

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

MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
6
ответ дан 2 December 2019 в 07:02
поделиться

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

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

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

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

1
ответ дан 2 December 2019 в 07:02
поделиться