ab_riscv_interpreter/rv64/b/
zbb.rs1pub 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}