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, Hart> ExecutableInstructionOperands for Rv32ZbbZbkbSharedInstruction<Hart>
18where
19    Reg: Register<Type = u32>,
20    Hart: HartConfig<Reg = Reg>,
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZbbZbkbSharedInstruction<Hart>
26where
27    Reg: Register<Type = u32>,
28    Hart: HartConfig<Reg = Reg>,
29{
30}
31
32#[instruction_execution]
33const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
34    for Rv32ZbbZbkbSharedInstruction<Hart>
35where
36    Reg: [const] Register<Type = u32>,
37    Hart: HartConfig<Reg = Reg>,
38    Regs: [const] RegisterFile<Reg>,
39{
40    #[inline(always)]
41    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
42    fn execute(
43        self,
44        Rs1Rs2OperandValues {
45            rs1_value,
46            rs2_value,
47        }: Rs1Rs2OperandValues<Reg::Type>,
48        _regs: &mut Regs,
49        _env: &mut Env,
50        _memory: &mut Memory,
51        _program_counter: &PC,
52    ) -> ExecutionResult<Reg> {
53        match self {
54            Self::Andn { rd, rs1: _, rs2: _ } => {
55                let value = rs1_value & !rs2_value;
56                ExecutionResult::Continue { rd, value }
57            }
58            Self::Orn { rd, rs1: _, rs2: _ } => {
59                let value = rs1_value | !rs2_value;
60                ExecutionResult::Continue { rd, value }
61            }
62            Self::Xnor { rd, rs1: _, rs2: _ } => {
63                let value = !(rs1_value ^ rs2_value);
64                ExecutionResult::Continue { rd, value }
65            }
66            Self::Rol { rd, rs1: _, rs2: _ } => {
67                let shamt = rs2_value & 0x1f;
68                let value = rs1_value.rotate_left(shamt);
69                ExecutionResult::Continue { rd, value }
70            }
71            Self::Ror { rd, rs1: _, rs2: _ } => {
72                let shamt = rs2_value & 0x1f;
73                let value = rs1_value.rotate_right(shamt);
74                ExecutionResult::Continue { rd, value }
75            }
76            Self::Rori { rd, rs1: _, shamt } => {
77                let value = rs1_value.rotate_right(shamt.get());
78                ExecutionResult::Continue { rd, value }
79            }
80            Self::Rev8 { rd, rs1: _ } => {
81                let value = rs1_value.swap_bytes();
82                ExecutionResult::Continue { rd, value }
83            }
84        }
85    }
86}
87
88#[instruction_execution]
89const impl<Reg, Hart> ExecutableInstructionOperands for Rv32ZbbInstruction<Hart>
90where
91    Reg: Register<Type = u32>,
92    Hart: HartConfig<Reg = Reg>,
93{
94}
95
96#[instruction_execution]
97const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZbbInstruction<Hart>
98where
99    Reg: Register<Type = u32>,
100    Hart: HartConfig<Reg = Reg>,
101{
102}
103
104#[instruction_execution]
105const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
106    for Rv32ZbbInstruction<Hart>
107where
108    Reg: [const] Register<Type = u32>,
109    Hart: HartConfig<Reg = Reg>,
110    Regs: [const] RegisterFile<Reg>,
111{
112    #[inline(always)]
113    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
114    fn execute(
115        self,
116        Rs1Rs2OperandValues {
117            rs1_value,
118            rs2_value,
119        }: Rs1Rs2OperandValues<Reg::Type>,
120        _regs: &mut Regs,
121        _env: &mut Env,
122        _memory: &mut Memory,
123        _program_counter: &PC,
124    ) -> ExecutionResult<Reg> {
125        match self {
126            Self::Clz { rd, rs1: _ } => {
127                let value = rs1_value.leading_zeros();
128                ExecutionResult::Continue { rd, value }
129            }
130            Self::Ctz { rd, rs1: _ } => {
131                let value = rs1_value.trailing_zeros();
132                ExecutionResult::Continue { rd, value }
133            }
134            Self::Cpop { rd, rs1: _ } => {
135                let value = rs1_value.count_ones();
136                ExecutionResult::Continue { rd, value }
137            }
138            Self::Max { rd, rs1: _, rs2: _ } => {
139                let a = rs1_value.cast_signed();
140                let b = rs2_value.cast_signed();
141                let value = a.max(b).cast_unsigned();
142                ExecutionResult::Continue { rd, value }
143            }
144            Self::Maxu { rd, rs1: _, rs2: _ } => {
145                let value = rs1_value.max(rs2_value);
146                ExecutionResult::Continue { rd, value }
147            }
148            Self::Min { rd, rs1: _, rs2: _ } => {
149                let a = rs1_value.cast_signed();
150                let b = rs2_value.cast_signed();
151                let value = a.min(b).cast_unsigned();
152                ExecutionResult::Continue { rd, value }
153            }
154            Self::Minu { rd, rs1: _, rs2: _ } => {
155                let value = rs1_value.min(rs2_value);
156                ExecutionResult::Continue { rd, value }
157            }
158            Self::Sextb { rd, rs1: _ } => {
159                let value = i32::from(rs1_value as i8).cast_unsigned();
160                ExecutionResult::Continue { rd, value }
161            }
162            Self::Sexth { rd, rs1: _ } => {
163                let value = i32::from(rs1_value as i16).cast_unsigned();
164                ExecutionResult::Continue { rd, value }
165            }
166            Self::Zexth { rd, rs1: _ } => {
167                let value = u32::from(rs1_value as u16);
168                ExecutionResult::Continue { rd, value }
169            }
170            Self::Orcb { rd, rs1: _ } => {
171                let src = rs1_value;
172
173                ExecutionResult::Continue {
174                    rd,
175                    value: rv32_zbb_helpers::orc_b(src),
176                }
177            }
178        }
179    }
180}