2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1993 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
54 #include <kern/zalloc.h>
56 #define NET_REG_EAX 0 /* data segment register */
57 #define NET_REG_EDX 1 /* header segment register */
58 #define NET_REG_EBX 2 /* free register */
59 #define NET_REG_ESI 3 /* free register */
60 #define NET_REG_EDI 4 /* free register */
61 #define NET_REG_MAX 5 /* number of available registers */
64 filter_t val
; /* value */
65 unsigned char reg
; /* register associated */
66 unsigned char used
; /* how many times it will be used */
69 boolean_t net_filter_enable
= FALSE
;
72 * Forward declarations.
74 void net_filter_optimize(
75 struct net_opt net_o
[],
81 * Compilation of a source network filter into i386 instructions.
95 unsigned char *pend_old
;
97 unsigned int use_header
;
98 unsigned int use_data
;
99 unsigned int push_ecx
;
100 int reg
[NET_REG_MAX
];
101 struct net_opt net_o
[NET_MAX_FILTER
];
110 * Addresses of end_true and end_false from the end of the program.
112 #define PEND_TRUE (pend_old - (11 + push + false_pad))
113 #define PEND_FALSE (pend_old - (4 + push))
116 * Don't produce anything if net_filter generation is not enabled.
118 if (!net_filter_enable
) {
120 return ((filter_fct_t
)0);
124 * called as (*filter)(data, data_count, header)
128 * %eax -> data (if needed);
129 * %edx -> header (if needed);
132 p
= (unsigned char *)0;
137 false_pad
= sizeof(int) - 1;
140 * The compiler needs 3 passes to produce the compiled net_filter:
141 * 0) compute without optimization the maximum size of the object
143 * 1) try to reduce the size of the object procedure (many runs),
144 * 2) produce final object code (one run).
150 else if (loop
== 1) {
151 if (reg
[NET_REG_EBX
] == -1) {
152 /* push and pop it */
157 if (reg
[NET_REG_ESI
] == -1) {
158 /* push and pop it */
162 if (reg
[NET_REG_EDI
] == -1) {
163 /* push and pop it */
179 *p
++ = 0x55; /* pushl %ebp */
180 *p
++ = 0x89; /* movl %esp, %ebp */
182 if (reg
[NET_REG_EBX
] == -1)
183 *p
++ = 0x53; /* pushl %ebx */
184 if (reg
[NET_REG_ESI
] == -1)
185 *p
++ = 0x56; /* pushl %esi */
186 if (reg
[NET_REG_EDI
] == -1)
187 *p
++ = 0x57; /* pushl %edi */
188 *p
++ = 0xB9; /* movl $1, %ecx */
194 *p
++ = 0x8B; /* movl 0x8(%ebp), %eax */
199 *p
++ = 0x8B; /* movl 0x10(%ebp), %edx */
208 while (fp
- fpstart
< fplen
)
226 *p
++ = 0x59; /* popl %ecx */
241 *p
++ = 0x51; /* pushl %ecx */
244 *p
++ = 0x31; /* xorl %ecx, %ecx */
261 *p
++ = 0x51; /* pushl %ecx */
264 *p
++ = 0xB9; /* movl *fp, %ecx */
265 *p
++ = *(unsigned char *)fp
;
266 *p
++ = *(((unsigned char *)fp
) + 1);
276 * if (arg >= data_count)
278 * arg = data_word[arg];
288 PEND_FALSE
- (pend
+ 5) >= 128)
298 *p
++ = 0x59; /* popl %ecx */
299 *p
++ = 0x39; /* cmpl 0xC(%ebp), %ecx */
303 if (PEND_FALSE
- (p
+ 2) >= 128) {
304 *p
++ = 0x0F; /* jle end_false */
306 *(p
+0) = PEND_FALSE
- (p
+ 4);
307 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
308 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
309 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
313 *p
++ = 0x7E; /* jle end_false */
314 *p
= PEND_FALSE
- (p
+ 1);
318 *p
++ = 0x0F; /* movzwl 0(%eax,%ecx,2), %ecx */
325 case NETF_PUSHHDRIND
:
328 * if (arg >= (NET_HDW_HDR_MAX /
329 * sizeof(unsigned short))
331 * arg = header_word[arg];
341 PEND_FALSE
- (pend
+ 8) >= 128)
351 *p
++ = 0x59; /* popl %ecx */
352 *p
++ = 0x81; /* cmpl %ecx, <value> */
354 *p
++ = NET_HDW_HDR_MAX
/
355 sizeof(unsigned short);
356 *p
++ = (NET_HDW_HDR_MAX
/
357 sizeof(unsigned short)) >> 8;
358 *p
++ = (NET_HDW_HDR_MAX
/
359 sizeof(unsigned short)) >> 16;
360 *p
++ = (NET_HDW_HDR_MAX
/
361 sizeof(unsigned short)) >> 24;
363 if (PEND_FALSE
- (p
+ 2) >= 128) {
364 *p
++ = 0x0F; /* jge end_false */
366 *(p
+0) = PEND_FALSE
- (p
+ 4);
367 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
368 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
369 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
373 *p
++ = 0x7D; /* jge end_false */
374 *p
= PEND_FALSE
- (p
+ 1);
378 *p
++ = 0x0F; /* movzwl 0(%edx,%ecx,2), %ecx */
386 if (arg
>= NETF_PUSHSTK
) {
397 pend
+= (arg
< 128) ? 4 : 7;
402 *p
++ = 0x51; /* pushl %ecx */
405 *p
++ = 0x8B; /* movl arg(%esp), %ecx */
419 } else if (arg
>= NETF_PUSHHDR
) {
422 * arg = header_word[arg];
436 assert(net_i
< net_j
);
438 assert(reg
[NET_REG_EDX
]
440 assert(pn
->used
== 0 ||
443 assert(pn
->val
== arg
+
453 pend
+= (arg
< 128) ? 5 : 8;
454 if (loop
== 1 && pn
->used
> 1 &&
456 net_o
[reg
[pn
->reg
]].val
!=
458 reg
[pn
->reg
] = net_i
;
465 *p
++ = 0x51; /* pushl %ecx */
470 assert(net_i
< net_j
);
472 assert(reg
[NET_REG_EDX
] == -2);
473 assert(pn
->used
== 0 ||
475 assert(pn
->val
== arg
+ NETF_PUSHHDR
);
478 net_o
[reg
[pn
->reg
]].val
==
483 /* movl %eax, %ecx */
488 /* movl %ebx, %ecx */
493 /* movl %esi, %ecx */
498 /* movl %edi, %ecx */
505 *p
++ = 0x0F;/* movzwl arg(%edx),%ecx */
521 (reg
[pn
->reg
] == -1 ||
522 net_o
[reg
[pn
->reg
]].val
!=
524 reg
[pn
->reg
] = net_i
;
526 assert(net_o
[net_i
].reg
!=
528 switch (net_o
[net_i
].reg
) {
530 /* movl %ecx, %eax */
534 /* movl %ecx, %ebx */
538 /* movl %ecx, %esi */
542 /* movl %ecx, %edi */
549 arg
-= NETF_PUSHWORD
;
551 * if (arg >= data_count)
553 * arg = data_word[arg];
566 assert(net_i
< net_j
);
568 assert(reg
[NET_REG_EAX
]
570 assert(pn
->used
== 0 ||
573 assert(pn
->val
== arg
+
584 pend
+= (arg
< 128) ? 4 : 7;
596 if (loop
== 1 && pn
->used
> 1 &&
598 net_o
[reg
[pn
->reg
]].val
!=
600 reg
[pn
->reg
] = net_i
;
607 *p
++ = 0x51; /* pushl %ecx */
612 assert(net_i
< net_j
);
614 assert(reg
[NET_REG_EAX
] == -2);
615 assert(pn
->used
== 0 ||
617 assert(pn
->val
== arg
+ NETF_PUSHWORD
);
620 net_o
[reg
[pn
->reg
]].val
==
625 /* movl %edx, %ecx */
630 /* movl %ebx, %ecx */
635 /* movl %esi, %ecx */
640 /* movl %edi, %ecx */
647 /* cmpl 0xC(%ebp), <arg> */
664 if (PEND_FALSE
- (p
+ 2) >= 128) {
665 *p
++ = 0x0F;/* jle end_false */
667 *(p
+0) = PEND_FALSE
- (p
+ 4);
668 *(p
+1) = (PEND_FALSE
- (p
+ 4))
670 *(p
+2) = (PEND_FALSE
- (p
+ 4))
672 *(p
+3) = (PEND_FALSE
- (p
+ 4))
677 *p
++ = 0x7E;/* jle end_false */
678 *p
= PEND_FALSE
- (p
+ 1);
682 *p
++ = 0x0F;/* movzwl arg(%eax),%ecx */
698 (reg
[pn
->reg
] == -1 ||
699 net_o
[reg
[pn
->reg
]].val
!=
701 reg
[pn
->reg
] = net_i
;
703 assert(net_o
[net_i
].reg
!=
705 switch (net_o
[net_i
].reg
) {
707 /* movl %ecx, %edx */
711 /* movl %ecx, %ebx */
715 /* movl %ecx, %esi */
719 /* movl %ecx, %edi */
729 case NETF_OP(NETF_NOP
):
736 case NETF_OP(NETF_AND
):
743 *p
++ = 0x21; /* andl (%esp), %ecx */
749 case NETF_OP(NETF_OR
):
756 *p
++ = 0x09; /* orl (%esp), %ecx */
762 case NETF_OP(NETF_XOR
):
769 *p
++ = 0x31; /* xorl (%esp), %ecx */
775 case NETF_OP(NETF_EQ
):
777 * *sp = (*sp == arg);
782 * Pad to longword boundary (cf dissas).
784 if (i
= ((pend
- (unsigned char *)0) &
786 pend
+= (sizeof(int) - i
);
790 *p
++ = 0x39; /* cmpl (%esp), %ecx */
794 i
= ((p
- (unsigned char *)top
) + 11) &
796 *p
++ = 0x74; /* je .+9+<pad> */
797 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
798 *p
++ = 0xC7; /* movl $0, 0(%esp) */
806 i
= ((p
- (unsigned char *)top
) + 2) &
808 *p
++ = 0xEB; /* jmp .+7+<pad> */
809 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
812 * Pad to longword boundary (cf dissas).
814 if (i
= (p
- (unsigned char *)top
) &
816 while (i
++ < sizeof(int))
817 *p
++ = 0x90; /* nop */
818 *p
++ = 0xC7; /* movl $1, 0(%esp) */
827 case NETF_OP(NETF_NEQ
):
829 * *sp = (*sp != arg);
834 * Pad to longword boundary (cf dissas).
836 if (i
= ((pend
- (unsigned char *)0) &
838 pend
+= (sizeof(int) - i
);
842 *p
++ = 0x39; /* cmpl (%esp), %ecx */
846 i
= ((p
- (unsigned char *)top
) + 11) &
848 *p
++ = 0x75; /* jne .+9+<pad> */
849 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
850 *p
++ = 0xC7; /* movl $0, 0(%esp) */
858 i
= ((p
- (unsigned char *)top
) + 2) &
860 *p
++ = 0xEB; /* jmp .+7+<pad> */
861 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
864 * Pad to longword boundary (cf dissas).
866 if (i
= (p
- (unsigned char *)top
) &
868 while (i
++ < sizeof(int))
869 *p
++ = 0x90; /* nop */
870 *p
++ = 0xC7; /* movl $1, 0(%esp) */
879 case NETF_OP(NETF_LT
):
886 * Pad to longword boundary (cf dissas).
888 if (i
= ((pend
- (unsigned char *)0) &
890 pend
+= (sizeof(int) - i
);
894 *p
++ = 0x39; /* cmpl (%esp), %ecx */
898 i
= ((p
- (unsigned char *)top
) + 11) &
900 *p
++ = 0x7C; /* jl .+9+<pad> */
901 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
902 *p
++ = 0xC7; /* movl $0, 0(%esp) */
910 i
= ((p
- (unsigned char *)top
) + 2) &
912 *p
++ = 0xEB; /* jmp .+7+<pad> */
913 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
916 * Pad to longword boundary (cf dissas).
918 if (i
= (p
- (unsigned char *)top
) &
920 while (i
++ < sizeof(int))
921 *p
++ = 0x90; /* nop */
922 *p
++ = 0xC7; /* movl $1, 0(%esp) */
931 case NETF_OP(NETF_LE
):
933 * *sp = (*sp <= arg);
938 * Pad to longword boundary (cf dissas).
940 if (i
= ((pend
- (unsigned char *)0) &
942 pend
+= (sizeof(int) - i
);
946 *p
++ = 0x39; /* cmpl (%esp), %ecx */
950 i
= ((p
- (unsigned char *)top
) + 11) &
952 *p
++ = 0x7E; /* jle .+9+<pad> */
953 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
954 *p
++ = 0xC7; /* movl $0, 0(%esp) */
962 i
= ((p
- (unsigned char *)top
) + 2) &
964 *p
++ = 0xEB; /* jmp .+7+<pad> */
965 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
968 * Pad to longword boundary (cf dissas).
970 if (i
= (p
- (unsigned char *)top
) &
972 while (i
++ < sizeof(int))
973 *p
++ = 0x90; /* nop */
974 *p
++ = 0xC7; /* movl $1, 0(%esp) */
983 case NETF_OP(NETF_GT
):
990 * Pad to longword boundary (cf dissas).
992 if (i
= ((pend
- (unsigned char *)0) &
994 pend
+= (sizeof(int) - i
);
998 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1002 i
= ((p
- (unsigned char *)top
) + 11) &
1004 *p
++ = 0x7F; /* jg .+9+<pad> */
1005 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1006 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1014 i
= ((p
- (unsigned char *)top
) + 2) &
1016 *p
++ = 0xEB; /* jmp .+7+<pad> */
1017 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1020 * Pad to longword boundary (cf dissas).
1022 if (i
= (p
- (unsigned char *)top
) &
1024 while (i
++ < sizeof(int))
1025 *p
++ = 0x90; /* nop */
1026 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1035 case NETF_OP(NETF_GE
):
1037 * *sp = (*sp >= arg);
1042 * Pad to longword boundary (cf dissas).
1044 if (i
= ((pend
- (unsigned char *)0) &
1046 pend
+= (sizeof(int) - i
);
1050 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1054 i
= ((p
- (unsigned char *)top
) + 11) &
1056 *p
++ = 0x7D; /* jge .+9+<pad> */
1057 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1058 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1066 i
= ((p
- (unsigned char *)top
) + 2) &
1068 *p
++ = 0xEB; /* jmp .+7+<pad> */
1069 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1072 * Pad to longword boundary (cf dissas).
1074 if (i
= (p
- (unsigned char *)top
) &
1076 while (i
++ < sizeof(int))
1077 *p
++ = 0x90; /* nop */
1078 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1087 case NETF_OP(NETF_COR
):
1094 PEND_TRUE
- (pend
+ 5) >= 128)
1101 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1105 if (PEND_TRUE
- (p
+ 2) >= 128) {
1106 *p
++ = 0x0F; /* je end_true */
1108 *(p
+0) = PEND_TRUE
- (p
+ 4);
1109 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1110 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1111 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1115 *p
++ = 0x74; /* je end_true */
1116 *p
= PEND_TRUE
- (p
+ 1);
1120 *p
++ = 0x83; /* addl $4, %esp */
1125 case NETF_OP(NETF_CAND
):
1132 PEND_FALSE
- (pend
+ 5) >= 128)
1139 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1143 if (PEND_FALSE
- (p
+ 2) >= 128) {
1144 *p
++ = 0x0F; /* jne end_false */
1146 *(p
+0) = PEND_FALSE
- (p
+ 4);
1147 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1148 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1149 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1153 *p
++ = 0x75; /* jne end_false */
1154 *p
= PEND_FALSE
- (p
+ 1);
1158 *p
++ = 0x83; /* addl $4, %esp */
1163 case NETF_OP(NETF_CNOR
):
1170 PEND_FALSE
- (pend
+ 5) >= 128)
1177 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1181 if (PEND_FALSE
- (p
+ 2) >= 128) {
1182 *p
++ = 0x0F; /* je end_false */
1184 *(p
+0) = PEND_FALSE
- (p
+ 4);
1185 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1186 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1187 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1190 *p
++ = 0x74; /* je end_false */
1191 *p
= PEND_FALSE
- (p
+ 1);
1195 *p
++ = 0x83; /* addl $4, %esp */
1200 case NETF_OP(NETF_CNAND
):
1207 PEND_TRUE
- (pend
+ 5) >= 128)
1214 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1218 if (PEND_TRUE
- (p
+ 2) >= 128) {
1219 *p
++ = 0x0F; /* jne end_true */
1221 *(p
+0) = PEND_TRUE
- (p
+ 4);
1222 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1223 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1224 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1228 *p
++ = 0x75; /* jne end_true */
1229 *p
= PEND_TRUE
- (p
+ 1);
1233 *p
++ = 0x83; /* addl $4, %esp */
1238 case NETF_OP(NETF_LSH
):
1245 *p
++ = 0xD3; /* sall (%esp), %cl */
1251 case NETF_OP(NETF_RSH
):
1258 *p
++ = 0xD3; /* sarl (%esp), %cl */
1264 case NETF_OP(NETF_ADD
):
1271 *p
++ = 0x01; /* addl (%esp), %ecx */
1277 case NETF_OP(NETF_SUB
):
1284 *p
++ = 0x29; /* subl (%esp), %ecx */
1293 * return ((*sp) ? TRUE : FALSE);
1302 * Pad to longword boundary (cf dissas).
1304 i
= (pend
- (unsigned char *)0) & (sizeof(int) - 1);
1305 false_pad
= i
? sizeof(int) - i
: 0;
1306 pend
+= 4 + push
+ false_pad
;
1309 *p
++ = 0x83; /* cmpl %ecx, $0 */
1314 *p
++ = 0x83; /* cmpl (%esp), $0 */
1320 i
= ((p
- (unsigned char *)top
) + 9) &
1322 false_pad
= i
? sizeof(int) - i
: 0;
1323 *p
++ = 0x74; /* je end_false */
1324 *p
++ = 0x07 + false_pad
;
1326 *p
++ = 0xB8; /* movl $1, %eax */
1332 *p
++ = 0xEB; /* jmp .+2+<pad> */
1333 *p
++ = 0x02 + false_pad
;
1336 * Pad to longword boundary (cf dissas).
1338 for (i
= 0; i
< false_pad
; i
++)
1339 *p
++ = 0x90; /* nop */
1340 *p
++ = 0x31; /* xorl %eax, %eax */
1343 *p
++ = 0x8D; /* leal -<push>(%ebx), %esp */
1345 *p
++ = -((push
- 3) * 4);
1347 if (reg
[NET_REG_EDI
] >= 0)
1348 *p
++ = 0x5F; /* pop %edi */
1349 if (reg
[NET_REG_ESI
] >= 0)
1350 *p
++ = 0x5E; /* pop %esi */
1351 if (reg
[NET_REG_EBX
] >= 0)
1352 *p
++ = 0x5B; /* pop %ebx */
1353 *p
++ = 0xC9; /* leave */
1354 *p
++ = 0xC3; /* ret */
1358 * Prepare next loop if any.
1363 if (loop
== 1 && pend
== pend_old
) {
1365 *len
= pend
- (unsigned char *)0;
1366 top
= (filter_fct_t
)kalloc(*len
);
1367 p
= (unsigned char *)top
;
1368 pend_old
= p
+ (pend
- (unsigned char *)0);
1373 * Compute and optimize free registers usage.
1375 for (i
= 0; i
< NET_REG_MAX
; i
++)
1378 reg
[NET_REG_EAX
] = -2;
1380 reg
[NET_REG_EDX
] = -2;
1381 net_filter_optimize(net_o
, net_j
,
1387 for (i
= 0; i
< NET_REG_MAX
; i
++)
1399 kfree((vm_offset_t
)fp
, len
);
1403 * Try to compute how to use (if needed) extra registers to store
1404 * values read more than once.
1406 * Input : net_o is an array of used values (only .val is valid).
1407 * net_len is the length of net_o.
1408 * reg is an array of available registers (-2 ==> used register).
1409 * nbreg is the maximum number of registers.
1411 * Output : net_o is an array of register usage.
1412 * .used == 0 ==> do not used any register.
1413 * .used >= 2 ==> how many times the .reg register
1415 * reg is an array of used registers.
1416 * == -2 ==> unused or unavailable register.
1417 * >= 0 ==> used register.
1419 * N.B. This procedure is completely machine-independent and should take place
1420 * in a file of the device directory.
1423 net_filter_optimize(
1424 struct net_opt net_o
[],
1441 for (i
= 0; i
< nbreg
; i
++)
1448 * First step: set up used field.
1450 p
= &net_o
[net_len
];
1451 while (p
!= net_o
) {
1452 for (q
= p
--; q
< &net_o
[net_len
]; q
++)
1453 if (q
->val
== p
->val
) {
1454 p
->used
= q
->used
+ 1;
1457 if (q
== &net_o
[net_len
])
1462 * Second step: choose best register and update used field.
1465 if (net_o
[0].used
== 1)
1466 used
= net_o
[0].used
= 0;
1472 for (p
= &net_o
[1]; p
< &net_o
[net_len
]; p
++) {
1475 for (i
= 0; i
< avail
; i
++) {
1478 while (q
-- != net_o
)
1479 if (q
->used
> 0 && q
->reg
== i
) {
1488 if (q
->val
== p
->val
) {
1496 if (first
== avail
&& used
== avail
) {
1498 for (q
= p
+1; q
->val
!= p
->val
; p
++)
1512 else if (used
< avail
)
1522 * Third step: associate correct register number and keep max value.
1524 for (p
= net_o
; p
< &net_o
[net_len
]; p
++) {
1530 if (first
== p
->reg
) {
1541 * Forth step: invalidate useless registers.
1544 for (i
= 0; i
< nbreg
; i
++)
1548 } else if (used
< avail
) {
1550 for (i
= 0; i
< nbreg
; i
++)