2015-08-31 48 views
0

下面展开的子公司的执行产生了错误的结果,我设法观察到只有元素b[0]b[2]被计数,而b[1]b[3]不是。Aarch64程序集LD2问题

#include <stdio.h> 

int count_multiple_bits(unsigned long long *b, int size) { 
    unsigned long long *d = b; 
    int c; 
    __asm__("LD2 {v0.D, v1.D}[0], [%1], #16 \n\t" 
      "LD2 {v0.D, v1.D}[1], [%1]  \n\t" 
      "CNT v0.16b, v0.16b    \n\t" 
      "CNT v1.16b, v1.16b    \n\t" 
      "UADDLV h2, v0.16b    \n\t" 
      "UADDLV h2, v1.16b    \n\t" 
      "UMOV %0, v2.d[0]    \n\t" 
      : "+r"(c) 
      : "r"(d) : "v0", "v1", "v2"); 
    return c; 
} 

int main(int argc, const char *argv[]) { 
    unsigned long long bits[] = { -1ull, -1ull, -1ull, -1ull }; 
    printf("Test: %i\n", count_multiple_bits(bits, 4)); 
    return 0; 
} 

这一次它一次计数2元正常工作:

int count_multiple_bits(unsigned long long *b, int size) { 
    unsigned long long *d = b; 
    int c; 
    __asm__("LD1 {v0.D}[0], [%1], #8 \n\t" 
      "LD1 {v0.D}[1], [%1]  \n\t" 
      "CNT v0.16b, v0.16b  \n\t" 
      "UADDLV h1, v0.16b   \n\t" 
      "UMOV %0, v1.d[0]   \n\t" 
      : "+r"(c) 
      : "r"(d) : "v0", "v1"); 
    return c; 
} 

与所有其他条件相同,我猜负载是错误的,这里的布局我相信:

v0.D[0] = b[0] 
    v1.D[0] = b[1] 
    v0.D[1] = b[2] 
    v1.D[1] = b[3] 

回答

0

我的不好。

的问题是在UADDLV它清除目标寄存器,下面是总结任意长度的输入最终版本:

int count_multiple_bits(unsigned long long *b, unsigned int size) { 
    unsigned long long *d = b; 
    unsigned int masked = 0, i = 0; 
    int c = 0; 

    masked = size & ~3; 
    for (; i < masked; i += 4) 
    __asm__("LD1 {v0.2D, v1.2D}[0], [%1], #32 \n\t" 
      "CNT v0.16b, v0.16b    \n\t" 
      "CNT v1.16b, v1.16b    \n\t" 
      "UADDLV h2, v0.16b    \n\t" 
      "UADDLV h3, v1.16b    \n\t" 
      "ADD d2, d3, d2     \n\t" 
      "UMOV x0, v2.d[0]     \n\t" 
      "ADD %0, x0, %0     \n\t" 
      : "+r"(c), "+r"(d) 
      :: "x0", "v0", "v1", "v2", "v3"); 

    masked = size & 3; 
    for (i = 0; i < masked; ++i) 
    __asm__("LD1 {v0.D}[0], [%1], #8 \n\t" 
      "CNT v0.8b, v0.8b  \n\t" 
      "UADDLV h1, v0.8b   \n\t" 
      "UMOV x0, v1.d[0]   \n\t" 
      "ADD %0, x0, %0   \n\t" 
      : "+r"(c), "+r"(d) 
      : : "x0", "v0", "v1"); 

    return c; 
} 

就像一个魅力:)

+0

任何特别的原因使用对'LD2的'在一个LD1 {v0.2D,v1.2D},[%1],#32'上?无论如何,当你只是将它们混合在一起时,似乎没有必要在单个通道上解交叉数据的麻烦。 – Notlikethat

+0

哇,这样好多了,我没有意识到(没有正确解读docs语法)多谢'LD''的'2D' /'#32'调试! – arul