在risc-v体系结构中,mulh [[s] u]操作返回的位是什么样的?

问题描述

TLDR:给定64位寄存器rs1(signed) = 0xffff'ffff'ffff'fff6rs2(unsigned) = 0x10,riscv 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);

应该签名吗?未签名?

根据说明手册:

MUL对rs1与rs2进行XLEn位×XLEn位相乘,并将低XLEn位放入 在目标寄存器中。 MULH,MULHU和 MULHSU 执行相同的乘法,但返回 完整的2×XLEn位乘积的高XLEn位,用于带符号×带符号,无符号×无符号, 和有符号rs1×无符号rs2乘法。如果高位和低位相同 需要乘积,则建议的代码序列为:MULH [[S] U] rdh,rs1,rs2; UL rdl,rs1,rs2(源寄存器说明符必须具有相同的顺序,并且rdh不能与rs1或 rs2)。然后,微架构可以将它们融合为一个乘法运算,而不是执行 两个单独的乘法。

解决方法

您的问题的答案是: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整数,而u128是无符号的128整数。

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