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> 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}