BBSLIMS
BBSLIMS

Reputation: 363

In the risc-v architecture, what do the bits returned by the mulh[[s]u] operation look like?

TLDR: given 64 bit registers rs1(signed) = 0xffff'ffff'ffff'fff6 and rs2(unsigned) = 0x10 does the riscv mulhsu instruction return 0x0000'0000'0000'000f or 0xffff'ffff'ffff'ffff or something else entirely to rd?

I am working on implementing a simulated version of the RiscV architecture and have run into a snag when implementing the RV64M mulh[[s]u] instruction. I'm not sure if mulhsu returns a signed or unsigned number. If it does return a signed number, then what is the difference between mulhsu and mulh?

here is some pseudocode demonstrating the problem (s64 and u64 denote signed and unsigned 64-bit register respectively)

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);

Should rd be signed? unsigned?

From the instruction manual:

MUL performs an XLEN-bit × XLEN-bit multiplication of rs1 by rs2 and places the lower XLEN bits in the destination register. MULH, MULHU, and MULHSU perform the same multiplication but return the upper XLEN bits of the full 2 × XLEN-bit product, for signed × signed, unsigned × unsigned, and signed rs1×unsigned rs2 multiplication, respectively. If both the high and low bits of the same product are required, then the recommended code sequence is: MULH[[S]U] rdh, rs1, rs2; MUL rdl, rs1, rs2 (source register specifiers must be in same order and rdh cannot be the same as rs1 or rs2). Microarchitectures can then fuse these into a single multiply operation instead of performing two separate multiplies.

Upvotes: 1

Views: 5350

Answers (1)

yflelion
yflelion

Reputation: 1746

The answer for your question is :EXPECT_EQ(0xffff'ffff'ffff'ffff, rd);.

mulhsu will do a multiplication of a sign extend of rs1.s64 and a zero extend rs2.u64. You can see that in the compiler machine description riscv.md.

so mulhsu (64 bits) will return the equivalent of : ((s128) rs1.s64 * (u128) rs2.u64) >> 64. where s128 is a signed 128 int and u128 an unsigned 128 int.

the difference between the three mul is:
mulhsu is a multiplication between a sign extended register and a zero extended register.
mulh is a multiplication of two sign extended registers.
mulhu is a multiplication of two zero extended registers.

Upvotes: 2

Related Questions