1

TLDR:给定 64 位寄存器rs1(signed) = 0xffff'ffff'ffff'fff6rs2(unsigned) = 0x10riscv mulhsu 指令是否返回0x0000'0000'0000'000f0xffff'ffff'ffff'ffff完全返回到 rd?

我正在实现 RiscV 架构的模拟版本,在实现 RV64M mulh[[s]u] 指令时遇到了障碍。我不确定 mulhsu 是否返回有符号或无符号数字。如果它确实返回一个有符号数,那么 mulhsu 和 mulh 有什么区别?

这是一些演示问题的伪代码(s64 和 u64 分别表示有符号和无符号的 64 位寄存器)

rs1.s64 = 0xffff'ffff'ffff'fff6;   //-10
rs2.u64 = 0x10;                    // 16

execute(mulhsu(rs1, rs2));

// which of these is correct? Note: rd only returns the upper 64 bits of the product
EXPECT_EQ(0x0000'0000'0000'000f, rd);
EXPECT_EQ(0xffff'ffff'ffff'ffff, rd);
EXPECT_EQ(<some other value>, rd);

应该签署 rd 吗?未签名?

从使用说明书:

MUL 执行 rs1 与 rs2 的 XLEN 位 × XLEN 位乘法,并将低 XLEN 位放入目标寄存器。MULH、MULHU 和MULHSU执行相同的乘法,但返回完整 2 × XLEN 位乘积的高 XLEN 位,分别用于有符号 × 有符号、无符号 × 无符号和有符号 rs1×无符号 rs2 乘法。如果同一个产品的高低位都需要,那么推荐的编码顺序是:MULH[[S]U] rdh, rs1, rs2; MUL rdl, rs1, rs2(源寄存器说明符的顺序必须相同,并且 rdh 不能与 rs1 或 rs2 相同)。然后,微架构可以将这些融合到单个乘法运算中,而不是执行两个单独的乘法运算。

4

1 回答 1

2

你的问题的答案是:EXPECT_EQ(0xffff'ffff'ffff'ffff, rd);

mulhsu 将 rs1.s64 的符号扩展和 rs2.u64 的零扩展相乘。您可以在编译器机器描述中看到这一点riscv.md

所以 mulhsu (64位)将返回相当于 : ((s128) rs1.s64 * (u128) rs2.u64) >> 64。其中 s128 是有符号的 128 int,u128 是无符号的 128 int。

三个mul的区别是:
mulhsu是符号扩展寄存器和零扩展寄存器的乘法。
mulh 是两个符号扩展寄存器的乘法。
mulhu 是两个零扩展寄存器的乘法。

于 2020-10-05T19:42:31.360 回答