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