Skip to main content

ab_riscv_interpreter/rv64/zce/
zcb.rs

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