Как вы заполняете регистр x86 XMM четырьмя одинаковыми поплавками из другой записи регистра XMM?
Я пытаюсь реализовать некоторый встроенный ассемблер (в коде C/С++), чтобы воспользоваться SSE. Я хотел бы скопировать и дублировать значения (из регистра XMM или из памяти) в другой регистр XMM. Например, предположим, что у меня есть некоторые значения {1, 2, 3, 4} в памяти. Я бы хотел скопировать эти значения таким образом, чтобы xmm1 заполнялся {1, 1, 1, 1}, xmm2 с {2, 2, 2, 2} и т.д. И т.д.
Просматривая справочные руководства Intel, я не мог найти инструкции для этого. Нужно ли мне просто использовать комбинацию повторяющихся MOVSS и вращаться (через PSHUFD?)?
Ответы
Ответ 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)
-
Пусть компилятор лучше всего выбирает с помощью _mm_set1_ps
и _mm_cvtss_f32
:
__m128 first = ...;
__m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
Обратите внимание, что второй метод приведет к созданию ужасного кода в MSVC, как описано здесь, и будет генерировать только "xxxx" в результате, в отличие от первый вариант.
Я пытаюсь внедрить ряд встроенных ассемблер (в коде C/С++) преимущество SSE
Это очень непропорционально. Используйте встроенные функции.
Ответ 2
Переместите источник в регистр dest. Используйте "shufps" и просто используйте новый регистр dest дважды, а затем выберите соответствующую маску.
Следующий пример передает значения XMM2.x в XMM0.xyzw
MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
Ответ 3
Если ваши значения равны 16 байт в памяти:
movdqa (mem), %xmm1
pshufd $0xff, %xmm1, %xmm4
pshufd $0xaa, %xmm1, %xmm3
pshufd $0x55, %xmm1, %xmm2
pshufd $0x00, %xmm1, %xmm1
Если нет, вы можете выполнить нестандартную нагрузку или четыре скалярные нагрузки. На новых платформах неуравновешенная нагрузка должна быть быстрее; на более старых платформах могут сказываться скалярные нагрузки.
Как отмечали другие, вы также можете использовать shufps
.