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::{
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 Rv32ZbkbInstruction<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 Rv32ZbkbInstruction<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 Rv32ZbkbInstruction<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::Pack { rd, rs1: _, rs2: _ } => {
55                // Pack low 16 bits of rs1 into rd[15:0],
56                // low 16 bits of rs2 into rd[31:16].
57                let lo = rs1_value & 0x0000_FFFFu32;
58                let hi = (rs2_value & 0x0000_FFFFu32) << 16;
59                ExecutionResult::Continue { rd, value: lo | hi }
60            }
61            Self::Packh { rd, rs1: _, rs2: _ } => {
62                // Pack low byte of rs1 into bits [7:0], low byte of rs2 into bits [15:8].
63                // Upper bits of rd are zeroed.
64                let lo = rs1_value & 0xFF;
65                let hi = (rs2_value & 0xFF) << 8;
66                ExecutionResult::Continue { rd, value: lo | hi }
67            }
68            Self::Brev8 { rd, rs1: _ } => {
69                // Reverse bits within each byte of rs1
70                let bytes = rs1_value.to_le_bytes();
71                let value = u32::from_le_bytes([
72                    bytes[0].reverse_bits(),
73                    bytes[1].reverse_bits(),
74                    bytes[2].reverse_bits(),
75                    bytes[3].reverse_bits(),
76                ]);
77                ExecutionResult::Continue { rd, value }
78            }
79            Self::Zip { rd, rs1: _ } => {
80                // Bit-interleave: scatter bits of rs1 so that
81                // rs1[i]    -> rd[2*i]   (even positions, lower half source)
82                // rs1[i+16] -> rd[2*i+1] (odd positions, upper half source)
83                // for i in 0..16.
84                let src = rs1_value;
85
86                ExecutionResult::Continue {
87                    rd,
88                    value: rv32_zbkb_helpers::zip(src),
89                }
90            }
91            Self::Unzip { rd, rs1: _ } => {
92                // Inverse of zip: gather bits of rs1 so that
93                // rs1[2*i]   -> rd[i]    (even-position bits -> lower half)
94                // rs1[2*i+1] -> rd[i+16] (odd-position bits -> upper half)
95                // for i in 0..16.
96                let src = rs1_value;
97
98                ExecutionResult::Continue {
99                    rd,
100                    value: rv32_zbkb_helpers::unzip(src),
101                }
102            }
103        }
104    }
105}