1 /*-
2 * Copyright (c) 2002 - 2003 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 Jung-uk Kim <jkim@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS intERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34 #ifndef _BPF_JIT_MACHDEP_H_
35 #define _BPF_JIT_MACHDEP_H_
36
37 /*
38 * Registers
39 */
40 #define EAX 0
41 #define ECX 1
42 #define EDX 2
43 #define EBX 3
44 #define ESP 4
45 #define EBP 5
46 #define ESI 6
47 #define EDI 7
48
49 #define AX 0
50 #define CX 1
51 #define DX 2
52 #define BX 3
53 #define SP 4
54 #define BP 5
55 #define SI 6
56 #define DI 7
57
58 #define AL 0
59 #define CL 1
60 #define DL 2
61 #define BL 3
62
63 /* A stream of native binary code.*/
64 typedef struct bpf_bin_stream {
65 /* Current native instruction pointer. */
66 int cur_ip;
67
68 /*
69 * Current BPF instruction pointer, i.e. position in
70 * the BPF program reached by the jitter.
71 */
72 int bpf_pc;
73
74 /* Instruction buffer, contains the generated native code. */
75 char *ibuf;
76
77 /* Jumps reference table. */
78 u_int *refs;
79 } bpf_bin_stream;
80
81 /*
82 * Prototype of the emit functions.
83 *
84 * Different emit functions are used to create the reference table and
85 * to generate the actual filtering code. This allows to have simpler
86 * instruction macros.
87 * The first parameter is the stream that will receive the data.
88 * The second one is a variable containing the data.
89 * The third one is the length, that can be 1, 2, or 4 since it is possible
90 * to emit a byte, a short, or a word at a time.
91 */
92 typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
93
94 /*
95 * native Instruction Macros
96 */
97
98 /* mov r32,i32 */
99 #define MOVid(r32, i32) do { \
100 emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \
101 emitm(&stream, i32, 4); \
102 } while (0)
103
104 /* mov dr32,sr32 */
105 #define MOVrd(dr32, sr32) do { \
106 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
107 emitm(&stream, \
108 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
109 } while (0)
110
111 /* mov dr32,sr32[off] */
112 #define MOVodd(dr32, sr32, off) do { \
113 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
114 emitm(&stream, \
115 (1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
116 emitm(&stream, off, 1); \
117 } while (0)
118
119 /* mov dr32,sr32[or32] */
120 #define MOVobd(dr32, sr32, or32) do { \
121 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
122 emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
123 emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \
124 } while (0)
125
126 /* mov dr16,sr32[or32] */
127 #define MOVobw(dr32, sr32, or32) do { \
128 emitm(&stream, 0x66, 1); \
129 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
130 emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
131 emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \
132 } while (0)
133
134 /* mov dr8,sr32[or32] */
135 #define MOVobb(dr8, sr32, or32) do { \
136 emitm(&stream, 0x8a, 1); \
137 emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \
138 emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \
139 } while (0)
140
141 /* mov [dr32][or32],sr32 */
142 #define MOVomd(dr32, or32, sr32) do { \
143 emitm(&stream, 0x89, 1); \
144 emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \
145 emitm(&stream, ((or32 & 0x7) << 3) | (dr32 & 0x7), 1); \
146 } while (0)
147
148 /* bswap dr32 */
149 #define BSWAP(dr32) do { \
150 emitm(&stream, 0xf, 1); \
151 emitm(&stream, (0x19 << 3) | dr32, 1); \
152 } while (0)
153
154 /* xchg al,ah */
155 #define SWAP_AX() do { \
156 emitm(&stream, 0x86, 1); \
157 emitm(&stream, 0xc4, 1); \
158 } while (0)
159
160 /* push r32 */
161 #define PUSH(r32) do { \
162 emitm(&stream, (5 << 4) | (0 << 3) | (r32 & 0x7), 1); \
163 } while (0)
164
165 /* pop r32 */
166 #define POP(r32) do { \
167 emitm(&stream, (5 << 4) | (1 << 3) | (r32 & 0x7), 1); \
168 } while (0)
169
170 /* leave/ret */
171 #define LEAVE_RET() do { \
172 emitm(&stream, 0xc9, 1); \
173 emitm(&stream, 0xc3, 1); \
174 } while (0)
175
176 /* add dr32,sr32 */
177 #define ADDrd(dr32, sr32) do { \
178 emitm(&stream, 0x03, 1); \
179 emitm(&stream, \
180 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
181 } while (0)
182
183 /* add eax,i32 */
184 #define ADD_EAXi(i32) do { \
185 emitm(&stream, 0x05, 1); \
186 emitm(&stream, i32, 4); \
187 } while (0)
188
189 /* add r32,i32 */
190 #define ADDid(r32, i32) do { \
191 emitm(&stream, 0x81, 1); \
192 emitm(&stream, (24 << 3) | r32, 1); \
193 emitm(&stream, i32, 4); \
194 } while (0)
195
196 /* add r32,i8 */
197 #define ADDib(r32, i8) do { \
198 emitm(&stream, 0x83, 1); \
199 emitm(&stream, (24 << 3) | r32, 1); \
200 emitm(&stream, i8, 1); \
201 } while (0)
202
203 /* sub dr32,sr32 */
204 #define SUBrd(dr32, sr32) do { \
205 emitm(&stream, 0x2b, 1); \
206 emitm(&stream, \
207 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
208 } while (0)
209
210 /* sub eax,i32 */
211 #define SUB_EAXi(i32) do { \
212 emitm(&stream, 0x2d, 1); \
213 emitm(&stream, i32, 4); \
214 } while (0)
215
216 /* mul r32 */
217 #define MULrd(r32) do { \
218 emitm(&stream, 0xf7, 1); \
219 emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
220 } while (0)
221
222 /* div r32 */
223 #define DIVrd(r32) do { \
224 emitm(&stream, 0xf7, 1); \
225 emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \
226 } while (0)
227
228 /* and r8,i8 */
229 #define ANDib(r8, i8) do { \
230 emitm(&stream, 0x80, 1); \
231 emitm(&stream, (7 << 5) | r8, 1); \
232 emitm(&stream, i8, 1); \
233 } while (0)
234
235 /* and r32,i32 */
236 #define ANDid(r32, i32) do { \
237 if (r32 == EAX) { \
238 emitm(&stream, 0x25, 1); \
239 emitm(&stream, i32, 4); \
240 } else { \
241 emitm(&stream, 0x81, 1); \
242 emitm(&stream, (7 << 5) | r32, 1); \
243 emitm(&stream, i32, 4); \
244 } \
245 } while (0)
246
247 /* and dr32,sr32 */
248 #define ANDrd(dr32, sr32) do { \
249 emitm(&stream, 0x23, 1); \
250 emitm(&stream, \
251 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
252 } while (0)
253
254 /* or dr32,sr32 */
255 #define ORrd(dr32, sr32) do { \
256 emitm(&stream, 0x0b, 1); \
257 emitm(&stream, \
258 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
259 } while (0)
260
261 /* or r32,i32 */
262 #define ORid(r32, i32) do { \
263 if (r32 == EAX) { \
264 emitm(&stream, 0x0d, 1); \
265 emitm(&stream, i32, 4); \
266 } else { \
267 emitm(&stream, 0x81, 1); \
268 emitm(&stream, (25 << 3) | r32, 1); \
269 emitm(&stream, i32, 4); \
270 } \
271 } while (0)
272
273 /* shl r32,i8 */
274 #define SHLib(r32, i8) do { \
275 emitm(&stream, 0xc1, 1); \
276 emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
277 emitm(&stream, i8, 1); \
278 } while (0)
279
280 /* shl dr32,cl */
281 #define SHL_CLrb(dr32) do { \
282 emitm(&stream, 0xd3, 1); \
283 emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \
284 } while (0)
285
286 /* shr r32,i8 */
287 #define SHRib(r32, i8) do { \
288 emitm(&stream, 0xc1, 1); \
289 emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
290 emitm(&stream, i8, 1); \
291 } while (0)
292
293 /* shr dr32,cl */
294 #define SHR_CLrb(dr32) do { \
295 emitm(&stream, 0xd3, 1); \
296 emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \
297 } while (0)
298
299 /* neg r32 */
300 #define NEGd(r32) do { \
301 emitm(&stream, 0xf7, 1); \
302 emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \
303 } while (0)
304
305 /* cmp dr32,sr32[off] */
306 #define CMPodd(dr32, sr32, off) do { \
307 emitm(&stream, (3 << 4) | 3 | (1 << 3), 1); \
308 emitm(&stream, \
309 (1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
310 emitm(&stream, off, 1); \
311 } while (0)
312
313 /* cmp dr32,sr32 */
314 #define CMPrd(dr32, sr32) do { \
315 emitm(&stream, 0x3b, 1); \
316 emitm(&stream, \
317 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
318 } while (0)
319
320 /* cmp dr32,i32 */
321 #define CMPid(dr32, i32) do { \
322 if (dr32 == EAX){ \
323 emitm(&stream, 0x3d, 1); \
324 emitm(&stream, i32, 4); \
325 } else { \
326 emitm(&stream, 0x81, 1); \
327 emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \
328 emitm(&stream, i32, 4); \
329 } \
330 } while (0)
331
332 /* jne off32 */
333 #define JNEb(off8) do { \
334 emitm(&stream, 0x75, 1); \
335 emitm(&stream, off8, 1); \
336 } while (0)
337
338 /* je off32 */
339 #define JE(off32) do { \
340 emitm(&stream, 0x0f, 1); \
341 emitm(&stream, 0x84, 1); \
342 emitm(&stream, off32, 4); \
343 } while (0)
344
345 /* jle off32 */
346 #define JLE(off32) do { \
347 emitm(&stream, 0x0f, 1); \
348 emitm(&stream, 0x8e, 1); \
349 emitm(&stream, off32, 4); \
350 } while (0)
351
352 /* jle off8 */
353 #define JLEb(off8) do { \
354 emitm(&stream, 0x7e, 1); \
355 emitm(&stream, off8, 1); \
356 } while (0)
357
358 /* ja off32 */
359 #define JA(off32) do { \
360 emitm(&stream, 0x0f, 1); \
361 emitm(&stream, 0x87, 1); \
362 emitm(&stream, off32, 4); \
363 } while (0)
364
365 /* jae off32 */
366 #define JAE(off32) do { \
367 emitm(&stream, 0x0f, 1); \
368 emitm(&stream, 0x83, 1); \
369 emitm(&stream, off32, 4); \
370 } while (0)
371
372 /* jg off32 */
373 #define JG(off32) do { \
374 emitm(&stream, 0x0f, 1); \
375 emitm(&stream, 0x8f, 1); \
376 emitm(&stream, off32, 4); \
377 } while (0)
378
379 /* jge off32 */
380 #define JGE(off32) do { \
381 emitm(&stream, 0x0f, 1); \
382 emitm(&stream, 0x8d, 1); \
383 emitm(&stream, off32, 4); \
384 } while (0)
385
386 /* jmp off32 */
387 #define JMP(off32) do { \
388 emitm(&stream, 0xe9, 1); \
389 emitm(&stream, off32, 4); \
390 } while (0)
391
392 /* xor eax,eax */
393 #define ZERO_EAX() do { \
394 emitm(&stream, 0x31, 1); \
395 emitm(&stream, 0xc0, 1); \
396 } while (0)
397
398 /* xor edx,edx */
399 #define ZERO_EDX() do { \
400 emitm(&stream, 0x31, 1); \
401 emitm(&stream, 0xd2, 1); \
402 } while (0)
403
404 #endif /* _BPF_JIT_MACHDEP_H_ */
Cache object: ab0aaf4e36fafd549a657e0e90645bce
|