1use crate::{
2 decode::{
3 decode_binary_immediate, decode_binary_register, decode_call_immediate,
4 decode_call_register, decode_endian, decode_exit, decode_jump, decode_jump_immediate,
5 decode_jump_register, decode_jump32_immediate, decode_jump32_register,
6 decode_load_immediate, decode_load_memory, decode_store_immediate, decode_store_register,
7 decode_unary,
8 },
9 errors::{ExecutionError, SBPFError},
10 execute::{
11 Vm, execute_binary_immediate, execute_binary_register, execute_call_immediate,
12 execute_call_register, execute_endian, execute_exit, execute_jump, execute_jump_immediate,
13 execute_jump_register, execute_load_immediate, execute_load_memory,
14 execute_store_immediate, execute_store_register, execute_unary,
15 },
16 instruction::Instruction,
17 opcode::{
18 BIN_IMM_OPS, BIN_REG_OPS, CALL_IMM_OPS, CALL_REG_OPS, ENDIAN_OPS, EXIT_OPS, JUMP_IMM_OPS,
19 JUMP_OPS, JUMP_REG_OPS, JUMP32_IMM_OPS, JUMP32_REG_OPS, LOAD_IMM_OPS, LOAD_MEMORY_OPS,
20 Opcode, OperationType, STORE_IMM_OPS, STORE_REG_OPS, UNARY_OPS,
21 },
22 validate::{
23 validate_binary_immediate, validate_binary_register, validate_call_immediate,
24 validate_call_register, validate_endian, validate_exit, validate_jump,
25 validate_jump_immediate, validate_jump_register, validate_load_immediate,
26 validate_load_memory, validate_store_immediate, validate_store_register, validate_unary,
27 },
28};
29
30type DecodeFn = fn(&[u8]) -> Result<Instruction, SBPFError>;
31type ValidateFn = fn(&Instruction) -> Result<(), SBPFError>;
32pub type ExecuteFn = fn(&mut dyn Vm, &Instruction) -> Result<(), ExecutionError>;
33
34pub struct InstructionHandler {
35 pub decode: DecodeFn,
36 pub validate: ValidateFn,
37 pub execute: ExecuteFn,
38}
39
40use {once_cell::sync::Lazy, std::collections::HashMap};
41
42pub static OPCODE_TO_HANDLER: Lazy<HashMap<Opcode, InstructionHandler>> = Lazy::new(|| {
43 let mut map = HashMap::new();
45
46 fn register_group(
47 map: &mut HashMap<Opcode, InstructionHandler>,
48 ops: &[Opcode],
49 decode: DecodeFn,
50 validate: ValidateFn,
51 execute: ExecuteFn,
52 ) {
53 for &op in ops {
54 map.insert(
55 op,
56 InstructionHandler {
57 decode,
58 validate,
59 execute,
60 },
61 );
62 }
63 }
64
65 register_group(
66 &mut map,
67 LOAD_IMM_OPS,
68 decode_load_immediate,
69 validate_load_immediate,
70 execute_load_immediate,
71 );
72 register_group(
73 &mut map,
74 LOAD_MEMORY_OPS,
75 decode_load_memory,
76 validate_load_memory,
77 execute_load_memory,
78 );
79 register_group(
80 &mut map,
81 STORE_IMM_OPS,
82 decode_store_immediate,
83 validate_store_immediate,
84 execute_store_immediate,
85 );
86 register_group(
87 &mut map,
88 STORE_REG_OPS,
89 decode_store_register,
90 validate_store_register,
91 execute_store_register,
92 );
93 register_group(
94 &mut map,
95 BIN_IMM_OPS,
96 decode_binary_immediate,
97 validate_binary_immediate,
98 execute_binary_immediate,
99 );
100 register_group(
101 &mut map,
102 BIN_REG_OPS,
103 decode_binary_register,
104 validate_binary_register,
105 execute_binary_register,
106 );
107 register_group(
108 &mut map,
109 UNARY_OPS,
110 decode_unary,
111 validate_unary,
112 execute_unary,
113 );
114 register_group(
115 &mut map,
116 ENDIAN_OPS,
117 decode_endian,
118 validate_endian,
119 execute_endian,
120 );
121 register_group(&mut map, JUMP_OPS, decode_jump, validate_jump, execute_jump);
122 register_group(
123 &mut map,
124 JUMP_IMM_OPS,
125 decode_jump_immediate,
126 validate_jump_immediate,
127 execute_jump_immediate,
128 );
129 register_group(
130 &mut map,
131 JUMP_REG_OPS,
132 decode_jump_register,
133 validate_jump_register,
134 execute_jump_register,
135 );
136 register_group(
137 &mut map,
138 JUMP32_IMM_OPS,
139 decode_jump32_immediate,
140 validate_jump_immediate,
142 execute_jump_immediate,
143 );
144 register_group(
145 &mut map,
146 JUMP32_REG_OPS,
147 decode_jump32_register,
148 validate_jump_register,
150 execute_jump_register,
151 );
152 register_group(
153 &mut map,
154 CALL_IMM_OPS,
155 decode_call_immediate,
156 validate_call_immediate,
157 execute_call_immediate,
158 );
159 register_group(
160 &mut map,
161 CALL_REG_OPS,
162 decode_call_register,
163 validate_call_register,
164 execute_call_register,
165 );
166 register_group(&mut map, EXIT_OPS, decode_exit, validate_exit, execute_exit);
167
168 map
169});
170
171pub static OPCODE_TO_TYPE: Lazy<HashMap<Opcode, OperationType>> = Lazy::new(|| {
172 let mut map = HashMap::new();
173
174 fn register_group(
175 map: &mut HashMap<Opcode, OperationType>,
176 ops: &[Opcode],
177 op_type: OperationType,
178 ) {
179 for &op in ops {
180 map.insert(op, op_type);
181 }
182 }
183
184 register_group(&mut map, LOAD_IMM_OPS, OperationType::LoadImmediate);
185 register_group(&mut map, LOAD_MEMORY_OPS, OperationType::LoadMemory);
186 register_group(&mut map, STORE_IMM_OPS, OperationType::StoreImmediate);
187 register_group(&mut map, STORE_REG_OPS, OperationType::StoreRegister);
188 register_group(&mut map, BIN_IMM_OPS, OperationType::BinaryImmediate);
189 register_group(&mut map, BIN_REG_OPS, OperationType::BinaryRegister);
190 register_group(&mut map, UNARY_OPS, OperationType::Unary);
191 register_group(&mut map, ENDIAN_OPS, OperationType::Endian);
192 register_group(&mut map, JUMP_OPS, OperationType::Jump);
193 register_group(&mut map, JUMP_IMM_OPS, OperationType::JumpImmediate);
194 register_group(&mut map, JUMP_REG_OPS, OperationType::JumpRegister);
195 register_group(&mut map, JUMP32_IMM_OPS, OperationType::Jump32Immediate);
196 register_group(&mut map, JUMP32_REG_OPS, OperationType::Jump32Register);
197 register_group(&mut map, CALL_IMM_OPS, OperationType::CallImmediate);
198 register_group(&mut map, CALL_REG_OPS, OperationType::CallRegister);
199 register_group(&mut map, EXIT_OPS, OperationType::Exit);
200
201 map
202});