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