代碼轉自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;
}