Skip to main content

ab_riscv_interpreter/rv64/zk/
zbkb.rs

1//! RV64 Zbkb extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::{ExecutableInstruction, ExecutionError, RegisterFile};
7use ab_riscv_macros::instruction_execution;
8use ab_riscv_primitives::prelude::*;
9use core::ops::ControlFlow;
10
11#[instruction_execution]
12impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
13    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
14    for Rv64ZbkbInstruction<Reg>
15where
16    Reg: Register<Type = u64>,
17    Regs: RegisterFile<Reg>,
18{
19    #[inline(always)]
20    fn execute(
21        self,
22        regs: &mut Regs,
23        _ext_state: &mut ExtState,
24        _memory: &mut Memory,
25        _program_counter: &mut PC,
26        _system_instruction_handler: &mut InstructionHandler,
27    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
28        match self {
29            Self::Pack { rd, rs1, rs2 } => {
30                // Pack lower 32 bits of rs1 into lower 32 bits of rd,
31                // lower 32 bits of rs2 into upper 32 bits of rd.
32                let lo = regs.read(rs1) & 0x0000_0000_FFFF_FFFFu64;
33                let hi = (regs.read(rs2) & 0x0000_0000_FFFF_FFFFu64) << 32;
34                regs.write(rd, lo | hi);
35            }
36            Self::Packh { rd, rs1, rs2 } => {
37                // Pack low byte of rs1 into bits [7:0], low byte of rs2 into bits [15:8].
38                // Upper bits of rd are zeroed.
39                let lo = regs.read(rs1) & 0xFF;
40                let hi = (regs.read(rs2) & 0xFF) << 8;
41                regs.write(rd, lo | hi);
42            }
43            Self::Packw { rd, rs1, rs2 } => {
44                // Pack low 16 bits of rs1 into bits [15:0] of the 32-bit result,
45                // low 16 bits of rs2 into bits [31:16], then sign-extend to 64 bits.
46                let lo = regs.read(rs1) & 0xFFFF;
47                let hi = (regs.read(rs2) & 0xFFFF) << 16;
48                let word = (lo | hi) as u32;
49                let value = i64::from(word.cast_signed()).cast_unsigned();
50                regs.write(rd, value);
51            }
52            Self::Brev8 { rd, rs1 } => {
53                // Reverse bits within each byte of rs1
54                let src = regs.read(rs1);
55                let mut bytes = src.to_le_bytes();
56                for byte in &mut bytes {
57                    *byte = byte.reverse_bits();
58                }
59                regs.write(rd, u64::from_le_bytes(bytes));
60            }
61        }
62
63        Ok(ControlFlow::Continue(()))
64    }
65}