什么原因导致ARM上的GCC 7.2.1对内存(lr
)使用某些常量的负载,以及在某些其他情况下立即使用(mov
)?具体来说,我看到以下内容:
ARM的GCC 7.2.1编译:
extern void abc(int);
int test() { abc(1199); return 0; }
......进入那个:
test():
push {r4, lr}
ldr r0, .L4 // ??!
bl abc(int)
mov r0, #0
pop {r4, lr}
bx lr
.L4:
.word 1199
和此:
extern void abc(int);
int test() { abc(1200); return 0; }
......进入那个:
test():
push {r4, lr}
mov r0, #1200 // OK
bl abc(int)
mov r0, #0
pop {r4, lr}
bx lr
起初我预计1200会成为某种独特的截止,但在1024处还有其他类似的截止(1024产生mov r0, #1024
,而1025使用ldr
)和其他值
为什么GCC会使用内存加载来获取常量,而不是使用立即?
答案 0 :(得分:17)
这与在ARM指令集中编码常量操作数的方式有关。它们被编码为(无符号)8位常数和4位旋转字段 - 8位值将旋转该4位字段中值的2倍。因此,适合该形式的任何值都可以用作常量参数。
常量1200
是二进制的10010110000,因此它可以编码为8位常数01001011和4的旋转。
常量1199
是二进制的10010101111,因此无法将其置于ARM常量操作数中。