Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions ExecuteI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -285,21 +285,23 @@ let execSUB (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineS

//=================================================
// SLL - Shift Logical Left
// SLL, SRL, and SRA perform logical left, logical right, and arithmetic right shifts on the value in register
// rs1 by the shift amount held in register rs2. In RV32I, only the low 5 bits of rs2 are considered for the
// shift amount. In RV64I, only the low 6 bits of rs2 are considered for the shift amount.
let execSLL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rdVal =
match mstate.Arch.archBits with
| RV32 -> (mstate.getRegister rs1) <<< int32(mstate.getRegister rs2)
| _ ->
| RV32 ->
let shamt = (mstate.getRegister rs2) &&& 0x1f
int64(int32(uint32(mstate.getRegister rs1) <<< int32(shamt)))
| _ ->
let shamt = (mstate.getRegister rs2) &&& 0x3f
(mstate.getRegister rs1) <<< int32(shamt)
let mstate = mstate.setRegister rd rdVal
mstate.incPC

//=================================================
// SLT - Set 1 if Less Then
// SLL, SRL, and SRA perform logical left, logical right, and arithmetic right shifts on the value in register
// rs1 by the shift amount held in register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
// shift amount.
let execSLT (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rdVal = if mstate.getRegister rs1 < mstate.getRegister rs2 then 1L else 0L
let mstate = mstate.setRegister rd rdVal
Expand All @@ -325,13 +327,15 @@ let execXOR (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineS
//=================================================
// SRL - Shift Right Logical
// SLL, SRL, and SRA perform logical left, logical right, and arithmetic right shifts on the value in register
// rs1 by the shift amount held in register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
// shift amount.
// rs1 by the shift amount held in register rs2. In RV32I, only the low 5 bits of rs2 are considered for the
// shift amount. In RV64I, only the low 6 bits of rs2 are considered for the shift amount.
let execSRL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rdVal =
match mstate.Arch.archBits with
| RV32 -> int64(uint32(mstate.getRegister rs1) >>> int32(mstate.getRegister rs2))
| _ ->
| RV32 ->
let shamt = (mstate.getRegister rs2) &&& 0x1f
int64(int32(uint32(mstate.getRegister rs1) >>> int32(shamt)))
| _ ->
let shamt = (mstate.getRegister rs2) &&& 0x3f
int64(uint64(mstate.getRegister rs1) >>> int32(shamt))
let mstate = mstate.setRegister rd rdVal
Expand All @@ -340,13 +344,15 @@ let execSRL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineS
//=================================================
// SRA - Shift Right Arithmetic
// SLL, SRL, and SRA perform logical left, logical right, and arithmetic right shifts on the value in register
// rs1 by the shift amount held in register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
// shift amount.
// rs1 by the shift amount held in register rs2. In RV32I, only the low 5 bits of rs2 are considered for the
// shift amount. In RV64I, only the low 6 bits of rs2 are considered for the shift amount.
let execSRA (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rdVal =
match mstate.Arch.archBits with
| RV32 -> (mstate.getRegister rs1) >>> int32 (mstate.getRegister rs2)
| _ ->
| RV32 ->
let shamt = (mstate.getRegister rs2) &&& 0x1f
int64(int32(mstate.getRegister rs1) >>> int32(shamt))
| _ ->
let shamt = (mstate.getRegister rs2) &&& 0x3f
(mstate.getRegister rs1) >>> int32 (shamt)
let mstate = mstate.setRegister rd rdVal
Expand Down
22 changes: 22 additions & 0 deletions Tests/rv32i/alu.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ let ``SUB: x3 = x2 - x1`` (x1, x2, x3) =
[<Theory>]
[<InlineData(5, 0b101101, 0b10110100000)>]
[<InlineData(0, 0b101101, 0b101101)>]
// Edge cases: RV32 uses only the low 5 bits of the shift amount (rs2[4:0], mask 0x1f)
[<InlineData(32, 0b101101, 0b101101)>] // 32 & 0x1f = 0 -> value unchanged (regression case)
[<InlineData(33, 0b101101, 0b1011010)>] // 33 & 0x1f = 1
[<InlineData(31, 1, 0x80000000)>] // shift into the sign bit
[<InlineData(63, 1, 0x80000000)>] // bit 5 masked off: 63 & 0x1f = 31
[<InlineData(37, 1, 32)>] // arbitrary high bits masked: 37 & 0x1f = 5
[<InlineData(1, 0xFFFFFFFF, 0xFFFFFFFE)>] // overflow shifted off the top (32-bit result)
let ``SLL: x3 = x2 << x1`` (x1, x2, x3) =
ALU 0x001111b3 x1 x2 x3

Expand Down Expand Up @@ -83,12 +90,27 @@ let ``XOR: x3 = x2 ^ x1`` (x1, x2, x3) =
[<InlineData(0b101, 0b1011001101, 0b0000010110)>]
[<InlineData(0b101, 0b11001100101, 0b00000110011)>]
[<InlineData(0b101, 0b11110000111100000000000000001111, 0b00000111100001111000000000000000)>]
// Edge cases: logical (zero-fill) shift, shift amount masked to rs2[4:0]
[<InlineData(32, 0b1011001101, 0b1011001101)>] // 32 & 0x1f = 0 -> value unchanged
[<InlineData(33, 0b1011001101, 0b101100110)>] // 33 & 0x1f = 1
[<InlineData(1, 0xFFFFFFFF, 0x7FFFFFFF)>] // zero-fill, not sign-fill
[<InlineData(33, 0xFFFFFFFF, 0x7FFFFFFF)>] // 33 & 0x1f = 1 (same as shift 1)
[<InlineData(63, 0x80000000, 1)>] // 63 & 0x1f = 31
[<InlineData(37, 0xFFFFFFFF, 0x07FFFFFF)>] // 37 & 0x1f = 5
let ``SRL: x3 = x2 >> x1`` (x1, x2, x3) =
ALU 0x001151b3 x1 x2 x3

[<Theory>]
[<InlineData(0b101, 0b1011001101, 0b0000010110)>]
[<InlineData(0b101, 0b11110000111100000000000000001111, 0b11111111100001111000000000000000)>]
// Edge cases: arithmetic (sign-fill) shift, shift amount masked to rs2[4:0]
[<InlineData(32, 0x40000000, 0x40000000)>] // 32 & 0x1f = 0 -> value unchanged (regression case)
[<InlineData(33, 0x40000000, 0x20000000)>] // 33 & 0x1f = 1
[<InlineData(1, 0xFFFFFFFF, -1)>] // sign-fill: -1 >> 1 stays -1
[<InlineData(33, 0xFFFFFFFF, -1)>] // 33 & 0x1f = 1 (same as shift 1)
[<InlineData(31, 0x80000000, -1)>] // sign bit smeared across the word
[<InlineData(63, 0x80000000, -1)>] // 63 & 0x1f = 31
[<InlineData(37, 0x40000000, 0x2000000)>] // 37 & 0x1f = 5
let ``SRA: x3 = x2 >> x1`` (x1, x2, x3) =
ALU 0x401151b3 x1 x2 x3

Expand Down