¿Cómo se rellena un registro XMM x 86 con 4 flotadores idénticos de otra entrada de registro XMM?

StackOverflow https://stackoverflow.com/questions/2015726

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?)?

¿Fue útil?

Solución

Hay dos maneras:

  1. 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)
    
  2. 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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top