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