1use core::fmt;
5
6pub use super::common::*;
7pub type Instruction = super::Instruction<Ebpf>;
8pub type Program<'a> = super::Program<'a, Ebpf>;
9
10pub struct Ebpf;
11
12impl super::instruction::Dialect for Ebpf {
13 const MAX_INSTRUCTIONS: usize = u16::MAX as _;
14 const SOCKOPT: libc::c_int = libc::SO_ATTACH_REUSEPORT_EBPF as _;
15
16 fn debug(i: &Instruction, f: &mut fmt::Formatter) -> fmt::Result {
17 let code = i.code;
18 let k = i.k;
19 let jt = i.jt;
20 let jf = i.jf;
21 let alt = f.alternate();
22
23 let mut f = f.debug_struct("Instruction");
24 let class = Class::decode(code);
25
26 if alt {
27 f.field("code", &code).field("jt", &jt).field("jf", &jf);
28 }
29
30 f.field("class", &class);
31
32 match class {
33 Class::ALU => {
34 f.field("op", &Alu::decode(code));
35 }
36 Class::JMP | Class::JMP32 => {
37 f.field("op", &Jump::decode(code));
38 }
39 Class::LD | Class::LDX => {
40 f.field("size", &Size::decode(code))
41 .field("mode", &Mode::decode(code));
42 }
43 _ => {}
45 }
46
47 if jt > 0 {
48 f.field("jt", &jt);
49 }
50
51 if jf > 0 {
52 f.field("jf", &jf);
53 }
54
55 f.field("k", &k).finish()
56 }
57
58 fn display(i: &Instruction, f: &mut fmt::Formatter, line: Option<usize>) -> fmt::Result {
59 let code = i.code;
60 let k = i.k;
61 let jt = i.jt;
62 let jf = i.jf;
63
64 if let Some(line) = line {
65 write!(f, "l{line:<4}: ")?;
66 }
67
68 let class = Class::decode(code);
69
70 match class {
71 Class::LD | Class::LDX => {
72 let size = Size::decode(code).suffix();
73 let mode = Mode::decode(code);
74
75 match mode {
76 Mode::IMM => return write!(f, "{class}{size} #{k}"),
77 Mode::ABS => {
78 let prefix = if k == 0 { "" } else { "0x" };
79 return if let Some(info) = super::ancillary::lookup(k) {
80 write!(
81 f,
82 "{class}{size} {} ; [{prefix}{k:x}] // {}",
83 info.extension, info.capi
84 )
85 } else {
86 write!(f, "{class}{size} [{prefix}{k:x}]")
87 };
88 }
89 _ => {}
90 }
91 }
92 Class::ALU => {
93 let op = Alu::decode(code);
94 let source = Source::decode(code);
95
96 return match source {
97 Source::K => write!(f, "{op} #{k}"),
98 Source::X => write!(f, "{op} x"),
99 };
100 }
101 Class::JMP | Class::JMP32 => {
102 let op = Jump::decode(code);
103 let source = Source::decode(code);
104
105 match source {
106 Source::K => write!(f, "{op} #{k}")?,
107 Source::X => write!(f, "{op} x")?,
108 }
109
110 if let Some(line) = line {
111 let line = line + 1;
112 let jt = line + jt as usize;
113 let jf = line + jf as usize;
114 write!(f, ",l{jt},l{jf}")?
115 } else {
116 write!(f, ",{jt},{jf}")?
117 }
118
119 return Ok(());
120 }
121 _ => {}
122 }
123
124 write!(f, "<unknown instruction {i:?}>")
125 }
126}
127
128define!(
130 #[mask(0x07)]
131 pub enum Class {
132 LD = 0x00,
133 LDX = 0x01,
134 ST = 0x02,
135 STX = 0x03,
136 ALU = 0x04,
137 JMP = 0x05,
138 JMP32 = 0x06,
139 ALU64 = 0x07,
140 }
141);
142
143define!(
145 #[mask(0x18)]
146 pub enum Size {
147 W = 0x00,
149 H = 0x08,
151 B = 0x10,
153 DW = 0x18,
155 }
156);
157
158impl Size {
159 #[inline]
160 pub const fn suffix(self) -> &'static str {
161 match self {
162 Self::W => "",
163 Self::H => "H",
164 Self::B => "B",
165 Self::DW => "DW",
166 }
167 }
168}
169
170define!(
172 #[mask(0xe0)]
173 pub enum Mode {
174 IMM = 0x00,
175 ABS = 0x20,
176 IND = 0x40,
177 MEM = 0x60,
178 ATOMIC = 0xc0,
179 }
180);
181
182define!(
184 #[mask(0xf0)]
185 pub enum Alu {
186 ADD = 0x00,
187 SUB = 0x10,
188 MUL = 0x20,
189 DIV = 0x30,
190 OR = 0x40,
191 AND = 0x50,
192 LSH = 0x60,
193 RSH = 0x70,
194 NEG = 0x80,
195 MOD = 0x90,
196 XOR = 0xa0,
197 MOV = 0xb0,
198 ARSH = 0xc0,
199 END = 0xd0,
200 }
201);
202
203define!(
205 #[mask(0xf0)]
206 pub enum Jump {
207 JA = 0x00,
208 JEQ = 0x10,
209 JGT = 0x20,
210 JGE = 0x30,
211 JSET = 0x40,
212 JNE = 0x50,
213 JSGET = 0x60,
214 JSGE = 0x70,
215 CALL = 0x80,
216 EXIT = 0x90,
217 JLT = 0xa0,
218 JLE = 0xb0,
219 JSLT = 0xc0,
220 JSLE = 0xd0,
221 }
222);
223
224define!(
226 #[mask(0x0f)]
227 pub enum Swap {
228 TO_LE = 0x00,
229 TO_BE = 0x08,
230 }
231);
232
233impl_ops!();
234
235pub const fn len() -> K {
236 todo!()
238}