¿Cómo se rellena un registro XMM x 86 con 4 flotadores idénticos de otra entrada de registro XMM?
-
19-09-2019 - |
Pregunta
Estoy tratando de poner en práctica algunas ensamblador en línea (en C / C ++ de código) para tomar ventaja de la ESS. Me gustaría copiar y duplicar los valores (de un registro XMM, o desde la memoria) a otro registro XMM. Por ejemplo, supongamos que tengo algunos valores {1, 2, 3, 4} en la memoria. Me gustaría copiar estos valores tales que XMM1 se rellena con {1, 1, 1, 1}, XMM2 con {2, 2, 2, 2}, y así sucesivamente y así sucesivamente.
Mirando a través de los manuales de referencia de Intel, no pude encontrar una instrucción para hacer esto. No sólo hay que utilizar una combinación de MOVSS repetida y gira (a través de PSHUFD?)?
Solución
Hay dos maneras:
-
Utilice exclusivamente
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)
-
Deja que el compilador de elegir la mejor manera de utilizar
_mm_set1_ps
y_mm_cvtss_f32
:__m128 first = ...; __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
Tenga en cuenta que el segundo método producirá código horrible en MSVC, como discutido aquí, y sólo producirá 'xxxx' como resultado de ello, a diferencia de la primera opción.
Estoy tratando de poner en práctica algunas inline ensamblador (en C / C ++ de código) para tomar ventaja de SSE
Esto es altamente no portables. Utilice los intrínsecos.
Otros consejos
Mover la fuente al registro dest. Uso 'shufps' y sólo tiene que utilizar el nuevo registro dest dos veces y luego seleccionar la máscara adecuada.
El siguiente ejemplo transmite los valores de XMM2.x a XMM0.xyzw
MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
Si sus valores son de 16 bytes alineados en la memoria:
movdqa (mem), %xmm1
pshufd $0xff, %xmm1, %xmm4
pshufd $0xaa, %xmm1, %xmm3
pshufd $0x55, %xmm1, %xmm2
pshufd $0x00, %xmm1, %xmm1
Si no es así, se puede hacer una carga no alineado, o cuatro cargas escalares. En las plataformas más recientes, la carga no alineado debe ser más rápido; en las plataformas de mayor edad las cargas escalares pueden ganar.
Como otros han señalado, también se puede utilizar shufps
.