diff --git a/DecodeM.fs b/DecodeM.fs
index cc25d0c..5d0d7a1 100644
--- a/DecodeM.fs
+++ b/DecodeM.fs
@@ -17,13 +17,6 @@ type InstructionM =
| REM of {| rd: Register; rs1: Register; rs2: Register |}
| REMU of {| rd: Register; rs1: Register; rs2: Register |}
- // Only x64
- | MULW of {| rd: Register; rs1: Register; rs2: Register |}
- | DIVW of {| rd: Register; rs1: Register; rs2: Register |}
- | DIVUW of {| rd: Register; rs1: Register; rs2: Register |}
- | REMW of {| rd: Register; rs1: Register; rs2: Register |}
- | REMUW of {| rd: Register; rs1: Register; rs2: Register |}
-
| None // Instruction not found
/// Decode 'M' instructions
@@ -56,21 +49,6 @@ let Decode (mstate : MachineState) (instr: InstrField) : InstructionM =
| _ -> None
| _ -> None
- // RV64M Standard Extension (in addition to RV32M)
- | 0b0111011 when mstate.Arch.archBits = RV64 ->
- match funct7 with
- | 0b0000001 ->
- match funct3 with
- // Multiplication Operations
- | 0b000 -> MULW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
- // Division Operations
- | 0b100 -> DIVW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
- | 0b101 -> DIVUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
- | 0b110 -> REMW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
- | 0b111 -> REMUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
- | _ -> None
- | _ -> None
-
| _ -> None
// Current ISA print log message for current instruction step
@@ -79,8 +57,7 @@ let verbosityMessage (instr : InstrField) (decodedInstr : InstructionM) (mstate
let instrMsg =
match (decodedInstr) with
| MUL x | MULH x | MULHSU x | MULHU x | DIV x
- | DIVU x | REM x | REMU x | MULW x | DIVW x
- | DIVUW x | REMW x | REMUW x -> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
+ | DIVU x | REM x | REMU x -> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
| _ -> "Undef"
let pc = sprintf "%08x:" mstate.PC
let instr = sprintf "%08x" instr
diff --git a/DecodeM64.fs b/DecodeM64.fs
new file mode 100644
index 0000000..532500c
--- /dev/null
+++ b/DecodeM64.fs
@@ -0,0 +1,59 @@
+module ISA.RISCV.Decode.M64
+
+open System
+open ISA.RISCV.Utils.Bits
+open ISA.RISCV.Arch
+open ISA.RISCV.MachineState
+
+//================================================================ -- \begin_latex{Major_Opcodes}
+// 'M64' (Integer Multiplication and Division 'M' Standard Extension)
+type InstructionM64 =
+ | MULW of {| rd: Register; rs1: Register; rs2: Register |}
+ | DIVW of {| rd: Register; rs1: Register; rs2: Register |}
+ | DIVUW of {| rd: Register; rs1: Register; rs2: Register |}
+ | REMW of {| rd: Register; rs1: Register; rs2: Register |}
+ | REMUW of {| rd: Register; rs1: Register; rs2: Register |}
+
+ | None // Instruction not found
+
+/// Decode 'M64' instructions
+let Decode (mstate : MachineState) (instr: InstrField) : InstructionM64 =
+ let opcode = instr.bitSlice 6 0
+ // Register number can be: 0-32
+ let rd = int32(instr.bitSlice 11 7)
+ let rs1 = int32(instr.bitSlice 19 15)
+ let rs2 = int32(instr.bitSlice 24 20)
+
+ let funct3 = instr.bitSlice 14 12
+ let funct7 = instr.bitSlice 31 25
+
+ match (opcode) with
+ // RV64M Standard Extension (in addition to RV32M)
+ | 0b0111011 when mstate.Arch.archBits = RV64 ->
+ match funct7 with
+ | 0b0000001 ->
+ match funct3 with
+ // Multiplication Operations
+ | 0b000 -> MULW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
+ // Division Operations
+ | 0b100 -> DIVW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
+ | 0b101 -> DIVUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
+ | 0b110 -> REMW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
+ | 0b111 -> REMUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
+ | _ -> None
+ | _ -> None
+
+ | _ -> None
+
+// Current ISA print log message for current instruction step
+let verbosityMessage (instr : InstrField) (decodedInstr : InstructionM64) (mstate : MachineState) =
+ let typeName = decodedInstr.GetType().Name
+ let instrMsg =
+ match (decodedInstr) with
+ MULW x | DIVW x | DIVUW x |
+ REMW x | REMUW x -> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
+ | _ -> "Undef"
+ let pc = sprintf "%08x:" mstate.PC
+ let instr = sprintf "%08x" instr
+ let instrMsg = String.Format("{0,-7}{1}", typeName, instrMsg)
+ printfn "%s" (String.Format("{0,-12}{1,-12}{2}", pc, instr, instrMsg))
diff --git a/Decoder.fs b/Decoder.fs
index cd2ba08..09bfb90 100644
--- a/Decoder.fs
+++ b/Decoder.fs
@@ -15,6 +15,8 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
let decI32 = I.Decode mstate instr
let decI64 = I64.Decode instr
let decM = M.Decode mstate instr
+ let decM64 = M64.Decode mstate instr
+
// Check is instruction should be executed
let execI32 =
match mstate.Arch with
@@ -30,8 +32,9 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
| _ -> false
let execM64 =
match mstate.Arch with
- | RV64im when decM <> M.InstructionM.None -> true
+ | RV64im when decM64 <> M64.InstructionM64.None -> true
| _ -> false
+
// Decoded instruction and execute ISA function
if execI32 then
Some(I.Execute decI32)
@@ -40,6 +43,6 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
else if execM32 then
Some(M.Execute decM)
else if execM64 then
- Some(M64.Execute decM)
+ Some(M64.Execute decM64)
else
None
diff --git a/ExecuteM.fs b/ExecuteM.fs
index 88bc8f9..cc722cd 100644
--- a/ExecuteM.fs
+++ b/ExecuteM.fs
@@ -5,6 +5,36 @@ open ISA.RISCV.Arch
open ISA.RISCV.MachineState
open ISA.RISCV.Utils.Bits
+let mulhu (x : uint64, y : uint64) : uint64 =
+ let x0 = uint64(uint32 x)
+ let y0 = uint64(uint32 y)
+ let x1 = x >>> 32
+ let y1 = y >>> 32
+
+ let t = x1 * y0 + ((x0 * y0) >>> 32)
+ let y2 = uint64(uint32 t)
+ let y3 = t >>> 32
+ let y4 = x0 * y1 + y2
+ let t = x1 * y1 + y3 + (y4 >>> 32)
+ let y5 = uint64(uint32 t)
+ let y6 = (t >>> 32) <<< 32
+ y6 ||| y5
+
+let mulh (x : int64, y : int64) : int64 =
+ let neg = (x < 0L) <> (y < 0L)
+ let x1 = uint64(if x < 0L then -x else x)
+ let y1 = uint64(if y < 0L then -y else y)
+ let res = mulhu(x1, y1)
+ let resd = if (x * y) = 0L then 1L else 0L
+ if neg then int64(~~~res) + resd else int64 res
+
+let mulhsu (x : int64, y : uint64) : int64 =
+ let neg = x < 0L
+ let x1 = uint64(if x < 0L then -x else x)
+ let res = mulhu(x1, y)
+ let resd = if (x * int64 y) = 0L then 1L else 0L
+ if neg then int64(~~~res) + resd else int64 res
+
//=================================================
// MUL - Multiplication operation - sign * sign
let execMUL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
@@ -15,8 +45,15 @@ let execMUL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineS
//=================================================
// MULH - Multiplication operation - sign * sign and return high 32 bits
let execMULH (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
- let rdVal = (mstate.getRegister rs1) * (mstate.getRegister rs2)
- let hRes = rdVal.bitSlice 63 32
+ let hRes =
+ match mstate.Arch.archBits with
+ | RV32 ->
+ let rdVal = (mstate.getRegister rs1) * (mstate.getRegister rs2)
+ rdVal.bitSlice 63 32
+ | _ ->
+ let rs1Val = mstate.getRegister rs1
+ let rs2Val = mstate.getRegister rs2
+ mulh(rs1Val, rs2Val)
let mstate = mstate.setRegister rd hRes
mstate.incPC
@@ -25,11 +62,13 @@ let execMULH (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machine
let execMULHSU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
- let rdVal =
+ let hRes =
match mstate.Arch.archBits with
- | RV32 -> rs1Val * int64(uint32 rs2Val)
- | _ -> rs1Val * int64(uint64 rs2Val)
- let hRes = rdVal.bitSlice 63 32
+ | RV32 ->
+ let rdVal = rs1Val * int64(uint32 rs2Val)
+ rdVal.bitSlice 63 32
+ | _ ->
+ mulhsu(rs1Val, uint64 rs2Val)
let mstate = mstate.setRegister rd hRes
mstate.incPC
@@ -38,11 +77,13 @@ let execMULHSU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machi
let execMULHU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
- let rdVal =
+ let hRes =
match mstate.Arch.archBits with
- | RV32 -> int64(uint32 rs1Val) * int64(uint32 rs2Val)
- | _ -> int64(uint64 rs1Val) * int64(uint64 rs2Val)
- let hRes = rdVal.bitSlice 63 32
+ | RV32 ->
+ let rdVal = int64(uint32 rs1Val) * int64(uint32 rs2Val)
+ rdVal.bitSlice 63 32
+ | _ ->
+ int64(mulhu(uint64 rs1Val, uint64 rs2Val))
let mstate = mstate.setRegister rd hRes
mstate.incPC
diff --git a/ExecuteM64.fs b/ExecuteM64.fs
index a9f33d8..21a3249 100644
--- a/ExecuteM64.fs
+++ b/ExecuteM64.fs
@@ -1,7 +1,7 @@
module ISA.RISCV.Execute.M64
open ISA.RISCV.Arch
-open ISA.RISCV.Decode.M
+open ISA.RISCV.Decode.M64
open ISA.RISCV.MachineState
//=================================================
@@ -15,16 +15,16 @@ let execMULW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machine
//=================================================
// DIVW - Division Word operation - sign * sign
let execDIVW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
- let rs1Val = mstate.getRegister rs1
- let rs2Val = mstate.getRegister rs2
- let minSigned = 0x8000000000000000L
+ let rs1Val = int32(mstate.getRegister rs1)
+ let rs2Val = int32(mstate.getRegister rs2)
+ let minSigned = 0x80000000
let rdVal =
- if rs2Val = 0L then
+ if rs2Val = 0 then
-1
- else if rs1Val = minSigned && rs2Val = -1L then
- int32 rs1Val
+ else if rs1Val = minSigned && rs2Val = -1 then
+ rs1Val
else
- int32 rs1Val / int32 rs2Val
+ rs1Val / rs2Val
let mstate = mstate.setRegister rd (int64 rdVal)
mstate.incPC
@@ -45,16 +45,16 @@ let execDIVUW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machin
//=================================================
// REMW - Division Unsign Word operation - sign * sign
let execREMW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
- let rs1Val = mstate.getRegister rs1
- let rs2Val = mstate.getRegister rs2
- let minSigned = 0x8000000000000000L
+ let rs1Val = int32(mstate.getRegister rs1)
+ let rs2Val = int32(mstate.getRegister rs2)
+ let minSigned = 0x80000000
let rdVal =
- if rs2Val = 0L then
+ if rs2Val = 0 then
int32 rs1Val
- else if rs1Val = minSigned && rs2Val = -1L then
+ else if rs1Val = minSigned && rs2Val = -1 then
0
else
- int32 rs1Val % int32 rs2Val
+ rs1Val % rs2Val
let mstate = mstate.setRegister rd (int64 rdVal)
mstate.incPC
@@ -72,7 +72,7 @@ let execREMUW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machin
mstate.incPC
// Execute M64-instructions
-let Execute (instr : InstructionM) (mstate : MachineState) =
+let Execute (instr : InstructionM64) (mstate : MachineState) =
match instr with
| MULW i ->
execMULW i.rd i.rs1 i.rs2 mstate
diff --git a/README.md b/README.md
index 0e8c963..261c561 100644
--- a/README.md
+++ b/README.md
@@ -34,10 +34,11 @@ Technical Group constituted by The RISC-V Foundation
- [x] Tests RV32I
- [x] Base instruction set: RV64I
- [x] Tests RV64I
- - [ ] Standard extension M (integer multiply/divide)
- - [ ] Tests for Standard extension M RV32/RV64
+ - [x] Standard extension M (integer multiply/divide)
+ - [x] Tests for Standard extension M RV32/RV64
+ - [ ] Standard extension A (atomic memory ops)
+ - [ ] Tests for Standard extension A RV32/RV64
* Features under development
- * Standard extension A (atomic memory ops)
* Standard extension C (Compressed 16-bit instructions)
* Standard extension F (Single-precision floating point)
* Standard extension D (Double-precision floating point)
diff --git a/Tests/Tests.fsproj b/Tests/Tests.fsproj
index 30fa5b6..13b9861 100644
--- a/Tests/Tests.fsproj
+++ b/Tests/Tests.fsproj
@@ -33,6 +33,9 @@
+
+
+
diff --git a/Tests/asm/Makefile b/Tests/asm/Makefile
index 0fbab4c..1e1369e 100644
--- a/Tests/asm/Makefile
+++ b/Tests/asm/Makefile
@@ -30,7 +30,7 @@ $(BUILDDIR)/%32: $(SRCDIR)/%.S init32.o mmio.ld
$(BUILDDIR)/%64: $(SRCDIR)/%.S init64.o mmio.ld
mkdir -p $(BUILDDIR)
- $(RISCVCC64) -c $(SRCDIR)/$*.S -o intermediate64.o
+ $(RISCVCC64) -c $(SRCDIR)/$*.S -o intermediate64.o -D x64
$(RISCVCC64) -o $(BUILDDIR)/$*64 -Tmmio.ld intermediate64.o init64.o
rm intermediate64.o
diff --git a/Tests/asm/src/alu.S b/Tests/asm/src/alu.S
index 83a8635..863ad9c 100644
--- a/Tests/asm/src/alu.S
+++ b/Tests/asm/src/alu.S
@@ -11,10 +11,30 @@ main:
sra x3, x2, x1
or x3, x2, x1
and x3, x2, x1
- # x64
+#ifdef x64
addw x3, x2, x1
subw x3, x2, x1
sllw x3, x2, x1
srlw x3, x2, x1
sraw x3, x2, x1
+#endif
+
+ # M-extension
+ mul x3, x2, x1
+ mulh x3, x2, x1
+ mulhu x3, x2, x1
+ mulhsu x3, x2, x1
+
+ div x3, x2, x1
+ divu x3, x2, x1
+ rem x3, x2, x1
+ remu x3, x2, x1
+
+#ifdef x64
+ mulw x3, x2, x1
+ divw x3, x2, x1
+ divuw x3, x2, x1
+ remw x3, x2, x1
+ remuw x3, x2, x1
+#endif
ret
diff --git a/Tests/asm/src/alui.S b/Tests/asm/src/alui.S
index 186999f..071e852 100644
--- a/Tests/asm/src/alui.S
+++ b/Tests/asm/src/alui.S
@@ -11,9 +11,10 @@ main:
slli x3, x2, 5
srli x3, x2, 5
srai x3, x2, 5
- # x64 only
+#ifdef x64
addiw x3, x2, 5
slliw x3, x2, 5
srliw x3, x2, 5
sraiw x3, x2, 5
+#endif
ret
diff --git a/Tests/asm/src/mem.S b/Tests/asm/src/mem.S
index f094c0a..0ef8c1d 100644
--- a/Tests/asm/src/mem.S
+++ b/Tests/asm/src/mem.S
@@ -7,15 +7,19 @@ main:
lh x3, -10(x2)
lw x3, 10(x2)
lw x3, -10(x2)
+#ifdef x64
ld x3, 10(x2)
ld x3, -10(x2)
+#endif
lbu x3, 10(x2)
lbu x3, -10(x2)
lhu x3, 10(x2)
lhu x3, -10(x2)
+#ifdef x64
lwu x3, 10(x2)
lwu x3, -10(x2)
+#endif
sb x3, 10(x2)
sb x3, -10(x2)
@@ -23,7 +27,8 @@ main:
sh x3, -10(x2)
sw x3, 10(x2)
sw x3, -10(x2)
- # x64
+#ifdef x64
sd x3, 10(x2)
sd x3, -10(x2)
+#endif
ret
diff --git a/Tests/rv32m/alu.fs b/Tests/rv32m/alu.fs
new file mode 100644
index 0000000..778f298
--- /dev/null
+++ b/Tests/rv32m/alu.fs
@@ -0,0 +1,171 @@
+module Tests.rv32m.alu
+
+open Xunit
+
+open ISA.RISCV
+open ISA.RISCV.Arch
+
+//===============================================
+// ALU tests
+let ALU instr x1 x2 x3 =
+ // Init MachineState
+ let addr = 0x80000000L
+ let mstate = MachineState.InitMachineState Map.empty RV32im true
+ let mstate = mstate.setPC addr
+ let mstate = mstate.setRegister 1 x1
+ let mstate = mstate.setRegister 2 x2
+
+ let executor = Decoder.Decode mstate instr
+ Assert.NotEqual(executor, None)
+ let mstate = executor.Value mstate
+ Assert.Equal(x1, mstate.getRegister 1)
+ Assert.Equal(x2, mstate.getRegister 2)
+ Assert.Equal(x3, mstate.getRegister 3)
+ Assert.Equal(addr + 4L, mstate.PC)
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``MUL: x3 = x2 * x1`` ( x3, x1, x2) =
+ ALU 0x021101b3 x1 x2 x3
+
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+//[]
+let ``MULH: x3 = half (x2 * x1)`` (x3, x1, x2) =
+ ALU 0x021111b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``MULHSU: x3 = half (sign x2 * unsign x1)`` (x3, x2, x1) =
+ ALU 0x021121b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``MULHU: x3 = half (unsign x2 * unsign x1)`` (x3, x1, x2) =
+ ALU 0x021131b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``DIV: x3 = x2 / x1`` (x3, x2, x1) =
+ ALU 0x021141b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``DIVU: x3 = (unsign x2) / (unsign x1)`` (x3, x2, x1) =
+ ALU 0x021151b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``REM: x3 = x2 % x1`` (x3, x2, x1) =
+ ALU 0x021161b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``REMU: x3 = (unsign x2) % (unsign x1)`` (x3, x2, x1) =
+ ALU 0x021171b3 x1 x2 x3
diff --git a/Tests/rv64m/alu.fs b/Tests/rv64m/alu.fs
new file mode 100644
index 0000000..2185fae
--- /dev/null
+++ b/Tests/rv64m/alu.fs
@@ -0,0 +1,186 @@
+module Tests.rv64m.alu
+
+open Xunit
+
+open ISA.RISCV
+open ISA.RISCV.Arch
+
+//===============================================
+// ALU `x64` tests
+let ALU instr x1 x2 x3 =
+ // Init MachineState
+ let addr = 0x80000000L
+ let mstate = MachineState.InitMachineState Map.empty RV64im true
+ let mstate = mstate.setPC addr
+ let mstate = mstate.setRegister 1 x1
+ let mstate = mstate.setRegister 2 x2
+
+ let executor = Decoder.Decode mstate instr
+ Assert.NotEqual(executor, None)
+ let mstate = executor.Value mstate
+ Assert.Equal(x1, mstate.getRegister 1)
+ Assert.Equal(x2, mstate.getRegister 2)
+ Assert.Equal(x3, mstate.getRegister 3)
+ Assert.Equal(addr + 4L, mstate.PC)
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``MUL: x3 = x2 * x1`` ( x3, x2, x1) =
+ ALU 0x021101b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``MULW: x3 = x2 * x1`` (x3, x2, x1) =
+ ALU 0x021101bb x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``MULH: x3 = half (x2 * x1)`` (x3, x2, x1) =
+ ALU 0x021111b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``WMULHU: x3 = half (unsign x2 * unsign x1)`` (x3, x2, x1) =
+ ALU 0x021131b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``WMULHSU: x3 = half (sign x2 * unsign x1)`` (x3, x2, x1) =
+ ALU 0x021121b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``DIV: x3 = x2 / x1`` (x3, x2, x1) =
+ ALU 0x021141b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``DIVW: x3 = x2 / x1`` (x3, x2, x1) =
+ ALU 0x021141bb x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``DIVU: x3 = (unsign x2) / (unsign x1)`` (x3, x2, x1) =
+ ALU 0x021151b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``DIVUW: x3 = unsign x2 / unsign x1`` (x3, x2, x1) =
+ ALU 0x021151bb x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``REM: x3 = x2 % x1`` (x3, x2, x1) =
+ ALU 0x021161b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``REMW: x3 = x2 % x1`` (x3, x2, x1) =
+ ALU 0x021161bb x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``x64-REMU: x3 = (unsign x2) % (unsign x1)`` (x3, x2, x1) =
+ ALU 0x021171b3 x1 x2 x3
+
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+[]
+let ``REMUW: x3 = unsign x2 % unsign x1`` (x3, x2, x1) =
+ ALU 0x021171bb x1 x2 x3
diff --git a/risc-v.fsproj b/risc-v.fsproj
index fda35de..b7bfb64 100644
--- a/risc-v.fsproj
+++ b/risc-v.fsproj
@@ -28,6 +28,7 @@ Additionally it's possible to operate with CLI, reading ELF files and set verbos
+