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> ExecutableInstructionOperands for Rv64ZbbInstruction<Reg> where
18    Reg: Register<Type = u64>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64ZbbInstruction<Reg> where
24    Reg: Register<Type = u64>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30    for Rv64ZbbInstruction<Reg>
31where
32    Reg: [const] Register<Type = u64>,
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 = u64::from(rs1_value.leading_zeros());
63                ExecutionResult::Continue { rd, value }
64            }
65            Self::Clzw { rd, rs1: _ } => {
66                let value = u64::from((rs1_value as u32).leading_zeros());
67                ExecutionResult::Continue { rd, value }
68            }
69            Self::Ctz { rd, rs1: _ } => {
70                let value = u64::from(rs1_value.trailing_zeros());
71                ExecutionResult::Continue { rd, value }
72            }
73            Self::Ctzw { rd, rs1: _ } => {
74                let value = u64::from((rs1_value as u32).trailing_zeros());
75                ExecutionResult::Continue { rd, value }
76            }
77            Self::Cpop { rd, rs1: _ } => {
78                let value = u64::from(rs1_value.count_ones());
79                ExecutionResult::Continue { rd, value }
80            }
81            Self::Cpopw { rd, rs1: _ } => {
82                let value = u64::from((rs1_value as u32).count_ones());
83                ExecutionResult::Continue { rd, value }
84            }
85            Self::Max { rd, rs1: _, rs2: _ } => {
86                let a = rs1_value.cast_signed();
87                let b = rs2_value.cast_signed();
88                let value = a.max(b).cast_unsigned();
89                ExecutionResult::Continue { rd, value }
90            }
91            Self::Maxu { rd, rs1: _, rs2: _ } => {
92                let value = rs1_value.max(rs2_value);
93                ExecutionResult::Continue { rd, value }
94            }
95            Self::Min { rd, rs1: _, rs2: _ } => {
96                let a = rs1_value.cast_signed();
97                let b = rs2_value.cast_signed();
98                let value = a.min(b).cast_unsigned();
99                ExecutionResult::Continue { rd, value }
100            }
101            Self::Minu { rd, rs1: _, rs2: _ } => {
102                let value = rs1_value.min(rs2_value);
103                ExecutionResult::Continue { rd, value }
104            }
105            Self::Sextb { rd, rs1: _ } => {
106                let value = i64::from(rs1_value as i8).cast_unsigned();
107                ExecutionResult::Continue { rd, value }
108            }
109            Self::Sexth { rd, rs1: _ } => {
110                let value = i64::from(rs1_value as i16).cast_unsigned();
111                ExecutionResult::Continue { rd, value }
112            }
113            Self::Zexth { rd, rs1: _ } => {
114                let value = u64::from(rs1_value as u16);
115                ExecutionResult::Continue { rd, value }
116            }
117            Self::Rol { rd, rs1: _, rs2: _ } => {
118                let shamt = (rs2_value & 0x3f) as u32;
119                let value = rs1_value.rotate_left(shamt);
120                ExecutionResult::Continue { rd, value }
121            }
122            Self::Rolw { rd, rs1: _, rs2: _ } => {
123                let shamt = (rs2_value & 0x1f) as u32;
124                let value = i64::from((rs1_value as u32).rotate_left(shamt).cast_signed());
125                ExecutionResult::Continue {
126                    rd,
127                    value: value.cast_unsigned(),
128                }
129            }
130            Self::Ror { rd, rs1: _, rs2: _ } => {
131                let shamt = (rs2_value & 0x3f) as u32;
132                let value = rs1_value.rotate_right(shamt);
133                ExecutionResult::Continue { rd, value }
134            }
135            Self::Rori { rd, rs1: _, shamt } => {
136                let value = rs1_value.rotate_right(u32::from(shamt & 0x3f));
137                ExecutionResult::Continue { rd, value }
138            }
139            Self::Roriw { rd, rs1: _, shamt } => {
140                let value = i64::from(
141                    (rs1_value as u32)
142                        .rotate_right(u32::from(shamt & 0x1f))
143                        .cast_signed(),
144                );
145                ExecutionResult::Continue {
146                    rd,
147                    value: value.cast_unsigned(),
148                }
149            }
150            Self::Rorw { rd, rs1: _, rs2: _ } => {
151                let shamt = (rs2_value & 0x1f) as u32;
152                let value = i64::from((rs1_value as u32).rotate_right(shamt).cast_signed());
153                ExecutionResult::Continue {
154                    rd,
155                    value: value.cast_unsigned(),
156                }
157            }
158            Self::Orcb { rd, rs1: _ } => {
159                let src = rs1_value;
160
161                ExecutionResult::Continue {
162                    rd,
163                    value: rv64_zbb_helpers::orc_b(src),
164                }
165            }
166            Self::Rev8 { rd, rs1: _ } => {
167                let value = rs1_value.swap_bytes();
168                ExecutionResult::Continue { rd, value }
169            }
170        }
171    }
172}