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