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> ExecutableInstructionOperands for Rv32ZbkbInstruction<Reg> where
18    Reg: Register<Type = u32>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZbkbInstruction<Reg> where
24    Reg: Register<Type = u32>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30    for Rv32ZbkbInstruction<Reg>
31where
32    Reg: [const] Register<Type = u32>,
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::Pack { rd, rs1: _, rs2: _ } => {
50                // Pack low 16 bits of rs1 into rd[15:0],
51                // low 16 bits of rs2 into rd[31:16].
52                let lo = rs1_value & 0x0000_FFFFu32;
53                let hi = (rs2_value & 0x0000_FFFFu32) << 16;
54                ExecutionResult::Continue { rd, value: lo | hi }
55            }
56            Self::Packh { rd, rs1: _, rs2: _ } => {
57                // Pack low byte of rs1 into bits [7:0], low byte of rs2 into bits [15:8].
58                // Upper bits of rd are zeroed.
59                let lo = rs1_value & 0xFF;
60                let hi = (rs2_value & 0xFF) << 8;
61                ExecutionResult::Continue { rd, value: lo | hi }
62            }
63            Self::Brev8 { rd, rs1: _ } => {
64                // Reverse bits within each byte of rs1
65                let bytes = rs1_value.to_le_bytes();
66                let value = u32::from_le_bytes([
67                    bytes[0].reverse_bits(),
68                    bytes[1].reverse_bits(),
69                    bytes[2].reverse_bits(),
70                    bytes[3].reverse_bits(),
71                ]);
72                ExecutionResult::Continue { rd, value }
73            }
74            Self::Zip { rd, rs1: _ } => {
75                // Bit-interleave: scatter bits of rs1 so that
76                // rs1[i]    -> rd[2*i]   (even positions, lower half source)
77                // rs1[i+16] -> rd[2*i+1] (odd positions, upper half source)
78                // for i in 0..16.
79                let src = rs1_value;
80
81                ExecutionResult::Continue {
82                    rd,
83                    value: rv32_zbkb_helpers::zip(src),
84                }
85            }
86            Self::Unzip { rd, rs1: _ } => {
87                // Inverse of zip: gather bits of rs1 so that
88                // rs1[2*i]   -> rd[i]    (even-position bits -> lower half)
89                // rs1[2*i+1] -> rd[i+16] (odd-position bits -> upper half)
90                // for i in 0..16.
91                let src = rs1_value;
92
93                ExecutionResult::Continue {
94                    rd,
95                    value: rv32_zbkb_helpers::unzip(src),
96                }
97            }
98        }
99    }
100}