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