1#[macro_use]
4pub mod macros;
5pub mod arithmetic;
6pub mod bitwise;
7pub mod block_info;
8pub mod contract;
9pub mod control;
10pub mod data;
11pub mod host;
12pub mod i256;
13pub mod memory;
14pub mod stack;
15pub mod system;
16pub mod tx_info;
17pub mod utility;
18
19use crate::{interpreter_types::InterpreterTypes, Host, Interpreter};
20
21pub type Instruction<W, H> = for<'a> fn(&'a mut Interpreter<W>, &'a mut H);
23
24pub type InstructionTable<W, H> = [Instruction<W, H>; 256];
26
27pub const fn instruction_table<WIRE: InterpreterTypes, H: Host + ?Sized>(
29) -> [Instruction<WIRE, H>; 256] {
30 use bytecode::opcode::*;
31 let mut table = [control::unknown as Instruction<WIRE, H>; 256];
32
33 table[STOP as usize] = control::stop;
34 table[ADD as usize] = arithmetic::add;
35 table[MUL as usize] = arithmetic::mul;
36 table[SUB as usize] = arithmetic::sub;
37 table[DIV as usize] = arithmetic::div;
38 table[SDIV as usize] = arithmetic::sdiv;
39 table[MOD as usize] = arithmetic::rem;
40 table[SMOD as usize] = arithmetic::smod;
41 table[ADDMOD as usize] = arithmetic::addmod;
42 table[MULMOD as usize] = arithmetic::mulmod;
43 table[EXP as usize] = arithmetic::exp;
44 table[SIGNEXTEND as usize] = arithmetic::signextend;
45
46 table[LT as usize] = bitwise::lt;
47 table[GT as usize] = bitwise::gt;
48 table[SLT as usize] = bitwise::slt;
49 table[SGT as usize] = bitwise::sgt;
50 table[EQ as usize] = bitwise::eq;
51 table[ISZERO as usize] = bitwise::iszero;
52 table[AND as usize] = bitwise::bitand;
53 table[OR as usize] = bitwise::bitor;
54 table[XOR as usize] = bitwise::bitxor;
55 table[NOT as usize] = bitwise::not;
56 table[BYTE as usize] = bitwise::byte;
57 table[SHL as usize] = bitwise::shl;
58 table[SHR as usize] = bitwise::shr;
59 table[SAR as usize] = bitwise::sar;
60
61 table[KECCAK256 as usize] = system::keccak256;
62
63 table[ADDRESS as usize] = system::address;
64 table[BALANCE as usize] = host::balance;
65 table[ORIGIN as usize] = tx_info::origin;
66 table[CALLER as usize] = system::caller;
67 table[CALLVALUE as usize] = system::callvalue;
68 table[CALLDATALOAD as usize] = system::calldataload;
69 table[CALLDATASIZE as usize] = system::calldatasize;
70 table[CALLDATACOPY as usize] = system::calldatacopy;
71 table[CODESIZE as usize] = system::codesize;
72 table[CODECOPY as usize] = system::codecopy;
73
74 table[GASPRICE as usize] = tx_info::gasprice;
75 table[EXTCODESIZE as usize] = host::extcodesize;
76 table[EXTCODECOPY as usize] = host::extcodecopy;
77 table[RETURNDATASIZE as usize] = system::returndatasize;
78 table[RETURNDATACOPY as usize] = system::returndatacopy;
79 table[EXTCODEHASH as usize] = host::extcodehash;
80 table[BLOCKHASH as usize] = host::blockhash;
81 table[COINBASE as usize] = block_info::coinbase;
82 table[TIMESTAMP as usize] = block_info::timestamp;
83 table[NUMBER as usize] = block_info::block_number;
84 table[DIFFICULTY as usize] = block_info::difficulty;
85 table[GASLIMIT as usize] = block_info::gaslimit;
86 table[CHAINID as usize] = block_info::chainid;
87 table[SELFBALANCE as usize] = host::selfbalance;
88 table[BASEFEE as usize] = block_info::basefee;
89 table[BLOBHASH as usize] = tx_info::blob_hash;
90 table[BLOBBASEFEE as usize] = block_info::blob_basefee;
91
92 table[POP as usize] = stack::pop;
93 table[MLOAD as usize] = memory::mload;
94 table[MSTORE as usize] = memory::mstore;
95 table[MSTORE8 as usize] = memory::mstore8;
96 table[SLOAD as usize] = host::sload;
97 table[SSTORE as usize] = host::sstore;
98 table[JUMP as usize] = control::jump;
99 table[JUMPI as usize] = control::jumpi;
100 table[PC as usize] = control::pc;
101 table[MSIZE as usize] = memory::msize;
102 table[GAS as usize] = system::gas;
103 table[JUMPDEST as usize] = control::jumpdest_or_nop;
104 table[TLOAD as usize] = host::tload;
105 table[TSTORE as usize] = host::tstore;
106 table[MCOPY as usize] = memory::mcopy;
107
108 table[PUSH0 as usize] = stack::push0;
109 table[PUSH1 as usize] = stack::push::<1, _, _>;
110 table[PUSH2 as usize] = stack::push::<2, _, _>;
111 table[PUSH3 as usize] = stack::push::<3, _, _>;
112 table[PUSH4 as usize] = stack::push::<4, _, _>;
113 table[PUSH5 as usize] = stack::push::<5, _, _>;
114 table[PUSH6 as usize] = stack::push::<6, _, _>;
115 table[PUSH7 as usize] = stack::push::<7, _, _>;
116 table[PUSH8 as usize] = stack::push::<8, _, _>;
117 table[PUSH9 as usize] = stack::push::<9, _, _>;
118 table[PUSH10 as usize] = stack::push::<10, _, _>;
119 table[PUSH11 as usize] = stack::push::<11, _, _>;
120 table[PUSH12 as usize] = stack::push::<12, _, _>;
121 table[PUSH13 as usize] = stack::push::<13, _, _>;
122 table[PUSH14 as usize] = stack::push::<14, _, _>;
123 table[PUSH15 as usize] = stack::push::<15, _, _>;
124 table[PUSH16 as usize] = stack::push::<16, _, _>;
125 table[PUSH17 as usize] = stack::push::<17, _, _>;
126 table[PUSH18 as usize] = stack::push::<18, _, _>;
127 table[PUSH19 as usize] = stack::push::<19, _, _>;
128 table[PUSH20 as usize] = stack::push::<20, _, _>;
129 table[PUSH21 as usize] = stack::push::<21, _, _>;
130 table[PUSH22 as usize] = stack::push::<22, _, _>;
131 table[PUSH23 as usize] = stack::push::<23, _, _>;
132 table[PUSH24 as usize] = stack::push::<24, _, _>;
133 table[PUSH25 as usize] = stack::push::<25, _, _>;
134 table[PUSH26 as usize] = stack::push::<26, _, _>;
135 table[PUSH27 as usize] = stack::push::<27, _, _>;
136 table[PUSH28 as usize] = stack::push::<28, _, _>;
137 table[PUSH29 as usize] = stack::push::<29, _, _>;
138 table[PUSH30 as usize] = stack::push::<30, _, _>;
139 table[PUSH31 as usize] = stack::push::<31, _, _>;
140 table[PUSH32 as usize] = stack::push::<32, _, _>;
141
142 table[DUP1 as usize] = stack::dup::<1, _, _>;
143 table[DUP2 as usize] = stack::dup::<2, _, _>;
144 table[DUP3 as usize] = stack::dup::<3, _, _>;
145 table[DUP4 as usize] = stack::dup::<4, _, _>;
146 table[DUP5 as usize] = stack::dup::<5, _, _>;
147 table[DUP6 as usize] = stack::dup::<6, _, _>;
148 table[DUP7 as usize] = stack::dup::<7, _, _>;
149 table[DUP8 as usize] = stack::dup::<8, _, _>;
150 table[DUP9 as usize] = stack::dup::<9, _, _>;
151 table[DUP10 as usize] = stack::dup::<10, _, _>;
152 table[DUP11 as usize] = stack::dup::<11, _, _>;
153 table[DUP12 as usize] = stack::dup::<12, _, _>;
154 table[DUP13 as usize] = stack::dup::<13, _, _>;
155 table[DUP14 as usize] = stack::dup::<14, _, _>;
156 table[DUP15 as usize] = stack::dup::<15, _, _>;
157 table[DUP16 as usize] = stack::dup::<16, _, _>;
158
159 table[SWAP1 as usize] = stack::swap::<1, _, _>;
160 table[SWAP2 as usize] = stack::swap::<2, _, _>;
161 table[SWAP3 as usize] = stack::swap::<3, _, _>;
162 table[SWAP4 as usize] = stack::swap::<4, _, _>;
163 table[SWAP5 as usize] = stack::swap::<5, _, _>;
164 table[SWAP6 as usize] = stack::swap::<6, _, _>;
165 table[SWAP7 as usize] = stack::swap::<7, _, _>;
166 table[SWAP8 as usize] = stack::swap::<8, _, _>;
167 table[SWAP9 as usize] = stack::swap::<9, _, _>;
168 table[SWAP10 as usize] = stack::swap::<10, _, _>;
169 table[SWAP11 as usize] = stack::swap::<11, _, _>;
170 table[SWAP12 as usize] = stack::swap::<12, _, _>;
171 table[SWAP13 as usize] = stack::swap::<13, _, _>;
172 table[SWAP14 as usize] = stack::swap::<14, _, _>;
173 table[SWAP15 as usize] = stack::swap::<15, _, _>;
174 table[SWAP16 as usize] = stack::swap::<16, _, _>;
175
176 table[LOG0 as usize] = host::log::<0, _>;
177 table[LOG1 as usize] = host::log::<1, _>;
178 table[LOG2 as usize] = host::log::<2, _>;
179 table[LOG3 as usize] = host::log::<3, _>;
180 table[LOG4 as usize] = host::log::<4, _>;
181
182 table[DATALOAD as usize] = data::data_load;
183 table[DATALOADN as usize] = data::data_loadn;
184 table[DATASIZE as usize] = data::data_size;
185 table[DATACOPY as usize] = data::data_copy;
186
187 table[RJUMP as usize] = control::rjump;
188 table[RJUMPI as usize] = control::rjumpi;
189 table[RJUMPV as usize] = control::rjumpv;
190 table[CALLF as usize] = control::callf;
191 table[RETF as usize] = control::retf;
192 table[JUMPF as usize] = control::jumpf;
193 table[DUPN as usize] = stack::dupn;
194 table[SWAPN as usize] = stack::swapn;
195 table[EXCHANGE as usize] = stack::exchange;
196
197 table[EOFCREATE as usize] = contract::eofcreate;
198
199 table[RETURNCONTRACT as usize] = contract::return_contract;
200
201 table[CREATE as usize] = contract::create::<_, false, _>;
202 table[CALL as usize] = contract::call;
203 table[CALLCODE as usize] = contract::call_code;
204 table[RETURN as usize] = control::ret;
205 table[DELEGATECALL as usize] = contract::delegate_call;
206 table[CREATE2 as usize] = contract::create::<_, true, _>;
207
208 table[RETURNDATALOAD as usize] = system::returndataload;
209 table[EXTCALL as usize] = contract::extcall;
210 table[EXTDELEGATECALL as usize] = contract::extdelegatecall;
211 table[STATICCALL as usize] = contract::static_call;
212 table[EXTSTATICCALL as usize] = contract::extstaticcall;
213 table[REVERT as usize] = control::revert;
214 table[INVALID as usize] = control::invalid;
215 table[SELFDESTRUCT as usize] = host::selfdestruct;
216 table
217}
218
219#[cfg(test)]
220mod tests {
221 use super::instruction_table;
222 use crate::{host::DummyHost, interpreter::EthInterpreter};
223 use bytecode::opcode::*;
224
225 #[test]
226 fn all_instructions_and_opcodes_used() {
227 let unknown_instruction = 0x0C_usize;
229 let instr_table = instruction_table::<EthInterpreter, DummyHost>();
230
231 let unknown_istr = instr_table[unknown_instruction];
232 for (i, instr) in instr_table.iter().enumerate() {
233 let is_opcode_unknown = OpCode::new(i as u8).is_none();
234 let is_instr_unknown = std::ptr::fn_addr_eq(*instr, unknown_istr);
236 assert_eq!(
237 is_instr_unknown, is_opcode_unknown,
238 "Opcode 0x{:X?} is not handled",
239 i
240 );
241 }
242 }
243}