代码转自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;
}