1use ab_riscv_interpreter::prelude::*;
2use ab_riscv_macros::{instruction, instruction_execution};
3use ab_riscv_primitives::prelude::*;
4use core::fmt;
5use core::ops::ControlFlow;
6
7#[derive(Debug, Default, Clone, Copy)]
13pub struct ContractRegisters<const ZEROSTORE: bool> {
14 regs: [u64; 32],
15}
16
17const impl<const ZEROSTORE: bool> RegisterFile<ContractRegister> for ContractRegisters<ZEROSTORE> {
18 #[inline(always)]
19 fn read(&self, reg: ContractRegister) -> u64 {
20 if reg == ContractRegister::Zero && !ZEROSTORE {
21 return 0;
23 }
24
25 *unsafe { self.regs.get_unchecked(usize::from(reg as u8)) }
27 }
28
29 #[inline(always)]
30 fn write(&mut self, reg: ContractRegister, value: u64) {
31 *unsafe { self.regs.get_unchecked_mut(usize::from(reg as u8)) } = value;
33
34 if ZEROSTORE {
35 *unsafe { self.regs.get_unchecked_mut(0) } = 0;
37 }
38 }
39}
40
41#[derive(Clone, Copy)]
45#[derive_const(Default, Eq, PartialEq)]
46#[repr(u8)]
47pub enum ContractRegister {
48 #[default]
50 Zero = 0,
51 Ra = 1,
53 Sp = 2,
55 T0 = 5,
61 T1 = 6,
63 T2 = 7,
65 S0 = 8,
67 S1 = 9,
69 A0 = 10,
71 A1 = 11,
73 A2 = 12,
75 A3 = 13,
77 A4 = 14,
79 A5 = 15,
81 A6 = 16,
83 A7 = 17,
85 S2 = 18,
87 S3 = 19,
89 S4 = 20,
91 S5 = 21,
93 S6 = 22,
95 S7 = 23,
97 S8 = 24,
99 S9 = 25,
101 S10 = 26,
103 S11 = 27,
105 T3 = 28,
107 T4 = 29,
109 T5 = 30,
111 T6 = 31,
113}
114
115impl fmt::Display for ContractRegister {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 match self {
118 Self::Zero => write!(f, "zero"),
119 Self::Ra => write!(f, "ra"),
120 Self::Sp => write!(f, "sp"),
121 Self::T0 => write!(f, "t0"),
122 Self::T1 => write!(f, "t1"),
123 Self::T2 => write!(f, "t2"),
124 Self::S0 => write!(f, "s0"),
125 Self::S1 => write!(f, "s1"),
126 Self::A0 => write!(f, "a0"),
127 Self::A1 => write!(f, "a1"),
128 Self::A2 => write!(f, "a2"),
129 Self::A3 => write!(f, "a3"),
130 Self::A4 => write!(f, "a4"),
131 Self::A5 => write!(f, "a5"),
132 Self::A6 => write!(f, "a6"),
133 Self::A7 => write!(f, "a7"),
134 Self::S2 => write!(f, "s2"),
135 Self::S3 => write!(f, "s3"),
136 Self::S4 => write!(f, "s4"),
137 Self::S5 => write!(f, "s5"),
138 Self::S6 => write!(f, "s6"),
139 Self::S7 => write!(f, "s7"),
140 Self::S8 => write!(f, "s8"),
141 Self::S9 => write!(f, "s9"),
142 Self::S10 => write!(f, "s10"),
143 Self::S11 => write!(f, "s11"),
144 Self::T3 => write!(f, "t3"),
145 Self::T4 => write!(f, "t4"),
146 Self::T5 => write!(f, "t5"),
147 Self::T6 => write!(f, "t6"),
148 }
149 }
150}
151
152impl fmt::Debug for ContractRegister {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 fmt::Display::fmt(self, f)
155 }
156}
157
158const impl Register for ContractRegister {
159 const ZERO: Self = Self::Zero;
160 const SP: Self = Self::Sp;
161 const RA: Self = Self::Ra;
162 const A0: Self = Self::A0;
163 const A1: Self = Self::A1;
164 type Type = u64;
165
166 #[inline(always)]
167 fn from_bits(bits: u8) -> Option<Self> {
168 match bits {
169 0 => Some(Self::Zero),
170 1 => Some(Self::Ra),
171 2 => Some(Self::Sp),
172 5 => Some(Self::T0),
173 6 => Some(Self::T1),
174 7 => Some(Self::T2),
175 8 => Some(Self::S0),
176 9 => Some(Self::S1),
177 10 => Some(Self::A0),
178 11 => Some(Self::A1),
179 12 => Some(Self::A2),
180 13 => Some(Self::A3),
181 14 => Some(Self::A4),
182 15 => Some(Self::A5),
183 16 => Some(Self::A6),
184 17 => Some(Self::A7),
185 18 => Some(Self::S2),
186 19 => Some(Self::S3),
187 20 => Some(Self::S4),
188 21 => Some(Self::S5),
189 22 => Some(Self::S6),
190 23 => Some(Self::S7),
191 24 => Some(Self::S8),
192 25 => Some(Self::S9),
193 26 => Some(Self::S10),
194 27 => Some(Self::S11),
195 28 => Some(Self::T3),
196 29 => Some(Self::T4),
197 30 => Some(Self::T5),
198 31 => Some(Self::T6),
199 _ => None,
200 }
201 }
202}
203
204const unsafe impl ZcmpRegister for ContractRegister {
206 const RVE: bool = false;
207}
208
209#[instruction(
211 ignore = [Ecall],
212 inherit = [
213 Rv64ZcaInstruction,
214 Rv64ZcbInstruction,
215 Rv64ZcmpInstruction,
216 Rv64Instruction,
217 Rv64MInstruction,
218 Rv64BInstruction,
219 Rv64ZbcInstruction,
220 Rv64ZknInstruction,
221 ZicondInstruction,
222 ],
223)]
224#[derive(Debug, Clone, Copy, PartialEq, Eq)]
225pub enum ContractInstruction<Reg = ContractRegister> {}
226
227#[instruction]
228const impl<Reg> Instruction for ContractInstruction<Reg> {
229 const ALIGNMENT: u8 = align_of::<u32>() as u8;
230
231 type Reg = Reg;
232
233 #[inline(always)]
234 fn try_decode(instruction: u32) -> Option<Self> {
235 None
236 }
237
238 #[inline(always)]
239 fn size(&self) -> u8 {
240 size_of::<u32>() as u8
241 }
242}
243
244#[instruction]
245impl<Reg> fmt::Display for ContractInstruction<Reg>
246where
247 Reg: Register,
248{
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 match self {}
251 }
252}
253
254#[instruction_execution]
255const impl<Reg> ExecutableInstructionOperands for ContractInstruction<Reg> {}
256
257#[instruction_execution]
258const impl<Reg, Env> ExecutableInstructionCsr<Env> for ContractInstruction<Reg> {}
259
260#[instruction_execution]
261impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
262 for ContractInstruction<Reg>
263where
264 Reg: Register,
265{
266 #[inline(always)]
267 fn execute(
268 self,
269 Rs1Rs2OperandValues {
270 rs1_value,
271 rs2_value,
272 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
273 regs: &mut Regs,
274 _env: &mut Env,
275 memory: &mut Memory,
276 program_counter: &mut PC,
277 ) -> ExecutionResult<Self::Reg> {
278 ExecutionResult::ContinueNoWrite
279 }
280}
281
282impl<Reg> ContractInstruction<Reg> {
283 #[inline]
285 #[expect(
286 clippy::rest_pattern_accessible_field,
287 reason = "Do not care about fields"
288 )]
289 pub fn is_jump(&self) -> bool {
290 matches!(
291 self,
292 Self::CJ { .. }
293 | Self::CBeqz { .. }
294 | Self::CBnez { .. }
295 | Self::CJr { .. }
296 | Self::CJalr { .. }
297 | Self::CmPopretz { .. }
298 | Self::CmPopret { .. }
299 | Self::Jalr { .. }
300 | Self::Beq { .. }
301 | Self::Bne { .. }
302 | Self::Blt { .. }
303 | Self::Bge { .. }
304 | Self::Bltu { .. }
305 | Self::Bgeu { .. }
306 | Self::Jal { .. }
307 )
308 }
309}