加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

简单的ADD / ADC ARM assemlby失败

发布时间:2020-12-16 07:03:00 所属栏目:百科 来源:网络整理
导读:我有(以下)相同代码的以下C和ASM版本.它的作用是加载2个128位整数,每个由2个64位整数表示,寄存器(前4 *低32位,然后4 *高32位)和ADD / ADC.它足够简单,而ARM / ST手册实际上给出了96bit(3个ADD / ADC)的相同示例. 对于简单调用,两个版本都有效(重复添加(1 x)
我有(以下)相同代码的以下C和ASM版本.它的作用是加载2个128位整数,每个由2个64位整数表示,寄存器(前4 *低32位,然后4 *高32位)和ADD / ADC.它足够简单,而ARM / ST手册实际上给出了96bit(3个ADD / ADC)的相同示例.

对于简单调用,两个版本都有效(重复添加(1 <<< x)或1..x).但是对于较长的测试套件,ARM组件会出现故障(电路板挂起). ATM我没有能力捕获/调试那个并且不能使用任何printf()或者喜欢找到测试失败,这无论如何都是无关紧要的,因为ASM版本中必定存在一些基本错误,因为C版本按预期工作. 我没有得到它,它很简单,非常接近C汇编输出(没有分支).我尝试了“内存”约束(不应该需要),我尝试在寄存器中保存低位和高位64位之间的进位,然后使用ADD(C).W,对齐,使用两个LDR / STR代替LDRD / STRD等.我假设电路板出现故障,因为某些附加设备出错并导致除以0或类似的情况.
GCC ASM在下面并使用类似的基本技术,所以我没有看到问题.

我真的只是寻找最快的添加方式,而不是专门修复代码.遗憾的是你必须使用常量寄存器名称,因为没有约束来指定rX和rX 1.此外,使用与GCC一样多的寄存器是不可能的,因为它们在编译期间会耗尽它们.

typedef struct I128 {
    int64_t high;
    uint64_t low;
} I128;

I128 I128add(I128 a,const I128 b) {
#if defined(USEASM) && defined(ARMx)
    __asm(
            "LDRD %%r2,%%r3,%[alo]n"
            "LDRD %%r4,%%r5,%[blo]n"
            "ADDS %%r2,%%r2,%%r4n"
            "ADCS %%r3,%%r5n"
            "STRD %%r2,%[alo]n"

            "LDRD %%r2,%[ahi]n"
            "LDRD %%r4,%[bhi]n"
            "ADCS %%r2,%%r4n"
            "ADC %%r3,%[ahi]n"
            : [alo] "+m" (a.low),[ahi] "+m" (a.high)
            : [blo] "m" (b.low),[bhi] "m" (b.high)
            : "r2","r3","r4","r5","cc"
            );
    return a;
#else
    // faster to use temp than saving low and adding to a directly
    I128 r = {a.high + b.high,a.low + b.low};
    // check for overflow of low 64 bits,add carry to high
    // avoid conditionals
    //r.high += r.low < a.low || r.low < b.low;
    // actually gcc produces faster code with conditionals
    if(r.low < a.low || r.low < b.low) ++r.high;
    return r;
}

使用“armv7m-none-eabi-gcc-4.7.2 -O3 -ggdb -fomit-frame-pointer -falign-functions = 16 -std = gnu99 -march = armv7e-m”的GCC C版本:

b082        sub sp,#8
e92d 0ff0   stmdb   sp!,{r4,r5,r6,r7,r8,r9,sl,fp}
a908        add r1,sp,#32
e881 000c   stmia.w r1,{r2,r3}
e9dd 890e   ldrd    r8,[sp,#56]   ; 0x38
e9dd 670a   ldrd    r6,#40]   ; 0x28
e9dd 2308   ldrd    r2,r3,#32]
e9dd 450c   ldrd    r4,#48]   ; 0x30
eb16 0a08   adds.w  sl,r8
eb47 0b09   adc.w   fp,r9
1912        adds    r2,r2,r4
eb43 0305   adc.w   r3,r5
45bb        cmp fp,r7
bf08        it  eq
45b2        cmpeq   sl,r6
d303        bcc.n   8012c9a <I128add+0x3a>
45cb        cmp fp,r9
bf08        it  eq
45c2        cmpeq   sl,r8
d204        bcs.n   8012ca4 <I128add+0x44>
2401        movs    r4,#1
2500        movs    r5,#0
1912        adds    r2,r5
e9c0 2300   strd    r2,[r0]
e9c0 ab02   strd    sl,fp,[r0,#8]
e8bd 0ff0   ldmia.w sp!,fp}
b002        add sp,#8
4770        bx  lr

我的ASM版本失败:

b082        sub sp,#8                                                                                  
b430        push    {r4,r5}                                                                            
a902        add r1,#8                                                                              
e881 000c   stmia.w r1,r3}                                                                        
e9dd 2304   ldrd    r2,#16]                                                                   
e9dd 4508   ldrd    r4,#32]                                                                   
1912        adds    r2,r4                                                                          
416b        adcs    r3,r5                                                                              
e9cd 2304   strd    r2,#16]                                                                   
e9dd 2302   ldrd    r2,#8]                                                                    
e9dd 4506   ldrd    r4,#24]                                                                   
4162        adcs    r2,r4                                                                              
eb43 0305   adc.w   r3,r5                                                                          
e9cd 2302   strd    r2,#8]                                                                    
4604        mov r4,r0                                                                                  
c90f        ldmia   r1,{r0,r1,r3}                                                                
e884 000f   stmia.w r4,r3}                                                                
4620        mov r0,r4                                                                                  
bc30        pop {r4,r5}                                                                                
b002        add sp,#8                                                                                  
4770        bx  lr

解决方法

我没有从您的代码中获取挂起,但它也不起作用,不知道为什么.但是很容易修补编译器生成的代码来处理进位:

I128 I128add(I128 a,const I128 b) {

    I128 r = {a.high + b.high,a.low + b.low};
    return r;
}

000001e4 <I128add>:
 1e4:   b082        sub sp,#8
 1e6:   b4f0        push    {r4,r7}
 1e8:   e9dd 4506   ldrd    r4,#24]
 1ec:   a904        add r1,#16
 1ee:   e881 000c   stmia.w r1,r3}
 1f2:   e9dd 230a   ldrd    r2,#40]   ; 0x28
 1f6:   1912        adds    r2,r4
 1f8:   eb43 0305   adc.w   r3,r5
 1fc:   e9dd 6704   ldrd    r6,#16]
 200:   e9dd 4508   ldrd    r4,#32]
 204:   1936        adds    r6,r4
 206:   eb47 0705   adc.w   r7,r5
 20a:   e9c0 6700   strd    r6,[r0]
 20e:   e9c0 2302   strd    r2,#8]
 212:   bcf0        pop {r4,r7}
 214:   b002        add sp,#8
 216:   4770        bx  lr

修正了补充

.thumb_func
.globl test2
test2:
    sub sp,#8
    push    {r4,r7}
    ldrd    r4,#24]
    add r1,#16
    stmia r1,r3}
    ldrd    r2,#40]
    add r2,r4
    adc r3,r5
    ldrd    r6,#16]
    ldrd    r4,#32]
    adc r6,r4
    adc r7,r5
    strd    r6,[r0]
    strd    r2,#8]
    pop {r4,r7}
    add sp,#8
    bx  lr

最后结果

00000024 <test2>:
  24:   b082        sub sp,#8
  26:   b4f0        push    {r4,r7}
  28:   e9dd 4506   ldrd    r4,#24]
  2c:   a904        add r1,#16
  2e:   c10c        stmia   r1!,r3}
  30:   e9dd 230a   ldrd    r2,#40]   ; 0x28
  34:   1912        adds    r2,r4
  36:   416b        adcs    r3,r5
  38:   e9dd 6704   ldrd    r6,#16]
  3c:   e9dd 4508   ldrd    r4,#32]
  40:   4166        adcs    r6,r4
  42:   416f        adcs    r7,r5
  44:   e9c0 6700   strd    r6,[r0]
  48:   e9c0 2302   strd    r2,#8]
  4c:   bcf0        pop {r4,r7}
  4e:   b002        add sp,#8
  50:   4770        bx  lr

注意thumb2指令的数量较少,除非你在具有thumb2支持的cortex-A上,那些来自flash(cortex-m)的提取(可能)很慢.我看到你正在尝试保存另外两个寄存器的推送和弹出,但是你花费了更多的时间.你可以采取上述方法,仍然重新安排加载和存储,并保存这两个寄存器.

迄今为止的最小测试. printfs显示上面的单词添加,我没有看到你的代码.我仍然试图解开调用约定(请为我们更多地记录您的代码),看起来r0由调用者准备放置结果,rest在堆栈上.我正在使用stellaris启动板(cortex-m4).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读