Skip to main content

ab_riscv_interpreter/rv64/a/
zalrsc.rs

1//! RV64 Zalrsc extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::rv32::a::ReservationSet;
7use crate::{
8    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
10    PackedAddress, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
11    ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15
16#[instruction_execution]
17const impl<Reg> ExecutableInstructionOperands for Rv64ZalrscInstruction<Reg> where
18    Reg: Register<Type = u64>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64ZalrscInstruction<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 Rv64ZalrscInstruction<Reg>
31where
32    Reg: [const] Register<Type = u64>,
33    Regs: [const] RegisterFile<Reg>,
34    Memory: [const] VirtualMemory,
35    Env: [const] ReservationSet<Reg>,
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        match self {
51            Self::Lr {
52                rd,
53                rs1: _,
54                aq: _,
55                rl: _,
56            } => {
57                if !rs1_value.is_multiple_of(4) {
58                    ::core::hint::cold_path();
59                    return ExecutionResult::Err(ExecutionError::MisalignedRead {
60                        address: PackedAddress::new(rs1_value),
61                    });
62                }
63                let value = memory.read::<i32>(rs1_value)?;
64                env.set_reservation(rs1_value);
65                ExecutionResult::Continue {
66                    rd,
67                    value: i64::from(value).cast_unsigned(),
68                }
69            }
70            Self::Sc {
71                rd,
72                rs1: _,
73                rs2: _,
74                aq: _,
75                rl: _,
76            } => {
77                if !rs1_value.is_multiple_of(4) {
78                    ::core::hint::cold_path();
79                    return ExecutionResult::Err(ExecutionError::MisalignedWrite {
80                        address: PackedAddress::new(rs1_value),
81                    });
82                }
83                let success = env.reservation() == Some(rs1_value);
84                env.clear_reservation();
85
86                if success {
87                    memory.write(rs1_value, rs2_value as u32)?;
88                    ExecutionResult::Continue { rd, value: 0 }
89                } else {
90                    ExecutionResult::Continue { rd, value: 1 }
91                }
92            }
93            Self::LrD {
94                rd,
95                rs1: _,
96                aq: _,
97                rl: _,
98            } => {
99                if !rs1_value.is_multiple_of(8) {
100                    ::core::hint::cold_path();
101                    return ExecutionResult::Err(ExecutionError::MisalignedRead {
102                        address: PackedAddress::new(rs1_value),
103                    });
104                }
105                let value = memory.read::<u64>(rs1_value)?;
106                env.set_reservation(rs1_value);
107                ExecutionResult::Continue { rd, value }
108            }
109            Self::ScD {
110                rd,
111                rs1: _,
112                rs2: _,
113                aq: _,
114                rl: _,
115            } => {
116                if !rs1_value.is_multiple_of(8) {
117                    ::core::hint::cold_path();
118                    return ExecutionResult::Err(ExecutionError::MisalignedWrite {
119                        address: PackedAddress::new(rs1_value),
120                    });
121                }
122                let success = env.reservation() == Some(rs1_value);
123                env.clear_reservation();
124
125                if success {
126                    memory.write(rs1_value, rs2_value)?;
127                    ExecutionResult::Continue { rd, value: 0 }
128                } else {
129                    ExecutionResult::Continue { rd, value: 1 }
130                }
131            }
132        }
133    }
134}