Jus*_*ntz 13 c assembly gcc arm compiler-optimization
在最快的Cortex M0 + Thumb 32x32 = 64乘法功能的问题上工作?我写了下面的C函数来看看它是如何编译的:
uint64_t lmul(uint32_t a, uint32_t b){
uint32_t hia = a >> 16,
hib = b >> 16,
loa = (uint32_t)(uint16_t)a,
lob = (uint32_t)(uint16_t)b,
low = loa * lob,
mid1 = hia * lob,
mid2 = loa * hib,
mid = mid1 + mid2,
high = hia * hib;
if (mid < mid1)
high += 0x10000;
return ((uint64_t)high << 32) + ((uint64_t)mid << 16) + low;
}
Run Code Online (Sandbox Code Playgroud)
在使用ARM GCC编译器4.7.3通过CodeWarrior(我正在使用的Freescale开发板附带)进行大小优化编译之后,它变成了:
00000eac <lmul>:
eac: b570 push {r4, r5, r6, lr}
eae: 0c06 lsrs r6, r0, #16
eb0: b280 uxth r0, r0
eb2: 0c0a lsrs r2, r1, #16
eb4: 1c04 adds r4, r0, #0
eb6: b289 uxth r1, r1
eb8: 434c muls r4, r1
eba: 4350 muls r0, r2
ebc: 4371 muls r1, r6
ebe: 1843 adds r3, r0, r1
ec0: 4356 muls r6, r2
ec2: 428b cmp r3, r1
ec4: d202 bcs.n ecc <lmul+0x20>
ec6: 2580 movs r5, #128 ; 0x80
ec8: 026a lsls r2, r5, #9
eca: 18b6 adds r6, r6, r2
ecc: 0c19 lsrs r1, r3, #16
ece: 0418 lsls r0, r3, #16
ed0: 1c22 adds r2, r4, #0
ed2: 2300 movs r3, #0
ed4: 1c04 adds r4, r0, #0
ed6: 1c0d adds r5, r1, #0
ed8: 18a4 adds r4, r4, r2
eda: 415d adcs r5, r3
edc: 1c31 adds r1, r6, #0
ede: 1c18 adds r0, r3, #0
ee0: 1c22 adds r2, r4, #0
ee2: 1c2b adds r3, r5, #0
ee4: 1812 adds r2, r2, r0
ee6: 414b adcs r3, r1
ee8: 1c10 adds r0, r2, #0
eea: 1c19 adds r1, r3, #0
eec: bd70 pop {r4, r5, r6, pc}
Run Code Online (Sandbox Code Playgroud)
我无法理解编译器在函数的最后40%中所做的事情.这就像它正在播放音乐寄存器,除了增加功能的大小之外别无其他目的.这是ARM已知的事情,还是有一些奇怪的目的,我缺乏ARM组装专业知识来理解?
如果我没有替换任何错误,函数的后半部分可以表示为:
ecc: 0c19 lsrs r1, r3, #16
ece: 0418 lsls r0, r3, #16
ed2: 2300 movs r3, #0
ed8: 18a4 adds r0, r0, r4
eda: 415d adcs r1, r3
ee6: 414b adds r1, r1, r6
eec: bd70 pop {r4, r5, r6, pc}
Run Code Online (Sandbox Code Playgroud)
我还没有使用过 CodeWarrior 工具链,但我决定使用 ARMCC 编译器 v 5.03.0.76 来尝试使用 uVision。优化空间是默认选项 ( -Ospace),生成的代码仍然相当难看......与您的代码没有太大不同。当我用它编译时,-O2它看起来更像你所期望的:
0x0000008A B570 PUSH {r4-r6,lr}
0x0000008C 0C02 LSRS r2,r0,#16
0x0000008E 0C0C LSRS r4,r1,#16
0x00000090 B280 UXTH r0,r0
0x00000092 B289 UXTH r1,r1
0x00000094 4606 MOV r6,r0
0x00000096 4615 MOV r5,r2
0x00000098 434D MULS r5,r1,r5
0x0000009A 4360 MULS r0,r4,r0
0x0000009C 434E MULS r6,r1,r6
0x0000009E 182B ADDS r3,r5,r0
0x000000A0 4362 MULS r2,r4,r2
0x000000A2 42AB CMP r3,r5
0x000000A4 D202 BCS 0x000000AC
0x000000A6 2001 MOVS r0,#0x01
0x000000A8 0400 LSLS r0,r0,#16
0x000000AA 1812 ADDS r2,r2,r0
0x000000AC 2400 MOVS r4,#0x00
0x000000AE 0C19 LSRS r1,r3,#16
0x000000B0 0418 LSLS r0,r3,#16
0x000000B2 1900 ADDS r0,r0,r4
0x000000B4 4151 ADCS r1,r1,r2
0x000000B6 1980 ADDS r0,r0,r6
0x000000B8 4161 ADCS r1,r1,r4
0x000000BA BD70 POP {r4-r6,pc}
Run Code Online (Sandbox Code Playgroud)
您可以尝试使用不同的优化选项进行编译,但我建议您使用更新的编译器,正如 Marc Glisse 在他的评论中所述。