Skip to main content

ab_riscv_interpreter/rv64/b/
zbb.rs

1//! RV64 Zbb extension
2
3pub mod rv64_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 Rv64ZbbZbkbSharedInstruction<Hart>
18where
19    Reg: Register<Type = u64>,
20    Hart: HartConfig<Reg = Reg>,
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv64ZbbZbkbSharedInstruction<Hart>
26where
27    Reg: Register<Type = u64>,
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 Rv64ZbbZbkbSharedInstruction<Hart>
35where
36    Reg: [const] Register<Type = u64>,
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 & 0x3f) as u32;
68                let value = rs1_value.rotate_left(shamt);
69                ExecutionResult::Continue { rd, value }
70            }
71            Self::Rolw { rd, rs1: _, rs2: _ } => {
72                let shamt = (rs2_value & 0x1f) as u32;
73                let value = i64::from((rs1_value as u32).rotate_left(shamt).cast_signed());
74                ExecutionResult::Continue {
75                    rd,
76                    value: value.cast_unsigned(),
77                }
78            }
79            Self::Ror { rd, rs1: _, rs2: _ } => {
80                let shamt = (rs2_value & 0x3f) as u32;
81                let value = rs1_value.rotate_right(shamt);
82                ExecutionResult::Continue { rd, value }
83            }
84            Self::Rori { rd, rs1: _, shamt } => {
85                let value = rs1_value.rotate_right(shamt.get());
86                ExecutionResult::Continue { rd, value }
87            }
88            Self::Roriw { rd, rs1: _, shamt } => {
89                let value = i64::from((rs1_value as u32).rotate_right(shamt.get()).cast_signed());
90                ExecutionResult::Continue {
91                    rd,
92                    value: value.cast_unsigned(),
93                }
94            }
95            Self::Rorw { rd, rs1: _, rs2: _ } => {
96                let shamt = (rs2_value & 0x1f) as u32;
97                let value = i64::from((rs1_value as u32).rotate_right(shamt).cast_signed());
98                ExecutionResult::Continue {
99                    rd,
100                    value: value.cast_unsigned(),
101                }
102            }
103            Self::Rev8 { rd, rs1: _ } => {
104                let value = rs1_value.swap_bytes();
105                ExecutionResult::Continue { rd, value }
106            }
107        }
108    }
109}
110
111#[instruction_execution]
112const impl<Reg, Hart> ExecutableInstructionOperands for Rv64ZbbInstruction<Hart>
113where
114    Reg: Register<Type = u64>,
115    Hart: HartConfig<Reg = Reg>,
116{
117}
118
119#[instruction_execution]
120const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv64ZbbInstruction<Hart>
121where
122    Reg: Register<Type = u64>,
123    Hart: HartConfig<Reg = Reg>,
124{
125}
126
127#[instruction_execution]
128const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
129    for Rv64ZbbInstruction<Hart>
130where
131    Reg: [const] Register<Type = u64>,
132    Hart: HartConfig<Reg = Reg>,
133    Regs: [const] RegisterFile<Reg>,
134{
135    #[inline(always)]
136    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
137    fn execute(
138        self,
139        Rs1Rs2OperandValues {
140            rs1_value,
141            rs2_value,
142        }: Rs1Rs2OperandValues<Reg::Type>,
143        _regs: &mut Regs,
144        _env: &mut Env,
145        _memory: &mut Memory,
146        _program_counter: &PC,
147    ) -> ExecutionResult<Reg> {
148        match self {
149            Self::Clz { rd, rs1: _ } => {
150                let value = u64::from(rs1_value.leading_zeros());
151                ExecutionResult::Continue { rd, value }
152            }
153            Self::Clzw { rd, rs1: _ } => {
154                let value = u64::from((rs1_value as u32).leading_zeros());
155                ExecutionResult::Continue { rd, value }
156            }
157            Self::Ctz { rd, rs1: _ } => {
158                let value = u64::from(rs1_value.trailing_zeros());
159                ExecutionResult::Continue { rd, value }
160            }
161            Self::Ctzw { rd, rs1: _ } => {
162                let value = u64::from((rs1_value as u32).trailing_zeros());
163                ExecutionResult::Continue { rd, value }
164            }
165            Self::Cpop { rd, rs1: _ } => {
166                let value = u64::from(rs1_value.count_ones());
167                ExecutionResult::Continue { rd, value }
168            }
169            Self::Cpopw { rd, rs1: _ } => {
170                let value = u64::from((rs1_value as u32).count_ones());
171                ExecutionResult::Continue { rd, value }
172            }
173            Self::Max { rd, rs1: _, rs2: _ } => {
174                let a = rs1_value.cast_signed();
175                let b = rs2_value.cast_signed();
176                let value = a.max(b).cast_unsigned();
177                ExecutionResult::Continue { rd, value }
178            }
179            Self::Maxu { rd, rs1: _, rs2: _ } => {
180                let value = rs1_value.max(rs2_value);
181                ExecutionResult::Continue { rd, value }
182            }
183            Self::Min { rd, rs1: _, rs2: _ } => {
184                let a = rs1_value.cast_signed();
185                let b = rs2_value.cast_signed();
186                let value = a.min(b).cast_unsigned();
187                ExecutionResult::Continue { rd, value }
188            }
189            Self::Minu { rd, rs1: _, rs2: _ } => {
190                let value = rs1_value.min(rs2_value);
191                ExecutionResult::Continue { rd, value }
192            }
193            Self::Sextb { rd, rs1: _ } => {
194                let value = i64::from(rs1_value as i8).cast_unsigned();
195                ExecutionResult::Continue { rd, value }
196            }
197            Self::Sexth { rd, rs1: _ } => {
198                let value = i64::from(rs1_value as i16).cast_unsigned();
199                ExecutionResult::Continue { rd, value }
200            }
201            Self::Zexth { rd, rs1: _ } => {
202                let value = u64::from(rs1_value as u16);
203                ExecutionResult::Continue { rd, value }
204            }
205            Self::Orcb { rd, rs1: _ } => {
206                let src = rs1_value;
207
208                ExecutionResult::Continue {
209                    rd,
210                    value: rv64_zbb_helpers::orc_b(src),
211                }
212            }
213        }
214    }
215}