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 RAX 0
41 #define RCX 1
42 #define RDX 2
43 #define RBX 3
44 #define RSP 4
45 #define RBP 5
46 #define RSI 6
47 #define RDI 7
48
49 #define EAX 0
50 #define ECX 1
51 #define EDX 2
52 #define EBX 3
53 #define ESP 4
54 #define EBP 5
55 #define ESI 6
56 #define EDI 7
57
58 #define AX 0
59 #define CX 1
60 #define DX 2
61 #define BX 3
62 #define SP 4
63 #define BP 5
64 #define SI 6
65 #define DI 7
66
67 #define AL 0
68 #define CL 1
69 #define DL 2
70 #define BL 3
71
72 /* A stream of native binary code.*/
73 typedef struct bpf_bin_stream {
74 /* Current native instruction pointer. */
75 int cur_ip;
76
77 /*
78 * Current BPF instruction pointer, i.e. position in
79 * the BPF program reached by the jitter.
80 */
81 int bpf_pc;
82
83 /* Instruction buffer, contains the generated native code. */
84 char *ibuf;
85
86 /* Jumps reference table. */
87 u_int *refs;
88 } bpf_bin_stream;
89
90 /*
91 * Prototype of the emit functions.
92 *
93 * Different emit functions are used to create the reference table and
94 * to generate the actual filtering code. This allows to have simpler
95 * instruction macros.
96 * The first parameter is the stream that will receive the data.
97 * The second one is a variable containing the data.
98 * The third one is the length, that can be 1, 2, or 4 since it is possible
99 * to emit a byte, a short, or a word at a time.
100 */
101 typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
102
103 /*
104 * native Instruction Macros
105 */
106
107 /* mov r32,i32 */
108 #define MOVid(r32, i32) do { \
109 emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \
110 emitm(&stream, i32, 4); \
111 } while (0)
112
113 /* mov r64,i64 */
114 #define MOViq(r64, i64) do { \
115 emitm(&stream, 0x48, 1); \
116 emitm(&stream, (11 << 4) | (1 << 3) | (r64 & 0x7), 1); \
117 emitm(&stream, i64, 4); \
118 emitm(&stream, (i64 >> 32), 4); \
119 } while (0)
120
121 /* mov dr32,sr32 */
122 #define MOVrd(dr32, sr32) do { \
123 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
124 emitm(&stream, \
125 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
126 } while (0)
127
128 /* mov dr64,sr64 */
129 #define MOVrq(dr64, sr64) do { \
130 emitm(&stream, 0x48, 1); \
131 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
132 emitm(&stream, \
133 (3 << 6) | ((dr64 & 0x7) << 3) | (sr64 & 0x7), 1); \
134 } while (0)
135
136 /* mov dr32,sr64[off] */
137 #define MOVodd(dr32, sr64, off) do { \
138 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
139 emitm(&stream, \
140 (1 << 6) | ((dr32 & 0x7) << 3) | (sr64 & 0x7), 1); \
141 emitm(&stream, off, 1); \
142 } while (0)
143
144 /* mov dr64[off],sr32 */
145 #define MOVoqd(dr64, off, sr32) do { \
146 emitm(&stream, (8 << 4) | 1 | (1 << 3), 1); \
147 emitm(&stream, \
148 (1 << 6) | ((sr32 & 0x7) << 3) | (dr64 & 0x7), 1); \
149 emitm(&stream, off, 1); \
150 } while (0)
151
152 /* mov dr32,sr64[or64] */
153 #define MOVobd(dr32, sr64, or64) do { \
154 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
155 emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
156 emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
157 } while (0)
158
159 /* mov dr16,sr64[or64] */
160 #define MOVobw(dr32, sr64, or64) do { \
161 emitm(&stream, 0x66, 1); \
162 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
163 emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
164 emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
165 } while (0)
166
167 /* mov dr8,sr64[or64] */
168 #define MOVobb(dr8, sr64, or64) do { \
169 emitm(&stream, 0x8a, 1); \
170 emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \
171 emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
172 } while (0)
173
174 /* mov [dr64][or64],sr32 */
175 #define MOVomd(dr64, or64, sr32) do { \
176 emitm(&stream, 0x89, 1); \
177 emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \
178 emitm(&stream, ((or64 & 0x7) << 3) | (dr64 & 0x7), 1); \
179 } while (0)
180
181 /* bswap dr32 */
182 #define BSWAP(dr32) do { \
183 emitm(&stream, 0xf, 1); \
184 emitm(&stream, (0x19 << 3) | dr32, 1); \
185 } while (0)
186
187 /* xchg al,ah */
188 #define SWAP_AX() do { \
189 emitm(&stream, 0x86, 1); \
190 emitm(&stream, 0xc4, 1); \
191 } while (0)
192
193 /* push r64 */
194 #define PUSH(r64) do { \
195 emitm(&stream, (5 << 4) | (0 << 3) | (r64 & 0x7), 1); \
196 } while (0)
197
198 /* pop r64 */
199 #define POP(r64) do { \
200 emitm(&stream, (5 << 4) | (1 << 3) | (r64 & 0x7), 1); \
201 } while (0)
202
203 /* leave/ret */
204 #define LEAVE_RET() do { \
205 emitm(&stream, 0xc9, 1); \
206 emitm(&stream, 0xc3, 1); \
207 } while (0)
208
209 /* add dr32,sr32 */
210 #define ADDrd(dr32, sr32) do { \
211 emitm(&stream, 0x03, 1); \
212 emitm(&stream, \
213 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
214 } while (0)
215
216 /* add eax,i32 */
217 #define ADD_EAXi(i32) do { \
218 emitm(&stream, 0x05, 1); \
219 emitm(&stream, i32, 4); \
220 } while (0)
221
222 /* add r32,i32 */
223 #define ADDid(r32, i32) do { \
224 emitm(&stream, 0x81, 1); \
225 emitm(&stream, (24 << 3) | r32, 1); \
226 emitm(&stream, i32, 4); \
227 } while (0)
228
229 /* add r32,i8 */
230 #define ADDib(r32, i8) do { \
231 emitm(&stream, 0x83, 1); \
232 emitm(&stream, (24 << 3) | r32, 1); \
233 emitm(&stream, i8, 1); \
234 } while (0)
235
236 /* sub dr32,sr32 */
237 #define SUBrd(dr32, sr32) do { \
238 emitm(&stream, 0x2b, 1); \
239 emitm(&stream, \
240 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
241 } while (0)
242
243 /* sub eax,i32 */
244 #define SUB_EAXi(i32) do { \
245 emitm(&stream, 0x2d, 1); \
246 emitm(&stream, i32, 4); \
247 } while (0)
248
249 /* mul r32 */
250 #define MULrd(r32) do { \
251 emitm(&stream, 0xf7, 1); \
252 emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
253 } while (0)
254
255 /* div r32 */
256 #define DIVrd(r32) do { \
257 emitm(&stream, 0xf7, 1); \
258 emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \
259 } while (0)
260
261 /* and r8,i8 */
262 #define ANDib(r8, i8) do { \
263 emitm(&stream, 0x80, 1); \
264 emitm(&stream, (7 << 5) | r8, 1); \
265 emitm(&stream, i8, 1); \
266 } while (0)
267
268 /* and r32,i32 */
269 #define ANDid(r32, i32) do { \
270 if (r32 == EAX) { \
271 emitm(&stream, 0x25, 1); \
272 emitm(&stream, i32, 4); \
273 } else { \
274 emitm(&stream, 0x81, 1); \
275 emitm(&stream, (7 << 5) | r32, 1); \
276 emitm(&stream, i32, 4); \
277 } \
278 } while (0)
279
280 /* and dr32,sr32 */
281 #define ANDrd(dr32, sr32) do { \
282 emitm(&stream, 0x23, 1); \
283 emitm(&stream, \
284 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
285 } while (0)
286
287 /* or dr32,sr32 */
288 #define ORrd(dr32, sr32) do { \
289 emitm(&stream, 0x0b, 1); \
290 emitm(&stream, \
291 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
292 } while (0)
293
294 /* or r32,i32 */
295 #define ORid(r32, i32) do { \
296 if (r32 == EAX) { \
297 emitm(&stream, 0x0d, 1); \
298 emitm(&stream, i32, 4); \
299 } else { \
300 emitm(&stream, 0x81, 1); \
301 emitm(&stream, (25 << 3) | r32, 1); \
302 emitm(&stream, i32, 4); \
303 } \
304 } while (0)
305
306 /* shl r32,i8 */
307 #define SHLib(r32, i8) do { \
308 emitm(&stream, 0xc1, 1); \
309 emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
310 emitm(&stream, i8, 1); \
311 } while (0)
312
313 /* shl dr32,cl */
314 #define SHL_CLrb(dr32) do { \
315 emitm(&stream, 0xd3, 1); \
316 emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \
317 } while (0)
318
319 /* shr r32,i8 */
320 #define SHRib(r32, i8) do { \
321 emitm(&stream, 0xc1, 1); \
322 emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
323 emitm(&stream, i8, 1); \
324 } while (0)
325
326 /* shr dr32,cl */
327 #define SHR_CLrb(dr32) do { \
328 emitm(&stream, 0xd3, 1); \
329 emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \
330 } while (0)
331
332 /* neg r32 */
333 #define NEGd(r32) do { \
334 emitm(&stream, 0xf7, 1); \
335 emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \
336 } while (0)
337
338 /* cmp dr32,sr64[off] */
339 #define CMPodd(dr32, sr64, off) do { \
340 emitm(&stream, (3 << 4) | 3 | (1 << 3), 1); \
341 emitm(&stream, \
342 (1 << 6) | ((dr32 & 0x7) << 3) | (sr64 & 0x7), 1); \
343 emitm(&stream, off, 1); \
344 } while (0)
345
346 /* cmp dr32,sr32 */
347 #define CMPrd(dr32, sr32) do { \
348 emitm(&stream, 0x3b, 1); \
349 emitm(&stream, \
350 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
351 } while (0)
352
353 /* cmp dr32,i32 */
354 #define CMPid(dr32, i32) do { \
355 if (dr32 == EAX){ \
356 emitm(&stream, 0x3d, 1); \
357 emitm(&stream, i32, 4); \
358 } else { \
359 emitm(&stream, 0x81, 1); \
360 emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \
361 emitm(&stream, i32, 4); \
362 } \
363 } while (0)
364
365 /* jne off32 */
366 #define JNEb(off8) do { \
367 emitm(&stream, 0x75, 1); \
368 emitm(&stream, off8, 1); \
369 } while (0)
370
371 /* je off32 */
372 #define JE(off32) do { \
373 emitm(&stream, 0x0f, 1); \
374 emitm(&stream, 0x84, 1); \
375 emitm(&stream, off32, 4); \
376 } while (0)
377
378 /* jle off32 */
379 #define JLE(off32) do { \
380 emitm(&stream, 0x0f, 1); \
381 emitm(&stream, 0x8e, 1); \
382 emitm(&stream, off32, 4); \
383 } while (0)
384
385 /* jle off8 */
386 #define JLEb(off8) do { \
387 emitm(&stream, 0x7e, 1); \
388 emitm(&stream, off8, 1); \
389 } while (0)
390
391 /* ja off32 */
392 #define JA(off32) do { \
393 emitm(&stream, 0x0f, 1); \
394 emitm(&stream, 0x87, 1); \
395 emitm(&stream, off32, 4); \
396 } while (0)
397
398 /* jae off32 */
399 #define JAE(off32) do { \
400 emitm(&stream, 0x0f, 1); \
401 emitm(&stream, 0x83, 1); \
402 emitm(&stream, off32, 4); \
403 } while (0)
404
405 /* jg off32 */
406 #define JG(off32) do { \
407 emitm(&stream, 0x0f, 1); \
408 emitm(&stream, 0x8f, 1); \
409 emitm(&stream, off32, 4); \
410 } while (0)
411
412 /* jge off32 */
413 #define JGE(off32) do { \
414 emitm(&stream, 0x0f, 1); \
415 emitm(&stream, 0x8d, 1); \
416 emitm(&stream, off32, 4); \
417 } while (0)
418
419 /* jmp off32 */
420 #define JMP(off32) do { \
421 emitm(&stream, 0xe9, 1); \
422 emitm(&stream, off32, 4); \
423 } while (0)
424
425 /* xor eax,eax */
426 #define ZERO_EAX() do { \
427 emitm(&stream, 0x31, 1); \
428 emitm(&stream, 0xc0, 1); \
429 } while (0)
430
431 /* xor edx,edx */
432 #define ZERO_EDX() do { \
433 emitm(&stream, 0x31, 1); \
434 emitm(&stream, 0xd2, 1); \
435 } while (0)
436
437 #endif /* _BPF_JIT_MACHDEP_H_ */
Cache object: f7b33e145ba92150e17c847b6b3c1300
|