Skip to main content

ab_riscv_interpreter/rv32/zk/
zbkb.rs

1//! RV32 Zbkb extension
2
3pub mod rv32_zbkb_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 Rv32ZbkbInstruction<Reg>
16where
17    Reg: Register<Type = u32>,
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::Pack { rd, rs1, rs2 } => {
31                // Pack low 16 bits of rs1 into rd[15:0],
32                // low 16 bits of rs2 into rd[31:16].
33                let lo = regs.read(rs1) & 0x0000_FFFFu32;
34                let hi = (regs.read(rs2) & 0x0000_FFFFu32) << 16;
35                regs.write(rd, lo | hi);
36            }
37            Self::Packh { rd, rs1, rs2 } => {
38                // Pack low byte of rs1 into bits [7:0], low byte of rs2 into bits [15:8].
39                // Upper bits of rd are zeroed.
40                let lo = regs.read(rs1) & 0xFF;
41                let hi = (regs.read(rs2) & 0xFF) << 8;
42                regs.write(rd, lo | hi);
43            }
44            Self::Brev8 { rd, rs1 } => {
45                // Reverse bits within each byte of rs1
46                let src = regs.read(rs1);
47                let mut bytes = src.to_le_bytes();
48                for byte in &mut bytes {
49                    *byte = byte.reverse_bits();
50                }
51                regs.write(rd, u32::from_le_bytes(bytes));
52            }
53            Self::Zip { rd, rs1 } => {
54                // Bit-interleave: scatter bits of rs1 so that
55                // rs1[i]    -> rd[2*i]   (even positions, lower half source)
56                // rs1[i+16] -> rd[2*i+1] (odd positions, upper half source)
57                // for i in 0..16.
58                let src = regs.read(rs1);
59
60                regs.write(rd, rv32_zbkb_helpers::zip(src));
61            }
62            Self::Unzip { rd, rs1 } => {
63                // Inverse of zip: gather bits of rs1 so that
64                // rs1[2*i]   -> rd[i]    (even-position bits -> lower half)
65                // rs1[2*i+1] -> rd[i+16] (odd-position bits -> upper half)
66                // for i in 0..16.
67                let src = regs.read(rs1);
68
69                regs.write(rd, rv32_zbkb_helpers::unzip(src));
70            }
71        }
72
73        Ok(ControlFlow::Continue(()))
74    }
75}