Skip to main content

ab_riscv_interpreter/rv32/zce/
zcb.rs

1//! Zcb compressed instruction execution (RV32)
2//!
3//! C.ZEXT.W is absent in RV32 - the enum has no such variant.
4
5#[cfg(test)]
6mod tests;
7
8use crate::{
9    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
10    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
11    PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
12    SystemInstructionHandler, ThreadedExecutableInstruction, ThreadedExecutionResult,
13    VirtualMemory,
14};
15use ab_riscv_macros::instruction_execution;
16use ab_riscv_primitives::prelude::*;
17
18#[instruction_execution]
19const impl<Reg, Hart> ExecutableInstructionOperands for Rv32ZcbInstruction<Hart>
20where
21    Reg: Register<Type = u32>,
22    Hart: HartConfig<Reg = Reg>,
23{
24}
25
26#[instruction_execution]
27const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZcbInstruction<Hart>
28where
29    Reg: Register<Type = u32>,
30    Hart: HartConfig<Reg = Reg>,
31{
32}
33
34#[instruction_execution]
35const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
36    for Rv32ZcbInstruction<Hart>
37where
38    Reg: [const] Register<Type = u32>,
39    Hart: HartConfig<Reg = Reg>,
40{
41    #[inline(always)]
42    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
43    fn execute(
44        self,
45        Rs1Rs2OperandValues {
46            rs1_value,
47            rs2_value,
48        }: Rs1Rs2OperandValues<Reg::Type>,
49        regs: &mut Regs,
50        _env: &mut Env,
51        memory: &mut Memory,
52        program_counter: &PC,
53    ) -> ExecutionResult<Reg> {
54        ExecutionResult::ContinueNoWrite
55    }
56}
57
58#[instruction_execution]
59const impl<Reg, Hart> ExecutableInstructionOperands for Rv32ZcbOnlyInstruction<Hart>
60where
61    Reg: Register<Type = u32>,
62    Hart: HartConfig<Reg = Reg>,
63{
64}
65
66#[instruction_execution]
67const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZcbOnlyInstruction<Hart>
68where
69    Reg: Register<Type = u32>,
70    Hart: HartConfig<Reg = Reg>,
71{
72}
73
74#[instruction_execution]
75const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
76    for Rv32ZcbOnlyInstruction<Hart>
77where
78    Reg: [const] Register<Type = u32>,
79    Hart: HartConfig<Reg = Reg>,
80    Regs: [const] RegisterFile<Reg>,
81    Memory: [const] VirtualMemory,
82    PC: [const] ProgramCounter<Reg::Type, Memory>,
83    Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
84{
85    #[inline(always)]
86    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
87    fn execute(
88        self,
89        Rs1Rs2OperandValues {
90            rs1_value,
91            rs2_value,
92        }: Rs1Rs2OperandValues<Reg::Type>,
93        regs: &mut Regs,
94        _env: &mut Env,
95        memory: &mut Memory,
96        _program_counter: &PC,
97    ) -> ExecutionResult<Reg> {
98        match self {
99            Self::CLbu { rd, rs1: _, uimm } => {
100                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
101                let value = memory.read::<u8>(addr)?;
102                ExecutionResult::Continue {
103                    rd,
104                    value: u32::from(value),
105                }
106            }
107            Self::CLh { rd, rs1: _, uimm } => {
108                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
109                let value = i32::from(memory.read::<i16>(addr)?);
110                ExecutionResult::Continue {
111                    rd,
112                    value: value.cast_unsigned(),
113                }
114            }
115            Self::CLhu { rd, rs1: _, uimm } => {
116                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
117                let value = memory.read::<u16>(addr)?;
118                ExecutionResult::Continue {
119                    rd,
120                    value: u32::from(value),
121                }
122            }
123            Self::CSb {
124                rs1: _,
125                rs2: _,
126                uimm,
127            } => {
128                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
129                memory.write(addr, rs2_value as u8)?;
130                ExecutionResult::ContinueNoWrite
131            }
132            Self::CSh {
133                rs1: _,
134                rs2: _,
135                uimm,
136            } => {
137                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
138                memory.write(addr, rs2_value as u16)?;
139                ExecutionResult::ContinueNoWrite
140            }
141            Self::CZextB { rd } => {
142                let value = regs.read(rd) & 0xff;
143                ExecutionResult::Continue { rd, value }
144            }
145            Self::CSextB { rd } => {
146                let value = i32::from(regs.read(rd) as i8);
147                ExecutionResult::Continue {
148                    rd,
149                    value: value.cast_unsigned(),
150                }
151            }
152            Self::CZextH { rd } => {
153                let value = regs.read(rd) & 0xffff;
154                ExecutionResult::Continue { rd, value }
155            }
156            Self::CSextH { rd } => {
157                let value = i32::from(regs.read(rd) as i16);
158                ExecutionResult::Continue {
159                    rd,
160                    value: value.cast_unsigned(),
161                }
162            }
163            Self::CNot { rd } => {
164                let value = !regs.read(rd);
165                ExecutionResult::Continue { rd, value }
166            }
167            Self::CMul { rd, rs2: _ } => {
168                let value = regs.read(rd).wrapping_mul(rs2_value);
169                ExecutionResult::Continue { rd, value }
170            }
171        }
172    }
173}