1use ab_riscv_interpreter::prelude::*;
2use ab_riscv_macros::{instruction, instruction_execution};
3use ab_riscv_primitives::prelude::*;
4use core::fmt;
5
6#[derive(Debug, Default, Clone, Copy)]
12pub struct ContractRegisters<const ZEROSTORE: bool> {
13 regs: [u64; 32],
14}
15
16const impl<const ZEROSTORE: bool> RegisterFile<ContractRegister> for ContractRegisters<ZEROSTORE> {
17 #[inline(always)]
18 fn read(&self, reg: ContractRegister) -> u64 {
19 if reg == ContractRegister::Zero && !ZEROSTORE {
20 return 0;
22 }
23
24 *unsafe { self.regs.get_unchecked(usize::from(reg as u8)) }
26 }
27
28 #[inline(always)]
29 fn write(&mut self, reg: ContractRegister, value: u64) {
30 *unsafe { self.regs.get_unchecked_mut(usize::from(reg as u8)) } = value;
32
33 if ZEROSTORE {
34 *unsafe { self.regs.get_unchecked_mut(0) } = 0;
36 }
37 }
38}
39
40#[derive(Clone, Copy)]
44#[derive_const(Default, Eq, PartialEq)]
45#[repr(u8)]
46pub enum ContractRegister {
47 #[default]
49 Zero = 0,
50 Ra = 1,
52 Sp = 2,
54 T0 = 5,
60 T1 = 6,
62 T2 = 7,
64 S0 = 8,
66 S1 = 9,
68 A0 = 10,
70 A1 = 11,
72 A2 = 12,
74 A3 = 13,
76 A4 = 14,
78 A5 = 15,
80 A6 = 16,
82 A7 = 17,
84 S2 = 18,
86 S3 = 19,
88 S4 = 20,
90 S5 = 21,
92 S6 = 22,
94 S7 = 23,
96 S8 = 24,
98 S9 = 25,
100 S10 = 26,
102 S11 = 27,
104 T3 = 28,
106 T4 = 29,
108 T5 = 30,
110 T6 = 31,
112}
113
114impl fmt::Display for ContractRegister {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 match self {
117 Self::Zero => write!(f, "zero"),
118 Self::Ra => write!(f, "ra"),
119 Self::Sp => write!(f, "sp"),
120 Self::T0 => write!(f, "t0"),
121 Self::T1 => write!(f, "t1"),
122 Self::T2 => write!(f, "t2"),
123 Self::S0 => write!(f, "s0"),
124 Self::S1 => write!(f, "s1"),
125 Self::A0 => write!(f, "a0"),
126 Self::A1 => write!(f, "a1"),
127 Self::A2 => write!(f, "a2"),
128 Self::A3 => write!(f, "a3"),
129 Self::A4 => write!(f, "a4"),
130 Self::A5 => write!(f, "a5"),
131 Self::A6 => write!(f, "a6"),
132 Self::A7 => write!(f, "a7"),
133 Self::S2 => write!(f, "s2"),
134 Self::S3 => write!(f, "s3"),
135 Self::S4 => write!(f, "s4"),
136 Self::S5 => write!(f, "s5"),
137 Self::S6 => write!(f, "s6"),
138 Self::S7 => write!(f, "s7"),
139 Self::S8 => write!(f, "s8"),
140 Self::S9 => write!(f, "s9"),
141 Self::S10 => write!(f, "s10"),
142 Self::S11 => write!(f, "s11"),
143 Self::T3 => write!(f, "t3"),
144 Self::T4 => write!(f, "t4"),
145 Self::T5 => write!(f, "t5"),
146 Self::T6 => write!(f, "t6"),
147 }
148 }
149}
150
151impl fmt::Debug for ContractRegister {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 fmt::Display::fmt(self, f)
154 }
155}
156
157const impl Register for ContractRegister {
158 const RVE: bool = false;
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
207#[instruction(
209 ignore = [Ecall],
210 inherit = [
211 Rv64ZcaInstruction,
212 Rv64ZcbInstruction,
213 Rv64ZcmpInstruction,
214 Rv64Instruction,
215 Rv64MInstruction,
216 Rv64BInstruction,
217 Rv64ZbcInstruction,
218 Rv64ZknInstruction,
219 ZicondInstruction,
220 ],
221)]
222#[derive(Debug, Clone, Copy, PartialEq, Eq)]
223pub enum ContractInstruction<Hart = BasicHart<ContractRegister>>
224where
225 Hart: HartConfig, {}
226
227#[instruction]
228const impl<Reg, Hart> Instruction for ContractInstruction<Hart>
229where
230 Hart: [const] HartConfig<Reg = Reg>,
231{
232 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[];
233
234 const ALIGNMENT: u8 = align_of::<u32>() as u8;
235
236 type Hart = Hart;
237
238 #[inline(always)]
239 fn try_decode(instruction: u32) -> Option<Self> {
240 None
241 }
242
243 #[inline(always)]
244 fn size(&self) -> u8 {
245 size_of::<u32>() as u8
246 }
247}
248
249#[instruction]
250impl<Reg, Hart> fmt::Display for ContractInstruction<Hart>
251where
252 Reg: Register,
253 Hart: HartConfig<Reg = Reg>,
254{
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 match self {}
257 }
258}
259
260#[instruction_execution]
261const impl<Reg, Hart> ExecutableInstructionOperands for ContractInstruction<Hart> where
262 Hart: HartConfig<Reg = Reg>
263{
264}
265
266#[instruction_execution]
267const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ContractInstruction<Hart> where
268 Hart: HartConfig<Reg = Reg>
269{
270}
271
272#[instruction_execution]
273impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
274 for ContractInstruction<Hart>
275where
276 Reg: Register,
277 Hart: HartConfig<Reg = Reg>,
278{
279 #[inline(always)]
280 fn execute(
281 self,
282 Rs1Rs2OperandValues {
283 rs1_value,
284 rs2_value,
285 }: Rs1Rs2OperandValues<Reg::Type>,
286 regs: &mut Regs,
287 _env: &mut Env,
288 memory: &mut Memory,
289 program_counter: &PC,
290 ) -> ExecutionResult<Reg> {
291 ExecutionResult::ContinueNoWrite
292 }
293}