title: Unpack m128i/m256i to m64 (MMX, SSE2, AVX2)
body: <p>I have memory organized like this:</p>
  
  <blockquote>
    <p>block1(m64), block2(m64), block3(m64), block4(m64), ....</p>
  </blockquote>
  
  <p>Now I do in a for loop this operation:</p>
  
  <p>iteration 1.....</p>
  
  <pre><code>    x = block1 XOR block2
      y = block1 AND block2
      block1 = x
      block2 = y
  </code></pre>
  
  <p>iteration 2.....</p>
  
  <pre><code>    x = block3 XOR block4
      y = block3 AND block4
      block3 = x
      block4 = y
  </code></pre>
  
  <p>And so on...</p>
  
  <p>I tried now to combine the m64 blocks to m128i blocks:</p>
  
  <blockquote>
    <p>block1_block3(m128), block2_block4(m128),....</p>
  </blockquote>
  
  <p>Now I am able to use 128 bit SIMD instructions and the for loop will be only 50% of m64 instructions.</p>
  
  <p>But the bad thing is that I can't cast the memory direct to an m128i/m256i because the m64 values aren't in one line. So I will need to assemble and dissasemble the values like this:</p>
  
  <pre><code>// combine two 128 bit to one 256 bit nummber
  __m256i static inline iCombine_128_256(__m128i *a, __m128i *b)
  {
    __m256i ret = _mm256_castsi128_si256(*a);
    return _mm256_inserti128_si256(ret, *b, 1);
  }
  
  // combine four 64 bit to one 256 bit nummber
  __m256i static inline iCombine_64_256(__m64 *a, __m64 *b, __m64 *c, __m64 *d)
  {
    __m256i ret = _mm256_castsi128_si256(_mm_set_epi64(*b, *a));
    return _mm256_inserti128_si256(ret, _mm_set_epi64(*d, *c), 1);
  }
  
  // combine eight 32 bit to one 256 bit nummber
  __m256i static inline iCombine_32_256(unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d, unsigned int *e, unsigned int *f, unsigned int *g, unsigned int *h)
  {
    __m256i ret = _mm256_castsi128_si256(_mm_set_epi32(*d, *c, *b, *a));
    return _mm256_inserti128_si256(ret, _mm_set_epi32(*h, *g, *f, *e), 1);
  }
  </code></pre>
  
  <p>So this will take some extra instructions to assemble these blocks.
  Isn't there a way to "cheat" an m256i? Let's say I tell x.m256i_u64[0] the pointer of the first block1, x.m256i_u64[1] the second pointer off block2,...
  And in sum it shows me the assembled m256i value of these 4 m64 values?
  Is this somehow possible?</p>