:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / net / packet / 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 *prog, 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  */