使用 2 个寄存器,一个额外的用于高半部分。 MIPS 没有标志,因此没有像在许多其他 ISA 上那样添加 int64_t 的 2 指令 add/add-with-carry,但您可以查看添加两个 64 的 C 函数的编译器输出位整数很容易。
#include <stdint.h>
int64_t add64(int64_t a, int64_t b) {
return a+b;
}
编译为 MIPS on the Godbolt compiler explorer 和 gcc5.4 -O3 -fno-delayed-branch1:
add64:
addu $3,$5,$7
sltu $5,$3,$5 # check for carry-out with sum_lo < a_lo (unsigned)
addu $2,$4,$6 # add high halves
addu $2,$5,$2 # add the carry-out from the low half into the high half
j $31 # return
nop # branch-delay slots
脚注 1:所以 GCC 只用 NOP 填充 branch-delay slot,而不是真正的指令。因此,相同的代码可以在没有延迟槽的简化 MIPS 上运行,就像 MARS 默认模拟的那样。
在内存中,大端模式下的 MIPS(MIPS 更常见的选择)以大端顺序存储整个 64 位整数,因此 “高半部分”(最高有效 32 位)在低地址,因此该字的最高字节在最低地址,所有 8 字节按位值的降序排列。
void add64_store(int64_t a, int64_t b, int64_t *res) {
*res = a+b;
}
## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
addu $7,$5,$7 # low half
lw $2,16($sp)
sltu $5,$7,$5 # carry-out
addu $4,$4,$6
addu $5,$5,$4 # high half
sw $5,0($2) # store the high half to res[0..3] (byte offsets)
sw $7,4($2) # store the low half to res[4..7]
j $31
nop # delay slot
从所使用的寄存器编号可以看出,调用约定将高半部分传递到编号较低的寄存器(早期的 arg)中,这与小端架构中高半部分传递在后面的 arg 传递槽中。如果您用完了寄存器并且在堆栈上传递了int64_t,这会使事情按预期工作。
在带有标志和带进位加法指令的体系结构上(例如 ARM32),您会得到一个加法指令,它会在 C:R0 中创建一个 33 位结果(进位标志中的最高位,a 中的低 32注册)。
add64:
adds r0, r2, r0 @ ADD and set flags
adc r1, r3, r1 @ r1 = r1 + r3 + carry
bx lr
您标记了此 MIPS32,因此您没有可用的 ISA 的 64 位扩展。这是 1991 年在 MIPS III 中引入的,但对于嵌入式使用,MIPS32 是一种现代 MIPS,具有 64 位寄存器以外的扩展。
同样的道理也适用于 64 位 MIPS 上的 128 位整数daddu