]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/bpf_jit_machdep.h
This commit was generated by cvs2svn to compensate for changes in r169693,
[FreeBSD/FreeBSD.git] / sys / amd64 / amd64 / bpf_jit_machdep.h
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_ */