Skip to main content

ab_riscv_interpreter/rv32/b/
zbb.rs

1//! RV32 Zbb extension
2
3pub mod rv32_zbb_helpers;
4#[cfg(test)]
5mod tests;
6
7use crate::{
8    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
10    RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
11    ThreadedExecutionResult,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15
16#[instruction_execution]
17const impl<Reg> ExecutableInstructionOperands for Rv32ZbbInstruction<Reg> where
18    Reg: Register<Type = u32>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZbbInstruction<Reg> where
24    Reg: Register<Type = u32>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30    for Rv32ZbbInstruction<Reg>
31where
32    Reg: [const] Register<Type = u32>,
33    Regs: [const] RegisterFile<Reg>,
34{
35    #[inline(always)]
36    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
37    fn execute(
38        self,
39        Rs1Rs2OperandValues {
40            rs1_value,
41            rs2_value,
42        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
43        _regs: &mut Regs,
44        _env: &mut Env,
45        _memory: &mut Memory,
46        _program_counter: &mut PC,
47    ) -> ExecutionResult<Self::Reg> {
48        match self {
49            Self::Andn { rd, rs1: _, rs2: _ } => {
50                let value = rs1_value & !rs2_value;
51                ExecutionResult::Continue { rd, value }
52            }
53            Self::Orn { rd, rs1: _, rs2: _ } => {
54                let value = rs1_value | !rs2_value;
55                ExecutionResult::Continue { rd, value }
56            }
57            Self::Xnor { rd, rs1: _, rs2: _ } => {
58                let value = !(rs1_value ^ rs2_value);
59                ExecutionResult::Continue { rd, value }
60            }
61            Self::Clz { rd, rs1: _ } => {
62                let value = rs1_value.leading_zeros();
63                ExecutionResult::Continue { rd, value }
64            }
65            Self::Ctz { rd, rs1: _ } => {
66                let value = rs1_value.trailing_zeros();
67                ExecutionResult::Continue { rd, value }
68            }
69            Self::Cpop { rd, rs1: _ } => {
70                let value = rs1_value.count_ones();
71                ExecutionResult::Continue { rd, value }
72            }
73            Self::Max { rd, rs1: _, rs2: _ } => {
74                let a = rs1_value.cast_signed();
75                let b = rs2_value.cast_signed();
76                let value = a.max(b).cast_unsigned();
77                ExecutionResult::Continue { rd, value }
78            }
79            Self::Maxu { rd, rs1: _, rs2: _ } => {
80                let value = rs1_value.max(rs2_value);
81                ExecutionResult::Continue { rd, value }
82            }
83            Self::Min { rd, rs1: _, rs2: _ } => {
84                let a = rs1_value.cast_signed();
85                let b = rs2_value.cast_signed();
86                let value = a.min(b).cast_unsigned();
87                ExecutionResult::Continue { rd, value }
88            }
89            Self::Minu { rd, rs1: _, rs2: _ } => {
90                let value = rs1_value.min(rs2_value);
91                ExecutionResult::Continue { rd, value }
92            }
93            Self::Sextb { rd, rs1: _ } => {
94                let value = i32::from(rs1_value as i8).cast_unsigned();
95                ExecutionResult::Continue { rd, value }
96            }
97            Self::Sexth { rd, rs1: _ } => {
98                let value = i32::from(rs1_value as i16).cast_unsigned();
99                ExecutionResult::Continue { rd, value }
100            }
101            Self::Zexth { rd, rs1: _ } => {
102                let value = u32::from(rs1_value as u16);
103                ExecutionResult::Continue { rd, value }
104            }
105            Self::Rol { rd, rs1: _, rs2: _ } => {
106                let shamt = rs2_value & 0x1f;
107                let value = rs1_value.rotate_left(shamt);
108                ExecutionResult::Continue { rd, value }
109            }
110            Self::Ror { rd, rs1: _, rs2: _ } => {
111                let shamt = rs2_value & 0x1f;
112                let value = rs1_value.rotate_right(shamt);
113                ExecutionResult::Continue { rd, value }
114            }
115            Self::Rori { rd, rs1: _, shamt } => {
116                let value = rs1_value.rotate_right(u32::from(shamt & 0x1f));
117                ExecutionResult::Continue { rd, value }
118            }
119            Self::Orcb { rd, rs1: _ } => {
120                let src = rs1_value;
121
122                ExecutionResult::Continue {
123                    rd,
124                    value: rv32_zbb_helpers::orc_b(src),
125                }
126            }
127            Self::Rev8 { rd, rs1: _ } => {
128                let value = rs1_value.swap_bytes();
129                ExecutionResult::Continue { rd, value }
130            }
131        }
132    }
133}