soporta rápido procesadores procesador pae más instalar gigahercio ghz con compatibles compatible athlon and x86 simd intrinsics sse2 sse4

x86 - rápido - procesadores intel compatibles con sse2



Simulación de la funcionalidad packusdw con SSE2 (1)

Puede firmar extender los valores primero y luego usar _mm_packs_epi32 :

t0 = _mm_slli_epi32 (t0, 16); t0 = _mm_srai_epi32 (t0, 16); t1 = _mm_slli_epi32 (t1, 16); t1 = _mm_srai_epi32 (t1, 16); t0 = _mm_packs_epi32 (t0, t1);

En realidad, puede combinar esto con los turnos anteriores para guardar dos instrucciones:

t0 = _mm_slli_epi32 (t0, 16 - 5); t0 = _mm_srai_epi32 (t0, 16); t1 = _mm_slli_epi32 (t1, 16 - 5); t1 = _mm_srai_epi32 (t1, 16); t0 = _mm_packs_epi32 (t0, t1);

Estoy implementando una función rápida de conversión x888 -> 565 píxeles en pixman según el algoritmo descrito por Intel [pdf] . Su código convierte x888 -> 555 mientras que yo quiero convertirlo a 565. Lamentablemente, convertir a 565 significa que el bit alto está configurado, lo que significa que no puedo usar las instrucciones del paquete de saturación firmada. La instrucción de paquete sin signo, packusdw no se agregó hasta SSE4.1. Me gustaría implementar su funcionalidad con SSE2 o encontrar otra forma de hacerlo.

Esta función toma dos registros XMM que contienen 4 píxeles de 32 bits cada uno y genera un solo registro XMM que contiene los 8 píxeles RGB565 convertidos.

static force_inline __m128i pack_565_2packedx128_128 (__m128i lo, __m128i hi) { __m128i rb0 = _mm_and_si128 (lo, mask_565_rb); __m128i rb1 = _mm_and_si128 (hi, mask_565_rb); __m128i t0 = _mm_madd_epi16 (rb0, mask_565_pack_multiplier); __m128i t1 = _mm_madd_epi16 (rb1, mask_565_pack_multiplier); __m128i g0 = _mm_and_si128 (lo, mask_green); __m128i g1 = _mm_and_si128 (hi, mask_green); t0 = _mm_or_si128 (t0, g0); t1 = _mm_or_si128 (t1, g1); t0 = _mm_srli_epi32 (t0, 5); t1 = _mm_srli_epi32 (t1, 5); /* XXX: maybe there''s a way to do this relatively efficiently with SSE2? */ return _mm_packus_epi32 (t0, t1); }

Ideas que he pensado:

  • Restando 0x8000, _mm_packs_epi32, volviendo a agregar 0x8000 a cada 565 píxeles. Intenté esto, pero no puedo hacer que esto funcione.

    t0 = _mm_sub_epi16 (t0, mask_8000); t1 = _mm_sub_epi16 (t1, mask_8000); t0 = _mm_packs_epi32 (t0, t1); return _mm_add_epi16 (t0, mask_8000);

  • Mezcle los datos en lugar de empaquetarlos. Funciona para MMX, pero como la mezcla SSE de 16 bits funciona solo en los 64 bits altos o bajos, se complicaría.

  • Guarde los bits altos, póngalos a cero, haga el paquete, restáurelos después. Parece bastante desordenado.

¿Hay alguna otra (ojalá más eficiente) forma en que pueda hacer esto?