PowerPC汇编指令疑问:C代码对应汇编的运算逻辑解析
PowerPC汇编与C代码对应问题解答
原始代码与疑问
C代码
#define X 8380417 #define INV 0x3802001 int32_t reduce(int64_t a) { int32_t t; t = (int64_t)(int32_t)a*INV; t = (a - (int64_t)t*X) >> 32; return t; }
PowerPC汇编代码
lis 8,0x380 lis 9,0xff80 ori 8,8,8193 ori 9,9,8191 mullw 8,8,4 mulhw 10,8,9 mullw 11,8,9 addc 4,4,11 adde 3,3,10 blr
疑问
- 执行
mullw 8,8,4后,R8寄存器的高位是否仍保留0x380? - X=8380417对应R9中的
0xff801fff,为何后续步骤使用加法而非减法?
解答
关于mullw执行后R8的高位变化
PowerPC的mullw是32位有符号乘法指令,它会取两个源寄存器的低32位相乘,将乘积的低32位存入目标寄存器的低32位,同时对这个32位结果做符号扩展填充目标寄存器的高32位。
在你的代码里,mullw 8,8,4用R8中存储的INV低32位,和R4中存储的a的低32位相乘。执行这条指令后,R8的原有内容(包括高位的0x380)会被完全覆盖——新的高32位是乘积低32位的符号扩展值,不再保留原来的0x380。
为何用加法而非减法
先看C代码的核心表达式:a - (int64_t)t*X。汇编里把X转换成了它的32位有符号负数补码:
- X=8380417的十六进制是
0x7FE001,对应的32位有符号负数补码就是0xFF801FFF(也就是R9中存储的值)。
这样一来,(int64_t)t*X等价于-(int64_t)t*0xFF801FFF,原表达式a - (int64_t)t*X可以改写为a + (int64_t)t*(-X)。
汇编中用mulhw(取32位乘法的高32位)和mullw(取低32位)算出t*(-X)的64位结果,再通过addc(带进位的低32位加法)和adde(带进位的高32位加法)完成64位加法,效果和C代码的减法完全一致。
用加法替代减法的原因是:PowerPC的带进位加法指令可直接处理64位运算,若用减法需要额外的取反加1操作,转成负数补码后直接加法更高效。
内容的提问来源于stack exchange,提问作者Gappu
相关产品推荐
相关产品推荐

