Patch by Jonathon Wilson:
[reactos.git] / reactos / drivers / net / npf / jitter.h
1 /*
2 * Copyright (c) 2002
3 * Politecnico di Torino. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 /** @ingroup NPF
23 * @{
24 */
25
26 /** @defgroup NPF_include NPF structures and definitions
27 * @{
28 */
29
30 //
31 // Registers
32 //
33 #define EAX 0
34 #define ECX 1
35 #define EDX 2
36 #define EBX 3
37 #define ESP 4
38 #define EBP 5
39 #define ESI 6
40 #define EDI 7
41
42 #define AX 0
43 #define CX 1
44 #define DX 2
45 #define BX 3
46 #define SP 4
47 #define BP 5
48 #define SI 6
49 #define DI 7
50
51 #define AL 0
52 #define CL 1
53 #define DL 2
54 #define BL 3
55
56 /*! \brief A stream of X86 binary code.*/
57 typedef struct binary_stream{
58 INT cur_ip; ///< Current X86 instruction pointer.
59 INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
60 PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
61 PUINT refs; ///< Jumps reference table.
62 }binary_stream;
63
64
65 /*! \brief Prototype of a filtering function created by the jitter.
66
67 The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
68 is not among the parameters, because it is hardwired in the function.
69 */
70 typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT);
71
72 /*! \brief Prototype of the emit functions.
73
74 Different emit functions are used to create the reference table and to generate the actual filtering code.
75 This allows to have simpler instruction macros.
76 The first parameter is the stream that will receive the data. The secon one is a variable containing
77 the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
78 or a work at a time.
79 */
80 typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
81
82 /*! \brief Structure describing a x86 filtering program created by the jitter.*/
83 typedef struct JIT_BPF_Filter{
84 BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
85 PINT mem;
86 }
87 JIT_BPF_Filter;
88
89
90
91
92 /**************************/
93 /* X86 INSTRUCTION MACROS */
94 /**************************/
95
96 /// mov r32,i32
97 #define MOVid(r32, i32) \
98 emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); emitm(&stream, i32, 4);
99
100 /// mov dr32,sr32
101 #define MOVrd(dr32, sr32) \
102 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); emitm(&stream, (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1);
103
104 /// mov dr32,sr32[off]
105 #define MOVodd(dr32, sr32, off) \
106 emitm(&stream, (8 << 4) | 3 | (1 << 3), 1); \
107 emitm(&stream, (1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1);\
108 emitm(&stream, off, 1);
109
110 /// mov dr32,sr32[or32]
111 #define MOVobd(dr32, sr32, or32) \
112 emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
113 emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
114 emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
115
116 /// mov dr16,sr32[or32]
117 #define MOVobw(dr32, sr32, or32) \
118 emitm(&stream, 0x66, 1); \
119 emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
120 emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
121 emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
122
123 /// mov dr8,sr32[or32]
124 #define MOVobb(dr8, sr32, or32) \
125 emitm(&stream, 0x8a, 1); \
126 emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
127 emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
128
129 /// mov [dr32][or32],sr32
130 #define MOVomd(dr32, or32, sr32) \
131 emitm(&stream, 0x89, 1); \
132 emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
133 emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
134
135 /// bswap dr32
136 #define BSWAP(dr32) \
137 emitm(&stream, 0xf, 1); \
138 emitm(&stream, 0x19 << 3 | dr32 , 1);
139
140 /// xchg al,ah
141 #define SWAP_AX() \
142 emitm(&stream, 0x86, 1); \
143 emitm(&stream, 0xc4 , 1);
144
145 /// push r32
146 #define PUSH(r32) \
147 emitm(&stream, (5 << 4) | (0 << 3) | (r32 & 0x7), 1);
148
149 /// pop r32
150 #define POP(r32) \
151 emitm(&stream, (5 << 4) | (1 << 3) | (r32 & 0x7), 1);
152
153 /// ret
154 #define RET() \
155 emitm(&stream, (12 << 4) | (0 << 3) | 3, 1);
156
157 /// add dr32,sr32
158 #define ADDrd(dr32, sr32) \
159 emitm(&stream, 0x03, 1);\
160 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
161
162 /// add eax,i32
163 #define ADD_EAXi(i32) \
164 emitm(&stream, 0x05, 1);\
165 emitm(&stream, i32, 4);
166
167 /// add r32,i32
168 #define ADDid(r32, i32) \
169 emitm(&stream, 0x81, 1);\
170 emitm(&stream, 24 << 3 | r32, 1);\
171 emitm(&stream, i32, 4);
172
173 /// add r32,i8
174 #define ADDib(r32, i8) \
175 emitm(&stream, 0x83, 1);\
176 emitm(&stream, 24 << 3 | r32, 1);\
177 emitm(&stream, i8, 1);
178
179 /// sub dr32,sr32
180 #define SUBrd(dr32, sr32) \
181 emitm(&stream, 0x2b, 1);\
182 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
183
184 /// sub eax,i32
185 #define SUB_EAXi(i32) \
186 emitm(&stream, 0x2d, 1);\
187 emitm(&stream, i32, 4);
188
189 /// mul r32
190 #define MULrd(r32) \
191 emitm(&stream, 0xf7, 1);\
192 emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
193
194 /// div r32
195 #define DIVrd(r32) \
196 emitm(&stream, 0xf7, 1);\
197 emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
198
199 /// and r8,i8
200 #define ANDib(r8, i8) \
201 emitm(&stream, 0x80, 1);\
202 emitm(&stream, 7 << 5 | r8, 1);\
203 emitm(&stream, i8, 1);
204
205 /// and r32,i32
206 #define ANDid(r32, i32) \
207 if (r32 == EAX){ \
208 emitm(&stream, 0x25, 1);\
209 emitm(&stream, i32, 4);}\
210 else{ \
211 emitm(&stream, 0x81, 1);\
212 emitm(&stream, 7 << 5 | r32, 1);\
213 emitm(&stream, i32, 4);}
214
215 /// and dr32,sr32
216 #define ANDrd(dr32, sr32) \
217 emitm(&stream, 0x23, 1);\
218 emitm(&stream, (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1);
219
220 /// or dr32,sr32
221 #define ORrd(dr32, sr32) \
222 emitm(&stream, 0x0b, 1);\
223 emitm(&stream, (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1);
224
225 /// or r32,i32
226 #define ORid(r32, i32) \
227 if (r32 == EAX){ \
228 emitm(&stream, 0x0d, 1);\
229 emitm(&stream, i32, 4);}\
230 else{ \
231 emitm(&stream, 0x81, 1);\
232 emitm(&stream, 25 << 3 | r32, 1);\
233 emitm(&stream, i32, 4);}
234
235 /// shl r32,i8
236 #define SHLib(r32, i8) \
237 emitm(&stream, 0xc1, 1);\
238 emitm(&stream, (7 << 5) | (r32 & 0x7), 1);\
239 emitm(&stream, i8, 1);
240
241 /// shl dr32,cl
242 #define SHL_CLrb(dr32) \
243 emitm(&stream, 0xd3, 1);\
244 emitm(&stream, (7 << 5) | (dr32 & 0x7), 1);
245
246 /// shr r32,i8
247 #define SHRib(r32, i8) \
248 emitm(&stream, 0xc1, 1);\
249 emitm(&stream, (29 << 3) | (r32 & 0x7), 1);\
250 emitm(&stream, i8, 1);
251
252 /// shr dr32,cl
253 #define SHR_CLrb(dr32) \
254 emitm(&stream, 0xd3, 1);\
255 emitm(&stream, (29 << 3) | (dr32 & 0x7), 1);
256
257 /// neg r32
258 #define NEGd(r32) \
259 emitm(&stream, 0xf7, 1);\
260 emitm(&stream, (27 << 3) | (r32 & 0x7), 1);
261
262 /// cmp dr32,sr32[off]
263 #define CMPodd(dr32, sr32, off) \
264 emitm(&stream, (3 << 4) | 3 | (1 << 3), 1); \
265 emitm(&stream, (1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1);\
266 emitm(&stream, off, 1);
267
268 /// cmp dr32,sr32
269 #define CMPrd(dr32, sr32) \
270 emitm(&stream, 0x3b, 1); \
271 emitm(&stream, (3 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1);
272
273 /// cmp dr32,i32
274 #define CMPid(dr32, i32) \
275 if (dr32 == EAX){ \
276 emitm(&stream, 0x3d, 1); \
277 emitm(&stream, i32, 4);} \
278 else{ \
279 emitm(&stream, 0x81, 1); \
280 emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
281 emitm(&stream, i32, 4);}
282
283 /// jne off32
284 #define JNEb(off8) \
285 emitm(&stream, 0x75, 1);\
286 emitm(&stream, off8, 1);
287
288 /// je off32
289 #define JE(off32) \
290 emitm(&stream, 0x0f, 1);\
291 emitm(&stream, 0x84, 1);\
292 emitm(&stream, off32, 4);
293
294 /// jle off32
295 #define JLE(off32) \
296 emitm(&stream, 0x0f, 1);\
297 emitm(&stream, 0x8e, 1);\
298 emitm(&stream, off32, 4);
299
300 /// jle off8
301 #define JLEb(off8) \
302 emitm(&stream, 0x7e, 1);\
303 emitm(&stream, off8, 1);
304
305 /// ja off32
306 #define JA(off32) \
307 emitm(&stream, 0x0f, 1);\
308 emitm(&stream, 0x87, 1);\
309 emitm(&stream, off32, 4);
310
311 /// jae off32
312 #define JAE(off32) \
313 emitm(&stream, 0x0f, 1);\
314 emitm(&stream, 0x83, 1);\
315 emitm(&stream, off32, 4);
316
317 /// jg off32
318 #define JG(off32) \
319 emitm(&stream, 0x0f, 1);\
320 emitm(&stream, 0x8f, 1);\
321 emitm(&stream, off32, 4);
322
323 /// jge off32
324 #define JGE(off32) \
325 emitm(&stream, 0x0f, 1);\
326 emitm(&stream, 0x8d, 1);\
327 emitm(&stream, off32, 4);
328
329 /// jmp off32
330 #define JMP(off32) \
331 emitm(&stream, 0xe9, 1);\
332 emitm(&stream, off32, 4);
333
334 /**
335 * @}
336 */
337
338 /**
339 * @}
340 */
341
342 /**************************/
343 /* Prototypes */
344 /**************************/
345
346 /** @ingroup NPF
347 * @{
348 */
349
350 /** @defgroup NPF_code NPF functions
351 * @{
352 */
353
354 /*!
355 \brief BPF jitter, builds an x86 function from a BPF program.
356 \param fp The BPF pseudo-assembly filter that will be translated into x86 code.
357 \param nins Number of instructions of the input filter.
358 \return The JIT_BPF_Filter structure containing the x86 filtering binary.
359
360 BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
361 calling BPFtoX86().
362 */
363 JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
364
365 /*!
366 \brief Translates a set of BPF instructions in a set of x86 ones.
367 \param ins Pointer to the BPF instructions that will be translated into x86 code.
368 \param nins Number of instructions to translate.
369 \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
370 \return The x86 filtering function.
371
372 This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
373 through the instruction macros defined in jitter.h it is able to create an function directly executable
374 by NPF.
375 */
376 BPF_filter_function BPFtoX86(struct bpf_insn *ins, UINT nins, INT *mem);
377 /*!
378 \brief Deletes a filtering function that was previously created by BPF_jitter().
379 \param Filter The filter to destroy.
380
381 This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
382 */
383 void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
384
385 /**
386 * @}
387 */
388
389 /**
390 * @}
391 */