Skip to main content

ab_riscv_interpreter/rv64/zk/
zbkb.rs

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