漢明距離的NEON版本

代碼轉自chromium中的libyuv

// 256 bits at a time
// uses short accumulator which restricts count to 131 KB
uint32_t HammingDistance_NEON(const uint8_t* src_a,
                              const uint8_t* src_b,
                              int count) {
  uint32_t diff;

  asm volatile(
      // 把q4寄存器置0,用於累加
      "vmov.u16   q4, #0                         \n"  // accumulator

      "1:                                        \n"
      // 從src_a load 256個bit到q0, q1中,src_a自加256
      "vld1.8     {q0, q1}, [%0]!                \n"
      // 從src_b load 256個bit到q2, q3中,src_b自加256
      "vld1.8     {q2, q3}, [%1]!                \n"
      // q0和q2異或的結果存到q0中
      "veor.32    q0, q0, q2                     \n"
      // q1和q3異或的結果存到q1中
      "veor.32    q1, q1, q3                     \n"
      // 統計q0中爲1的位數,存到q0中
      "vcnt.i8    q0, q0                         \n"
      // 統計q1中爲1的位數,存到q1中
      "vcnt.i8    q1, q1                         \n"
      // count自減32(一次計算了256個bit = 32 byte)
      "subs       %2, %2, #32                    \n"
      // 把q0和q1的爲1的位數相加(16個計數)
      "vadd.u8    q0, q0, q1                     \n"  // 16 byte counts
      // 把q0中每兩相鄰的8位相加得到8個計數,再和q4中已有的計數相加
      "vpadal.u8  q4, q0                         \n"  // 8 shorts
      // count > 0 繼續循環
      "bgt        1b                             \n"

	  // 把q4中每兩相鄰的16位相加並存到32位長度中,得到4個int
      "vpaddl.u16 q0, q4                         \n"  // 4 ints
      // q0 = {d0, d1} ,把d0和d1中每兩相鄰的32位相加(兩個int)
      "vpadd.u32  d0, d0, d1                     \n"
      把d0中兩相鄰的32位相加(得到一個int結果)
      "vpadd.u32  d0, d0, d0                     \n"
      // diff = d0的第0個int
      "vmov.32    %3, d0[0]                      \n"

      : "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(diff)
      :
      : "cc", "q0", "q1", "q2", "q3", "q4");
  return diff;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章