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