8d63ce
Correct vec_perm() application on little-endian 64-bit PowerPC
8d63ce
8d63ce
The LE transformation for vec_perm has an implicit assumption that the
8d63ce
permutation is being used to reorder vector elements (in this case 4-byte
8d63ce
integer word elements), not to reorder bytes within those elements.  Although
8d63ce
this is legal behavior, it is not anticipated by the transformation performed
8d63ce
by the compilers.
8d63ce
8d63ce
This causes pygame-1.9.1 test failure on PPC64LE because blitted pixmaps are
8d63ce
corrupted there due to how SDL uses vec_perm().
8d63ce
8d63ce
<https://bugzilla.redhat.com/show_bug.cgi?id=1392465>
8d63ce
8d63ce
--- SDL-1.2.15/src/video/SDL_blit_N.c.ori	2017-09-04 05:56:17.759347525 -0400
8d63ce
+++ SDL-1.2.15/src/video/SDL_blit_N.c	2017-09-06 05:36:20.570789610 -0400
8d63ce
@@ -146,6 +146,32 @@ static vector unsigned char calc_swizzle
8d63ce
     return(vswiz);
8d63ce
 }
8d63ce
 
8d63ce
+/* reorder bytes for PowerPC little endian */
8d63ce
+static vector unsigned char reorder_ppc64le_vec(vector unsigned char vpermute)
8d63ce
+{
8d63ce
+    /* The result vector of calc_swizzle32 reorder bytes using vec_perm.
8d63ce
+       The LE transformation for vec_perm has an implicit assumption
8d63ce
+       that the permutation is being used to reorder vector elements,
8d63ce
+       not to reorder bytes within those elements.  
8d63ce
+       Unfortunatly the result order is not the expected one for powerpc
8d63ce
+       little endian when the two first vector parameters of vec_perm are
8d63ce
+       not of type 'vector char'. This is because the numbering from the
8d63ce
+       left for BE, and numbering from the right for LE, produces a
8d63ce
+       different interpretation of what the odd and even lanes are.
8d63ce
+       Refer to fedora bug 1392465
8d63ce
+     */
8d63ce
+
8d63ce
+    const vector unsigned char ppc64le_reorder = VECUINT8_LITERAL(
8d63ce
+                                      0x01, 0x00, 0x03, 0x02,
8d63ce
+                                      0x05, 0x04, 0x07, 0x06,
8d63ce
+                                      0x09, 0x08, 0x0B, 0x0A,
8d63ce
+                                      0x0D, 0x0C, 0x0F, 0x0E );
8d63ce
+
8d63ce
+    vector unsigned char vswiz_ppc64le;
8d63ce
+    vswiz_ppc64le = vec_perm(vpermute, vpermute, ppc64le_reorder);
8d63ce
+    return(vswiz_ppc64le);
8d63ce
+}
8d63ce
+
8d63ce
 static void Blit_RGB888_RGB565(SDL_BlitInfo *info);
8d63ce
 static void Blit_RGB888_RGB565Altivec(SDL_BlitInfo *info) {
8d63ce
     int height = info->d_height;
8d63ce
@@ -631,6 +657,12 @@ static void Blit32to32KeyAltivec(SDL_Bli
8d63ce
                 vsel = (vector unsigned char)vec_and(vs, vrgbmask);
8d63ce
                 vsel = (vector unsigned char)vec_cmpeq(vs, vckey);
8d63ce
                 /* permute the src vec to the dest format */
8d63ce
+
8d63ce
+#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
8d63ce
+            /* reorder bytes for PowerPC little endian */
8d63ce
+            vpermute = reorder_ppc64le_vec(vpermute);
8d63ce
+#endif
8d63ce
+
8d63ce
                 vs = vec_perm(vs, valpha, vpermute);
8d63ce
                 /* load the destination vec */
8d63ce
                 vd = vec_ld(0, dstp);
8d63ce
@@ -704,6 +736,12 @@ static void ConvertAltivec32to32_noprefe
8d63ce
             src += 4;
8d63ce
             width -= 4;
8d63ce
             vbits = vec_perm(vbits, voverflow, valigner);  /* src is ready. */
8d63ce
+
8d63ce
+#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
8d63ce
+            /* reorder bytes for PowerPC little endian */
8d63ce
+            vpermute = reorder_ppc64le_vec(vpermute);
8d63ce
+#endif
8d63ce
+
8d63ce
             vbits = vec_perm(vbits, vzero, vpermute);  /* swizzle it. */
8d63ce
             vec_st(vbits, 0, dst);  /* store it back out. */
8d63ce
             dst += 4;
8d63ce
@@ -786,6 +824,12 @@ static void ConvertAltivec32to32_prefetc
8d63ce
             src += 4;
8d63ce
             width -= 4;
8d63ce
             vbits = vec_perm(vbits, voverflow, valigner);  /* src is ready. */
8d63ce
+
8d63ce
+#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN) 
8d63ce
+            /* reorder bytes for PowerPC little endian */
8d63ce
+            vpermute = reorder_ppc64le_vec(vpermute);
8d63ce
+#endif
8d63ce
+
8d63ce
             vbits = vec_perm(vbits, vzero, vpermute);  /* swizzle it. */
8d63ce
             vec_st(vbits, 0, dst);  /* store it back out. */
8d63ce
             dst += 4;