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::*;
17use core::ops::ControlFlow;
18
19#[instruction_execution]
20const impl<Reg> ExecutableInstructionOperands for Rv32ZcbInstruction<Reg> where
21    Reg: Register<Type = u32>
22{
23}
24
25#[instruction_execution]
26const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZcbInstruction<Reg> where
27    Reg: Register<Type = u32>
28{
29}
30
31#[instruction_execution]
32const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
33    for Rv32ZcbInstruction<Reg>
34where
35    Reg: [const] Register<Type = u32>,
36{
37    #[inline(always)]
38    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
39    fn execute(
40        self,
41        Rs1Rs2OperandValues {
42            rs1_value,
43            rs2_value,
44        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
45        regs: &mut Regs,
46        _env: &mut Env,
47        memory: &mut Memory,
48        program_counter: &mut PC,
49    ) -> ExecutionResult<Self::Reg> {
50        ExecutionResult::ContinueNoWrite
51    }
52}
53
54#[instruction_execution]
55const impl<Reg> ExecutableInstructionOperands for Rv32ZcbOnlyInstruction<Reg> where
56    Reg: Register<Type = u32>
57{
58}
59
60#[instruction_execution]
61const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZcbOnlyInstruction<Reg> where
62    Reg: Register<Type = u32>
63{
64}
65
66#[instruction_execution]
67const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
68    for Rv32ZcbOnlyInstruction<Reg>
69where
70    Reg: [const] Register<Type = u32>,
71    Regs: [const] RegisterFile<Reg>,
72    Memory: [const] VirtualMemory,
73    PC: [const] ProgramCounter<Reg::Type, Memory>,
74    Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
75{
76    #[inline(always)]
77    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
78    fn execute(
79        self,
80        Rs1Rs2OperandValues {
81            rs1_value,
82            rs2_value,
83        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
84        regs: &mut Regs,
85        _env: &mut Env,
86        memory: &mut Memory,
87        _program_counter: &mut PC,
88    ) -> ExecutionResult<Self::Reg> {
89        match self {
90            Self::CLbu { rd, rs1: _, uimm } => {
91                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
92                let value = memory.read::<u8>(addr)?;
93                ExecutionResult::Continue {
94                    rd,
95                    value: u32::from(value),
96                }
97            }
98            Self::CLh { rd, rs1: _, uimm } => {
99                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
100                let value = i32::from(memory.read::<i16>(addr)?);
101                ExecutionResult::Continue {
102                    rd,
103                    value: value.cast_unsigned(),
104                }
105            }
106            Self::CLhu { rd, rs1: _, uimm } => {
107                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
108                let value = memory.read::<u16>(addr)?;
109                ExecutionResult::Continue {
110                    rd,
111                    value: u32::from(value),
112                }
113            }
114            Self::CSb {
115                rs1: _,
116                rs2: _,
117                uimm,
118            } => {
119                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
120                memory.write(addr, rs2_value as u8)?;
121                ExecutionResult::ContinueNoWrite
122            }
123            Self::CSh {
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 u16)?;
130                ExecutionResult::ContinueNoWrite
131            }
132            Self::CZextB { rd } => {
133                let value = regs.read(rd) & 0xff;
134                ExecutionResult::Continue { rd, value }
135            }
136            Self::CSextB { rd } => {
137                let value = i32::from(regs.read(rd) as i8);
138                ExecutionResult::Continue {
139                    rd,
140                    value: value.cast_unsigned(),
141                }
142            }
143            Self::CZextH { rd } => {
144                let value = regs.read(rd) & 0xffff;
145                ExecutionResult::Continue { rd, value }
146            }
147            Self::CSextH { rd } => {
148                let value = i32::from(regs.read(rd) as i16);
149                ExecutionResult::Continue {
150                    rd,
151                    value: value.cast_unsigned(),
152                }
153            }
154            Self::CNot { rd } => {
155                let value = !regs.read(rd);
156                ExecutionResult::Continue { rd, value }
157            }
158            Self::CMul { rd, rs2: _ } => {
159                let value = regs.read(rd).wrapping_mul(rs2_value);
160                ExecutionResult::Continue { rd, value }
161            }
162        }
163    }
164}