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::{ExecutableInstruction, ExecutionError, RegisterFile};
8use ab_riscv_macros::instruction_execution;
9use ab_riscv_primitives::prelude::*;
10use core::ops::ControlFlow;
11
12#[instruction_execution]
13impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
14    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
15    for Rv64ZbbInstruction<Reg>
16where
17    Reg: Register<Type = u64>,
18    Regs: RegisterFile<Reg>,
19{
20    #[inline(always)]
21    fn execute(
22        self,
23        regs: &mut Regs,
24        _ext_state: &mut ExtState,
25        _memory: &mut Memory,
26        _program_counter: &mut PC,
27        _system_instruction_handler: &mut InstructionHandler,
28    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
29        match self {
30            Self::Andn { rd, rs1, rs2 } => {
31                let value = regs.read(rs1) & !regs.read(rs2);
32                regs.write(rd, value);
33            }
34            Self::Orn { rd, rs1, rs2 } => {
35                let value = regs.read(rs1) | !regs.read(rs2);
36                regs.write(rd, value);
37            }
38            Self::Xnor { rd, rs1, rs2 } => {
39                let value = !(regs.read(rs1) ^ regs.read(rs2));
40                regs.write(rd, value);
41            }
42            Self::Clz { rd, rs1 } => {
43                let value = u64::from(regs.read(rs1).leading_zeros());
44                regs.write(rd, value);
45            }
46            Self::Clzw { rd, rs1 } => {
47                let value = u64::from((regs.read(rs1) as u32).leading_zeros());
48                regs.write(rd, value);
49            }
50            Self::Ctz { rd, rs1 } => {
51                let value = u64::from(regs.read(rs1).trailing_zeros());
52                regs.write(rd, value);
53            }
54            Self::Ctzw { rd, rs1 } => {
55                let value = u64::from((regs.read(rs1) as u32).trailing_zeros());
56                regs.write(rd, value);
57            }
58            Self::Cpop { rd, rs1 } => {
59                let value = u64::from(regs.read(rs1).count_ones());
60                regs.write(rd, value);
61            }
62            Self::Cpopw { rd, rs1 } => {
63                let value = u64::from((regs.read(rs1) as u32).count_ones());
64                regs.write(rd, value);
65            }
66            Self::Max { rd, rs1, rs2 } => {
67                let a = regs.read(rs1).cast_signed();
68                let b = regs.read(rs2).cast_signed();
69                let value = a.max(b).cast_unsigned();
70                regs.write(rd, value);
71            }
72            Self::Maxu { rd, rs1, rs2 } => {
73                let value = regs.read(rs1).max(regs.read(rs2));
74                regs.write(rd, value);
75            }
76            Self::Min { rd, rs1, rs2 } => {
77                let a = regs.read(rs1).cast_signed();
78                let b = regs.read(rs2).cast_signed();
79                let value = a.min(b).cast_unsigned();
80                regs.write(rd, value);
81            }
82            Self::Minu { rd, rs1, rs2 } => {
83                let value = regs.read(rs1).min(regs.read(rs2));
84                regs.write(rd, value);
85            }
86            Self::Sextb { rd, rs1 } => {
87                let value = i64::from(regs.read(rs1) as i8).cast_unsigned();
88                regs.write(rd, value);
89            }
90            Self::Sexth { rd, rs1 } => {
91                let value = i64::from(regs.read(rs1) as i16).cast_unsigned();
92                regs.write(rd, value);
93            }
94            Self::Zexth { rd, rs1 } => {
95                let value = u64::from(regs.read(rs1) as u16);
96                regs.write(rd, value);
97            }
98            Self::Rol { rd, rs1, rs2 } => {
99                let shamt = (regs.read(rs2) & 0x3f) as u32;
100                let value = regs.read(rs1).rotate_left(shamt);
101                regs.write(rd, value);
102            }
103            Self::Rolw { rd, rs1, rs2 } => {
104                let shamt = (regs.read(rs2) & 0x1f) as u32;
105                let value = i64::from((regs.read(rs1) as u32).rotate_left(shamt).cast_signed());
106                regs.write(rd, value.cast_unsigned());
107            }
108            Self::Ror { rd, rs1, rs2 } => {
109                let shamt = (regs.read(rs2) & 0x3f) as u32;
110                let value = regs.read(rs1).rotate_right(shamt);
111                regs.write(rd, value);
112            }
113            Self::Rori { rd, rs1, shamt } => {
114                let value = regs.read(rs1).rotate_right(u32::from(shamt & 0x3f));
115                regs.write(rd, value);
116            }
117            Self::Roriw { rd, rs1, shamt } => {
118                let value = i64::from(
119                    (regs.read(rs1) as u32)
120                        .rotate_right((shamt & 0x1f) as u32)
121                        .cast_signed(),
122                );
123                regs.write(rd, value.cast_unsigned());
124            }
125            Self::Rorw { rd, rs1, rs2 } => {
126                let shamt = (regs.read(rs2) & 0x1f) as u32;
127                let value = i64::from((regs.read(rs1) as u32).rotate_right(shamt).cast_signed());
128                regs.write(rd, value.cast_unsigned());
129            }
130            Self::Orcb { rd, rs1 } => {
131                let src = regs.read(rs1);
132
133                regs.write(rd, rv64_zbb_helpers::orc_b(src));
134            }
135            Self::Rev8 { rd, rs1 } => {
136                let value = regs.read(rs1).swap_bytes();
137                regs.write(rd, value);
138            }
139        }
140
141        Ok(ControlFlow::Continue(()))
142    }
143}