RISC-V 32bit M拡張(整数乗除算拡張命令)
概要
R形式
31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
---|---|---|---|---|---|
funct7 | rs2 | rs1 | funct3 | rd | オペコード |
オペコードで命令形式を判別
funct3でM拡張命令を判別(funct7は全て同じ)
フォーマット
命令 rd, rs1, rs2
注意点
verilogでは明示しない限り,値はunsignedとして扱われる.
算術右シフトは「符号ありの値」と「>>>」を用いて実現する.
div, rem では0除算を考慮
各命令
mul
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 000 | rd | 01100 | 11 |
rs1とrs2の値を読み出し,その積の下位32bitをrd番のレジスタに書き込む
例
x[rd] = $signed(x[rs1]) * $signed(x[rs2]);
mulh
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 001 | rd | 01100 | 11 |
rs1とrs2を符号あり整数として解釈し,結果を符号あり整数として計算.
計算結果の上位32bitだけをレジスタに格納.
算術右シフトを使用する.
例
x[rd] = $signed($signed(x[rs1]) * $signed(x[rs2])) >>> 32;
mulhsu
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 010 | rd | 01100 | 11 |
rs1を符号あり整数,rs2を符号なし整数として解釈し,結果を符号あり整数として計算.
計算結果の上位32bitだけをレジスタに格納.
算術右シフトを使用する.
例
x[rd] = $signed(($signed(x[rs1]) * $signed({1'b0, x[rs2]})) >>> 32;
mulhu
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 011 | rd | 01100 | 11 |
rs1とrs2を符号なし整数として解釈し,結果を符号なし整数として計算.
計算結果の上位32bitだけをレジスタに格納.
例
x[rd] = (x[rs1] * x[rs2]) >> 32;
div
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 100 | rd | 01100 | 11 |
rs1とrs2は符号あり整数として解釈し,結果を符号あり整数として計算.
求めるべき商は,数学的な商ではなく,答えを実数で求めた後小数点以下を切り捨てたもの.(0への丸め)
ゼロ除算(rs2が0):-1.
オーバーフロー(rs1が−2^{31}かつrs2が-1の時,数学的な結果は2^{31}だが表現できない):-2^{31}
例
x[rd] = (x[rs2] == 32'b0) ? 32'hffff_ffff : ((x[rs1] == 32'h8000_0000) && (x[rs2] == 32'hffff_ffff)) ? 32'h8000_0000 : $signed($signed(x[rs1]) / $signed(x[rs2]));
divu
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 101 | rd | 01100 | 11 |
rs1とrs2は符号なし整数として解釈し,結果を符号なし整数として計算.
求めるべき商は,数学的な商ではなく,答えを実数で求めた後小数点以下を切り捨てたもの.(0への丸め)
ゼロ除算(rs2が0):2^{32}-1.
例
x[rd] = (x[rs2] == 32'b0) ? 32'hffff_ffff : (x[rs1] / x[rs2]);
rem
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 110 | rd | 01100 | 11 |
rs1とrs2は符号あり整数として解釈し,結果を符号あり整数として計算.
求めるべき商は,数学的な剰余ではなく,符号が被除数と同じ剰余.(rs1とrs2の絶対値をとってから剰余を計算した後,rs1と同じ符号にすればよい)
ゼロ除算(rs2が0):rs1
オーバーフロー(rs1が2^{31}かつrs2が-1の時):0
例
x[rd] = (x[rs2] == 32'b0) ? x[rs1] : ((x[rs1] == 32'h8000_0000) && (x[rs2] == 32'hffff_ffff)) ? 32'h0 : $signed($signed(x[rs1]) % $signed(x[rs2]));
remu
31 - 27 | 26 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 2 | 1 - 0 |
---|---|---|---|---|---|---|---|
0000 | 01 | rs2 | rs1 | 111 | rd | 01100 | 11 |
rs1とrs2は符号なし整数として解釈し,結果を符号なし整数として計算.
ゼロ除算(rs2が0):rs1
例
x[rd] = (x[rs2] == 32'b0) ? x[rs1] : (x[rs1] % x[rs2]);