Skip to main content

ab_riscv_interpreter/rv32/b/
zbs.rs

1//! RV32 Zbs extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::{
7    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
8    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
9    RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
10    ThreadedExecutionResult,
11};
12use ab_riscv_macros::instruction_execution;
13use ab_riscv_primitives::prelude::*;
14
15#[instruction_execution]
16const impl<Reg, Hart> ExecutableInstructionOperands for Rv32ZbsInstruction<Hart>
17where
18    Reg: Register<Type = u32>,
19    Hart: HartConfig<Reg = Reg>,
20{
21}
22
23#[instruction_execution]
24const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZbsInstruction<Hart>
25where
26    Reg: Register<Type = u32>,
27    Hart: HartConfig<Reg = Reg>,
28{
29}
30
31#[instruction_execution]
32const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
33    for Rv32ZbsInstruction<Hart>
34where
35    Reg: [const] Register<Type = u32>,
36    Hart: HartConfig<Reg = Reg>,
37    Regs: [const] RegisterFile<Reg>,
38{
39    #[inline(always)]
40    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
41    fn execute(
42        self,
43        Rs1Rs2OperandValues {
44            rs1_value,
45            rs2_value,
46        }: Rs1Rs2OperandValues<Reg::Type>,
47        _regs: &mut Regs,
48        _env: &mut Env,
49        _memory: &mut Memory,
50        _program_counter: &PC,
51    ) -> ExecutionResult<Reg> {
52        match self {
53            Self::Bset { rd, rs1: _, rs2: _ } => {
54                // Only the bottom 5 bits for RV32
55                let index = rs2_value & 0x1f;
56                let result = rs1_value | (1u32 << index);
57                ExecutionResult::Continue { rd, value: result }
58            }
59            Self::Bseti { rd, rs1: _, shamt } => {
60                let index = shamt.get();
61                let result = rs1_value | (1u32 << index);
62                ExecutionResult::Continue { rd, value: result }
63            }
64            Self::Bclr { rd, rs1: _, rs2: _ } => {
65                let index = rs2_value & 0x1f;
66                let result = rs1_value & !(1u32 << index);
67                ExecutionResult::Continue { rd, value: result }
68            }
69            Self::Bclri { rd, rs1: _, shamt } => {
70                let index = shamt.get();
71                let result = rs1_value & !(1u32 << index);
72                ExecutionResult::Continue { rd, value: result }
73            }
74            Self::Binv { rd, rs1: _, rs2: _ } => {
75                let index = rs2_value & 0x1f;
76                let result = rs1_value ^ (1u32 << index);
77                ExecutionResult::Continue { rd, value: result }
78            }
79            Self::Binvi { rd, rs1: _, shamt } => {
80                let index = shamt.get();
81                let result = rs1_value ^ (1u32 << index);
82                ExecutionResult::Continue { rd, value: result }
83            }
84            Self::Bext { rd, rs1: _, rs2: _ } => {
85                let index = rs2_value & 0x1f;
86                let result = (rs1_value >> index) & 1;
87                ExecutionResult::Continue { rd, value: result }
88            }
89            Self::Bexti { rd, rs1: _, shamt } => {
90                let index = shamt.get();
91                let result = (rs1_value >> index) & 1;
92                ExecutionResult::Continue { rd, value: result }
93            }
94        }
95    }
96}