title: Porting MMX/SSE instructions to AltiVec
body: <p>Let me preface this with.. I have extremely limited experience with ASM, and even less with SIMD.</p>
  
  <p>But it happens that I have the following MMX/SSE optimised code, that I would like to port across to AltiVec instructions for use on PPC/Cell processors.</p>
  
  <p>This is probably a big ask.. Even though it's only a few lines of code, I've had no end of trouble trying to work out what's going on here.</p>
  
  <p>The original function:</p>
  
  <pre><code>static inline int convolve(const short *a, const short *b, int n)
  {
      int out = 0;
      union {
          __m64 m64;
          int i32[2];
      } tmp;
      tmp.i32[0] = 0;
      tmp.i32[1] = 0;
      while (n &gt;= 4) {
          tmp.m64 = _mm_add_pi32(tmp.m64,
                                 _mm_madd_pi16(*((__m64 *)a),
                                               *((__m64 *)b)));
          a += 4;
          b += 4;
          n -= 4;
      }
      out = tmp.i32[0] + tmp.i32[1];
      _mm_empty();
  
      while (n --)
          out += (*(a++)) * (*(b++));
      return out;
  }
  </code></pre>
  
  <p>Any tips on how I might rewrite this to use AltiVec instructions?</p>
  
  <p>My first attempt (a very wrong attempt) looks something like this..  But it's not entirely (or even remotely) correct.</p>
  
  <pre><code>static inline int convolve_altivec(const short *a, const short *b, int n)
  {
      int out = 0;
      union {
          vector unsigned int m128;
          int i64[2];
      } tmp;
  
      vector unsigned int zero = {0, 0, 0, 0};
  
      tmp.i64[0] = 0;
      tmp.i64[1] = 0;
      while (n &gt;= 8) {
          tmp.m128 = vec_add(tmp.m128,
                                 vec_msum(*((vector unsigned short *)a),
                                               *((vector unsigned short *)b), zero));
  
          a += 8;
          b += 8;
          n -= 8;
      }
      out = tmp.i64[0] + tmp.i64[1];
  #endif
      while (n --)
          out += (*(a++)) * (*(b++));
      return out;
  }
  </code></pre>