Skip to main content

ab_contract_file/
contract_instruction_prototype.rs

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