Skip to main content

ab_contract_file/
contract_instruction_prototype.rs

1#[cfg(any(miri, not(all(target_arch = "riscv64", target_feature = "zbc"))))]
2use ab_riscv_interpreter::rv64::b::zbc::clmul_internal;
3use ab_riscv_interpreter::rv64::{Rv64InterpreterState, Rv64SystemInstructionHandler};
4use ab_riscv_interpreter::{ExecutableInstruction, ExecutionError, ProgramCounter, VirtualMemory};
5use ab_riscv_macros::{instruction, instruction_execution};
6use ab_riscv_primitives::instruction::Instruction;
7use ab_riscv_primitives::instruction::rv64::Rv64Instruction;
8use ab_riscv_primitives::instruction::rv64::b::zba::Rv64ZbaInstruction;
9use ab_riscv_primitives::instruction::rv64::b::zbb::Rv64ZbbInstruction;
10use ab_riscv_primitives::instruction::rv64::b::zbc::Rv64ZbcInstruction;
11use ab_riscv_primitives::instruction::rv64::b::zbs::Rv64ZbsInstruction;
12use ab_riscv_primitives::instruction::rv64::m::Rv64MInstruction;
13use ab_riscv_primitives::instruction::rv64::zk::zkn::zknh::Rv64ZknhInstruction;
14use ab_riscv_primitives::registers::{EReg, Register};
15use core::fmt;
16use core::ops::ControlFlow;
17
18/// Instructions that are the most popular among contracts
19#[instruction(
20    reorder = [
21        Ld,
22        Sd,
23        Add,
24        Addi,
25        Xor,
26        Rori,
27        Srli,
28        Or,
29        And,
30        Slli,
31        Lbu,
32        Auipc,
33        Jalr,
34        Sb,
35        Roriw,
36        Sub,
37        Sltu,
38        Mulhu,
39        Mul,
40        Sh1add,
41    ],
42    ignore = [
43        Rv64Instruction,
44        Rv64MInstruction,
45        Rv64BInstruction,
46        Rv64ZbcInstruction,
47    ],
48    inherit = [
49        Rv64Instruction,
50        Rv64MInstruction,
51        Rv64BInstruction,
52        Rv64ZbcInstruction,
53    ],
54)]
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum PopularInstruction<Reg> {}
57
58#[instruction]
59impl<Reg> const Instruction for PopularInstruction<Reg>
60where
61    Reg: [const] Register<Type = u64>,
62{
63    type Reg = EReg<u64>;
64
65    #[inline(always)]
66    fn try_decode(instruction: u32) -> Option<Self> {
67        None
68    }
69
70    #[inline(always)]
71    fn alignment() -> u8 {
72        size_of::<u32>() as u8
73    }
74
75    #[inline(always)]
76    fn size(&self) -> u8 {
77        size_of::<u32>() as u8
78    }
79}
80
81#[instruction]
82impl<Reg> fmt::Display for PopularInstruction<Reg>
83where
84    Reg: fmt::Display + Copy,
85{
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {}
88    }
89}
90
91#[instruction_execution]
92impl<Reg, Memory, PC, InstructionHandler, CustomError>
93    ExecutableInstruction<
94        Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
95        CustomError,
96    > for PopularInstruction<Reg>
97where
98    Reg: Register<Type = u64>,
99    [(); Reg::N]:,
100    Memory: VirtualMemory,
101    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
102    InstructionHandler: Rv64SystemInstructionHandler<Reg, Memory, PC, CustomError>,
103{
104    #[inline(always)]
105    fn execute(
106        self,
107        state: &mut Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
108    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, Self, CustomError>> {
109        Ok(ControlFlow::Continue(()))
110    }
111}
112
113/// Instructions that are less popular among contracts
114#[instruction(
115    ignore = [PopularInstruction, Fence, Ecall],
116    inherit = [
117        Rv64Instruction,
118        Rv64MInstruction,
119        Rv64BInstruction,
120        Rv64ZbcInstruction,
121        Rv64ZknhInstruction,
122    ],
123)]
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
125pub enum NotPopularInstruction<Reg> {}
126
127#[instruction]
128impl<Reg> const Instruction for NotPopularInstruction<Reg>
129where
130    Reg: [const] Register<Type = u64>,
131{
132    type Reg = EReg<u64>;
133
134    #[inline(always)]
135    fn try_decode(instruction: u32) -> Option<Self> {
136        None
137    }
138
139    #[inline(always)]
140    fn alignment() -> u8 {
141        size_of::<u32>() as u8
142    }
143
144    #[inline(always)]
145    fn size(&self) -> u8 {
146        size_of::<u32>() as u8
147    }
148}
149
150#[instruction]
151impl<Reg> fmt::Display for NotPopularInstruction<Reg>
152where
153    Reg: fmt::Display + Copy,
154{
155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        match self {}
157    }
158}
159
160#[instruction_execution]
161impl<Reg, Memory, PC, InstructionHandler, CustomError>
162    ExecutableInstruction<
163        Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
164        CustomError,
165    > for NotPopularInstruction<Reg>
166where
167    Reg: Register<Type = u64>,
168    [(); Reg::N]:,
169    Memory: VirtualMemory,
170    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
171    InstructionHandler: Rv64SystemInstructionHandler<Reg, Memory, PC, CustomError>,
172{
173    fn execute(
174        self,
175        state: &mut Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
176    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, Self, CustomError>> {
177        Ok(ControlFlow::Continue(()))
178    }
179}
180
181/// An instruction type used by contracts (prototype for macro usage)
182#[derive(Debug, Clone, Copy, PartialEq, Eq)]
183pub enum ContractInstructionPrototype<Reg> {
184    /// Instructions that are the most popular among contracts
185    Popular(PopularInstruction<Reg>),
186    /// Instructions that are less popular among contracts
187    NotPopular(NotPopularInstruction<Reg>),
188}
189
190impl<Reg> const Instruction for ContractInstructionPrototype<Reg>
191where
192    Reg: [const] Register<Type = u64>,
193{
194    type Reg = EReg<u64>;
195
196    #[inline(always)]
197    fn try_decode(instruction: u32) -> Option<Self> {
198        if let Some(instruction) = PopularInstruction::try_decode(instruction).map(Self::Popular) {
199            Some(instruction)
200        } else {
201            NotPopularInstruction::try_decode(instruction).map(Self::NotPopular)
202        }
203    }
204
205    #[inline(always)]
206    fn alignment() -> u8 {
207        size_of::<u32>() as u8
208    }
209
210    #[inline(always)]
211    fn size(&self) -> u8 {
212        size_of::<u32>() as u8
213    }
214}
215
216impl<Reg> fmt::Display for ContractInstructionPrototype<Reg>
217where
218    Reg: fmt::Display + Copy,
219{
220    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221        match self {
222            Self::Popular(instructions) => fmt::Display::fmt(instructions, f),
223            Self::NotPopular(instructions) => fmt::Display::fmt(instructions, f),
224        }
225    }
226}
227
228impl<Reg, Memory, PC, InstructionHandler, CustomError>
229    ExecutableInstruction<
230        Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
231        CustomError,
232    > for ContractInstructionPrototype<Reg>
233where
234    Reg: Register<Type = u64>,
235    [(); Reg::N]:,
236    Memory: VirtualMemory,
237    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
238    InstructionHandler: Rv64SystemInstructionHandler<Reg, Memory, PC, CustomError>,
239{
240    #[inline(always)]
241    fn execute(
242        self,
243        state: &mut Rv64InterpreterState<Reg, Memory, PC, InstructionHandler, CustomError>,
244    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, Self, CustomError>> {
245        match self {
246            Self::Popular(instructions) => instructions
247                .execute(state)
248                .map_err(|error| error.map_instruction(Self::Popular)),
249            Self::NotPopular(instructions) => instructions
250                .execute(state)
251                .map_err(|error| error.map_instruction(Self::NotPopular)),
252        }
253    }
254}