2 * Copyright (c) 2002 - 2003 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 Jung-uk Kim <jkim@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
34 #ifndef _BPF_JIT_MACHDEP_H_
35 #define _BPF_JIT_MACHDEP_H_
72 /* A stream of native binary code.*/
73 typedef struct bpf_bin_stream {
74 /* Current native instruction pointer. */
78 * Current BPF instruction pointer, i.e. position in
79 * the BPF program reached by the jitter.
83 /* Instruction buffer, contains the generated native code. */
86 /* Jumps reference table. */
91 * Prototype of the emit functions.
93 * Different emit functions are used to create the reference table and
94 * to generate the actual filtering code. This allows to have simpler
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.
101 typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
104 * native Instruction Macros
108 #define MOVid(r32, i32) do { \
109 emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \
110 emitm(&stream, i32, 4); \
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); \
122 #define MOVrd(dr32, sr32) do { \
123 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
125 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
129 #define MOVrq(dr64, sr64) do { \
130 emitm(&stream, 0x48, 1); \
131 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
133 (3 << 6) | ((dr64 & 0x7) << 3) | (sr64 & 0x7), 1); \
136 /* mov dr32,sr64[off] */
137 #define MOVodd(dr32, sr64, off) do { \
138 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
140 (1 << 6) | ((dr32 & 0x7) << 3) | (sr64 & 0x7), 1); \
141 emitm(&stream, off, 1); \
144 /* mov dr64[off],sr32 */
145 #define MOVoqd(dr64, off, sr32) do { \
146 emitm(&stream, (8 << 4) | 1 | (1 << 3), 1); \
148 (1 << 6) | ((sr32 & 0x7) << 3) | (dr64 & 0x7), 1); \
149 emitm(&stream, off, 1); \
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); \
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); \
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); \
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); \
182 #define BSWAP(dr32) do { \
183 emitm(&stream, 0xf, 1); \
184 emitm(&stream, (0x19 << 3) | dr32, 1); \
188 #define SWAP_AX() do { \
189 emitm(&stream, 0x86, 1); \
190 emitm(&stream, 0xc4, 1); \
194 #define PUSH(r64) do { \
195 emitm(&stream, (5 << 4) | (0 << 3) | (r64 & 0x7), 1); \
199 #define POP(r64) do { \
200 emitm(&stream, (5 << 4) | (1 << 3) | (r64 & 0x7), 1); \
204 #define LEAVE_RET() do { \
205 emitm(&stream, 0xc9, 1); \
206 emitm(&stream, 0xc3, 1); \
210 #define ADDrd(dr32, sr32) do { \
211 emitm(&stream, 0x03, 1); \
213 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
217 #define ADD_EAXi(i32) do { \
218 emitm(&stream, 0x05, 1); \
219 emitm(&stream, i32, 4); \
223 #define ADDid(r32, i32) do { \
224 emitm(&stream, 0x81, 1); \
225 emitm(&stream, (24 << 3) | r32, 1); \
226 emitm(&stream, i32, 4); \
230 #define ADDib(r32, i8) do { \
231 emitm(&stream, 0x83, 1); \
232 emitm(&stream, (24 << 3) | r32, 1); \
233 emitm(&stream, i8, 1); \
237 #define SUBrd(dr32, sr32) do { \
238 emitm(&stream, 0x2b, 1); \
240 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
244 #define SUB_EAXi(i32) do { \
245 emitm(&stream, 0x2d, 1); \
246 emitm(&stream, i32, 4); \
250 #define MULrd(r32) do { \
251 emitm(&stream, 0xf7, 1); \
252 emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
256 #define DIVrd(r32) do { \
257 emitm(&stream, 0xf7, 1); \
258 emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \
262 #define ANDib(r8, i8) do { \
263 emitm(&stream, 0x80, 1); \
264 emitm(&stream, (7 << 5) | r8, 1); \
265 emitm(&stream, i8, 1); \
269 #define ANDid(r32, i32) do { \
271 emitm(&stream, 0x25, 1); \
272 emitm(&stream, i32, 4); \
274 emitm(&stream, 0x81, 1); \
275 emitm(&stream, (7 << 5) | r32, 1); \
276 emitm(&stream, i32, 4); \
281 #define ANDrd(dr32, sr32) do { \
282 emitm(&stream, 0x23, 1); \
284 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
288 #define ORrd(dr32, sr32) do { \
289 emitm(&stream, 0x0b, 1); \
291 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
295 #define ORid(r32, i32) do { \
297 emitm(&stream, 0x0d, 1); \
298 emitm(&stream, i32, 4); \
300 emitm(&stream, 0x81, 1); \
301 emitm(&stream, (25 << 3) | r32, 1); \
302 emitm(&stream, i32, 4); \
307 #define SHLib(r32, i8) do { \
308 emitm(&stream, 0xc1, 1); \
309 emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
310 emitm(&stream, i8, 1); \
314 #define SHL_CLrb(dr32) do { \
315 emitm(&stream, 0xd3, 1); \
316 emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \
320 #define SHRib(r32, i8) do { \
321 emitm(&stream, 0xc1, 1); \
322 emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
323 emitm(&stream, i8, 1); \
327 #define SHR_CLrb(dr32) do { \
328 emitm(&stream, 0xd3, 1); \
329 emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \
333 #define NEGd(r32) do { \
334 emitm(&stream, 0xf7, 1); \
335 emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \
338 /* cmp dr32,sr64[off] */
339 #define CMPodd(dr32, sr64, off) do { \
340 emitm(&stream, (3 << 4) | 3 | (1 << 3), 1); \
342 (1 << 6) | ((dr32 & 0x7) << 3) | (sr64 & 0x7), 1); \
343 emitm(&stream, off, 1); \
347 #define CMPrd(dr32, sr32) do { \
348 emitm(&stream, 0x3b, 1); \
350 (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
354 #define CMPid(dr32, i32) do { \
356 emitm(&stream, 0x3d, 1); \
357 emitm(&stream, i32, 4); \
359 emitm(&stream, 0x81, 1); \
360 emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \
361 emitm(&stream, i32, 4); \
366 #define JNEb(off8) do { \
367 emitm(&stream, 0x75, 1); \
368 emitm(&stream, off8, 1); \
372 #define JE(off32) do { \
373 emitm(&stream, 0x0f, 1); \
374 emitm(&stream, 0x84, 1); \
375 emitm(&stream, off32, 4); \
379 #define JLE(off32) do { \
380 emitm(&stream, 0x0f, 1); \
381 emitm(&stream, 0x8e, 1); \
382 emitm(&stream, off32, 4); \
386 #define JLEb(off8) do { \
387 emitm(&stream, 0x7e, 1); \
388 emitm(&stream, off8, 1); \
392 #define JA(off32) do { \
393 emitm(&stream, 0x0f, 1); \
394 emitm(&stream, 0x87, 1); \
395 emitm(&stream, off32, 4); \
399 #define JAE(off32) do { \
400 emitm(&stream, 0x0f, 1); \
401 emitm(&stream, 0x83, 1); \
402 emitm(&stream, off32, 4); \
406 #define JG(off32) do { \
407 emitm(&stream, 0x0f, 1); \
408 emitm(&stream, 0x8f, 1); \
409 emitm(&stream, off32, 4); \
413 #define JGE(off32) do { \
414 emitm(&stream, 0x0f, 1); \
415 emitm(&stream, 0x8d, 1); \
416 emitm(&stream, off32, 4); \
420 #define JMP(off32) do { \
421 emitm(&stream, 0xe9, 1); \
422 emitm(&stream, off32, 4); \
426 #define ZERO_EAX() do { \
427 emitm(&stream, 0x31, 1); \
428 emitm(&stream, 0xc0, 1); \
432 #define ZERO_EDX() do { \
433 emitm(&stream, 0x31, 1); \
434 emitm(&stream, 0xd2, 1); \
437 #endif /* _BPF_JIT_MACHDEP_H_ */