sbpf_common/
inst_handler.rs

1use crate::{
2    decode::{
3        decode_binary_immediate, decode_binary_register, decode_call_immediate,
4        decode_call_register, decode_exit, decode_jump, decode_jump_immediate,
5        decode_jump_register, decode_load_immediate, decode_load_memory, decode_store_immediate,
6        decode_store_register, decode_unary,
7    },
8    errors::SBPFError,
9    instruction::Instruction,
10    opcode::{
11        BIN_IMM_OPS, BIN_REG_OPS, CALL_IMM_OPS, CALL_REG_OPS, EXIT_OPS, JUMP_IMM_OPS, JUMP_OPS,
12        JUMP_REG_OPS, LOAD_IMM_OPS, LOAD_MEMORY_OPS, Opcode, OperationType, STORE_IMM_OPS,
13        STORE_REG_OPS, UNARY_OPS,
14    },
15    validate::{
16        validate_binary_immediate, validate_binary_register, validate_call_immediate,
17        validate_call_register, validate_exit, validate_jump, validate_jump_immediate,
18        validate_jump_register, validate_load_immediate, validate_load_memory,
19        validate_store_immediate, validate_store_register, validate_unary,
20    },
21};
22
23type DecodeFn = fn(&[u8]) -> Result<Instruction, SBPFError>;
24type ValidateFn = fn(&Instruction) -> Result<(), SBPFError>;
25
26pub struct InstructionHandler {
27    pub decode: DecodeFn,
28    pub validate: ValidateFn,
29}
30
31use {once_cell::sync::Lazy, std::collections::HashMap};
32
33pub static OPCODE_TO_HANDLER: Lazy<HashMap<Opcode, InstructionHandler>> = Lazy::new(|| {
34    //
35    let mut map = HashMap::new();
36
37    fn register_group(
38        map: &mut HashMap<Opcode, InstructionHandler>,
39        ops: &[Opcode],
40        decode: DecodeFn,
41        validate: ValidateFn,
42    ) {
43        for &op in ops {
44            map.insert(op, InstructionHandler { decode, validate });
45        }
46    }
47
48    register_group(
49        &mut map,
50        LOAD_IMM_OPS,
51        decode_load_immediate,
52        validate_load_immediate,
53    );
54    register_group(
55        &mut map,
56        LOAD_MEMORY_OPS,
57        decode_load_memory,
58        validate_load_memory,
59    );
60    register_group(
61        &mut map,
62        STORE_IMM_OPS,
63        decode_store_immediate,
64        validate_store_immediate,
65    );
66    register_group(
67        &mut map,
68        STORE_REG_OPS,
69        decode_store_register,
70        validate_store_register,
71    );
72    register_group(
73        &mut map,
74        BIN_IMM_OPS,
75        decode_binary_immediate,
76        validate_binary_immediate,
77    );
78    register_group(
79        &mut map,
80        BIN_REG_OPS,
81        decode_binary_register,
82        validate_binary_register,
83    );
84    register_group(&mut map, UNARY_OPS, decode_unary, validate_unary);
85    register_group(&mut map, JUMP_OPS, decode_jump, validate_jump);
86    register_group(
87        &mut map,
88        JUMP_IMM_OPS,
89        decode_jump_immediate,
90        validate_jump_immediate,
91    );
92    register_group(
93        &mut map,
94        JUMP_REG_OPS,
95        decode_jump_register,
96        validate_jump_register,
97    );
98    register_group(
99        &mut map,
100        CALL_IMM_OPS,
101        decode_call_immediate,
102        validate_call_immediate,
103    );
104    register_group(
105        &mut map,
106        CALL_REG_OPS,
107        decode_call_register,
108        validate_call_register,
109    );
110    register_group(&mut map, EXIT_OPS, decode_exit, validate_exit);
111
112    map
113});
114
115pub static OPCODE_TO_TYPE: Lazy<HashMap<Opcode, OperationType>> = Lazy::new(|| {
116    let mut map = HashMap::new();
117
118    fn register_group(
119        map: &mut HashMap<Opcode, OperationType>,
120        ops: &[Opcode],
121        op_type: OperationType,
122    ) {
123        for &op in ops {
124            map.insert(op, op_type);
125        }
126    }
127
128    register_group(&mut map, LOAD_IMM_OPS, OperationType::LoadImmediate);
129    register_group(&mut map, LOAD_MEMORY_OPS, OperationType::LoadMemory);
130    register_group(&mut map, STORE_IMM_OPS, OperationType::StoreImmediate);
131    register_group(&mut map, STORE_REG_OPS, OperationType::StoreRegister);
132    register_group(&mut map, BIN_IMM_OPS, OperationType::BinaryImmediate);
133    register_group(&mut map, BIN_REG_OPS, OperationType::BinaryRegister);
134    register_group(&mut map, UNARY_OPS, OperationType::Unary);
135    register_group(&mut map, JUMP_OPS, OperationType::Jump);
136    register_group(&mut map, JUMP_IMM_OPS, OperationType::JumpImmediate);
137    register_group(&mut map, JUMP_REG_OPS, OperationType::JumpRegister);
138    register_group(&mut map, CALL_IMM_OPS, OperationType::CallImmediate);
139    register_group(&mut map, CALL_REG_OPS, OperationType::CallRegister);
140    register_group(&mut map, EXIT_OPS, OperationType::Exit);
141
142    map
143});