2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1993 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
57 #include <kern/zalloc.h>
59 #define NET_REG_EAX 0 /* data segment register */
60 #define NET_REG_EDX 1 /* header segment register */
61 #define NET_REG_EBX 2 /* free register */
62 #define NET_REG_ESI 3 /* free register */
63 #define NET_REG_EDI 4 /* free register */
64 #define NET_REG_MAX 5 /* number of available registers */
67 filter_t val
; /* value */
68 unsigned char reg
; /* register associated */
69 unsigned char used
; /* how many times it will be used */
72 boolean_t net_filter_enable
= FALSE
;
75 * Forward declarations.
77 void net_filter_optimize(
78 struct net_opt net_o
[],
84 * Compilation of a source network filter into i386 instructions.
98 unsigned char *pend_old
;
100 unsigned int use_header
;
101 unsigned int use_data
;
102 unsigned int push_ecx
;
103 int reg
[NET_REG_MAX
];
104 struct net_opt net_o
[NET_MAX_FILTER
];
113 * Addresses of end_true and end_false from the end of the program.
115 #define PEND_TRUE (pend_old - (11 + push + false_pad))
116 #define PEND_FALSE (pend_old - (4 + push))
119 * Don't produce anything if net_filter generation is not enabled.
121 if (!net_filter_enable
) {
123 return ((filter_fct_t
)0);
127 * called as (*filter)(data, data_count, header)
131 * %eax -> data (if needed);
132 * %edx -> header (if needed);
135 p
= (unsigned char *)0;
140 false_pad
= sizeof(int) - 1;
143 * The compiler needs 3 passes to produce the compiled net_filter:
144 * 0) compute without optimization the maximum size of the object
146 * 1) try to reduce the size of the object procedure (many runs),
147 * 2) produce final object code (one run).
153 else if (loop
== 1) {
154 if (reg
[NET_REG_EBX
] == -1) {
155 /* push and pop it */
160 if (reg
[NET_REG_ESI
] == -1) {
161 /* push and pop it */
165 if (reg
[NET_REG_EDI
] == -1) {
166 /* push and pop it */
182 *p
++ = 0x55; /* pushl %ebp */
183 *p
++ = 0x89; /* movl %esp, %ebp */
185 if (reg
[NET_REG_EBX
] == -1)
186 *p
++ = 0x53; /* pushl %ebx */
187 if (reg
[NET_REG_ESI
] == -1)
188 *p
++ = 0x56; /* pushl %esi */
189 if (reg
[NET_REG_EDI
] == -1)
190 *p
++ = 0x57; /* pushl %edi */
191 *p
++ = 0xB9; /* movl $1, %ecx */
197 *p
++ = 0x8B; /* movl 0x8(%ebp), %eax */
202 *p
++ = 0x8B; /* movl 0x10(%ebp), %edx */
211 while (fp
- fpstart
< fplen
)
229 *p
++ = 0x59; /* popl %ecx */
244 *p
++ = 0x51; /* pushl %ecx */
247 *p
++ = 0x31; /* xorl %ecx, %ecx */
264 *p
++ = 0x51; /* pushl %ecx */
267 *p
++ = 0xB9; /* movl *fp, %ecx */
268 *p
++ = *(unsigned char *)fp
;
269 *p
++ = *(((unsigned char *)fp
) + 1);
279 * if (arg >= data_count)
281 * arg = data_word[arg];
291 PEND_FALSE
- (pend
+ 5) >= 128)
301 *p
++ = 0x59; /* popl %ecx */
302 *p
++ = 0x39; /* cmpl 0xC(%ebp), %ecx */
306 if (PEND_FALSE
- (p
+ 2) >= 128) {
307 *p
++ = 0x0F; /* jle end_false */
309 *(p
+0) = PEND_FALSE
- (p
+ 4);
310 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
311 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
312 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
316 *p
++ = 0x7E; /* jle end_false */
317 *p
= PEND_FALSE
- (p
+ 1);
321 *p
++ = 0x0F; /* movzwl 0(%eax,%ecx,2), %ecx */
328 case NETF_PUSHHDRIND
:
331 * if (arg >= (NET_HDW_HDR_MAX /
332 * sizeof(unsigned short))
334 * arg = header_word[arg];
344 PEND_FALSE
- (pend
+ 8) >= 128)
354 *p
++ = 0x59; /* popl %ecx */
355 *p
++ = 0x81; /* cmpl %ecx, <value> */
357 *p
++ = NET_HDW_HDR_MAX
/
358 sizeof(unsigned short);
359 *p
++ = (NET_HDW_HDR_MAX
/
360 sizeof(unsigned short)) >> 8;
361 *p
++ = (NET_HDW_HDR_MAX
/
362 sizeof(unsigned short)) >> 16;
363 *p
++ = (NET_HDW_HDR_MAX
/
364 sizeof(unsigned short)) >> 24;
366 if (PEND_FALSE
- (p
+ 2) >= 128) {
367 *p
++ = 0x0F; /* jge end_false */
369 *(p
+0) = PEND_FALSE
- (p
+ 4);
370 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
371 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
372 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
376 *p
++ = 0x7D; /* jge end_false */
377 *p
= PEND_FALSE
- (p
+ 1);
381 *p
++ = 0x0F; /* movzwl 0(%edx,%ecx,2), %ecx */
389 if (arg
>= NETF_PUSHSTK
) {
400 pend
+= (arg
< 128) ? 4 : 7;
405 *p
++ = 0x51; /* pushl %ecx */
408 *p
++ = 0x8B; /* movl arg(%esp), %ecx */
422 } else if (arg
>= NETF_PUSHHDR
) {
425 * arg = header_word[arg];
439 assert(net_i
< net_j
);
441 assert(reg
[NET_REG_EDX
]
443 assert(pn
->used
== 0 ||
446 assert(pn
->val
== arg
+
456 pend
+= (arg
< 128) ? 5 : 8;
457 if (loop
== 1 && pn
->used
> 1 &&
459 net_o
[reg
[pn
->reg
]].val
!=
461 reg
[pn
->reg
] = net_i
;
468 *p
++ = 0x51; /* pushl %ecx */
473 assert(net_i
< net_j
);
475 assert(reg
[NET_REG_EDX
] == -2);
476 assert(pn
->used
== 0 ||
478 assert(pn
->val
== arg
+ NETF_PUSHHDR
);
481 net_o
[reg
[pn
->reg
]].val
==
486 /* movl %eax, %ecx */
491 /* movl %ebx, %ecx */
496 /* movl %esi, %ecx */
501 /* movl %edi, %ecx */
508 *p
++ = 0x0F;/* movzwl arg(%edx),%ecx */
524 (reg
[pn
->reg
] == -1 ||
525 net_o
[reg
[pn
->reg
]].val
!=
527 reg
[pn
->reg
] = net_i
;
529 assert(net_o
[net_i
].reg
!=
531 switch (net_o
[net_i
].reg
) {
533 /* movl %ecx, %eax */
537 /* movl %ecx, %ebx */
541 /* movl %ecx, %esi */
545 /* movl %ecx, %edi */
552 arg
-= NETF_PUSHWORD
;
554 * if (arg >= data_count)
556 * arg = data_word[arg];
569 assert(net_i
< net_j
);
571 assert(reg
[NET_REG_EAX
]
573 assert(pn
->used
== 0 ||
576 assert(pn
->val
== arg
+
587 pend
+= (arg
< 128) ? 4 : 7;
599 if (loop
== 1 && pn
->used
> 1 &&
601 net_o
[reg
[pn
->reg
]].val
!=
603 reg
[pn
->reg
] = net_i
;
610 *p
++ = 0x51; /* pushl %ecx */
615 assert(net_i
< net_j
);
617 assert(reg
[NET_REG_EAX
] == -2);
618 assert(pn
->used
== 0 ||
620 assert(pn
->val
== arg
+ NETF_PUSHWORD
);
623 net_o
[reg
[pn
->reg
]].val
==
628 /* movl %edx, %ecx */
633 /* movl %ebx, %ecx */
638 /* movl %esi, %ecx */
643 /* movl %edi, %ecx */
650 /* cmpl 0xC(%ebp), <arg> */
667 if (PEND_FALSE
- (p
+ 2) >= 128) {
668 *p
++ = 0x0F;/* jle end_false */
670 *(p
+0) = PEND_FALSE
- (p
+ 4);
671 *(p
+1) = (PEND_FALSE
- (p
+ 4))
673 *(p
+2) = (PEND_FALSE
- (p
+ 4))
675 *(p
+3) = (PEND_FALSE
- (p
+ 4))
680 *p
++ = 0x7E;/* jle end_false */
681 *p
= PEND_FALSE
- (p
+ 1);
685 *p
++ = 0x0F;/* movzwl arg(%eax),%ecx */
701 (reg
[pn
->reg
] == -1 ||
702 net_o
[reg
[pn
->reg
]].val
!=
704 reg
[pn
->reg
] = net_i
;
706 assert(net_o
[net_i
].reg
!=
708 switch (net_o
[net_i
].reg
) {
710 /* movl %ecx, %edx */
714 /* movl %ecx, %ebx */
718 /* movl %ecx, %esi */
722 /* movl %ecx, %edi */
732 case NETF_OP(NETF_NOP
):
739 case NETF_OP(NETF_AND
):
746 *p
++ = 0x21; /* andl (%esp), %ecx */
752 case NETF_OP(NETF_OR
):
759 *p
++ = 0x09; /* orl (%esp), %ecx */
765 case NETF_OP(NETF_XOR
):
772 *p
++ = 0x31; /* xorl (%esp), %ecx */
778 case NETF_OP(NETF_EQ
):
780 * *sp = (*sp == arg);
785 * Pad to longword boundary (cf dissas).
787 if (i
= ((pend
- (unsigned char *)0) &
789 pend
+= (sizeof(int) - i
);
793 *p
++ = 0x39; /* cmpl (%esp), %ecx */
797 i
= ((p
- (unsigned char *)top
) + 11) &
799 *p
++ = 0x74; /* je .+9+<pad> */
800 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
801 *p
++ = 0xC7; /* movl $0, 0(%esp) */
809 i
= ((p
- (unsigned char *)top
) + 2) &
811 *p
++ = 0xEB; /* jmp .+7+<pad> */
812 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
815 * Pad to longword boundary (cf dissas).
817 if (i
= (p
- (unsigned char *)top
) &
819 while (i
++ < sizeof(int))
820 *p
++ = 0x90; /* nop */
821 *p
++ = 0xC7; /* movl $1, 0(%esp) */
830 case NETF_OP(NETF_NEQ
):
832 * *sp = (*sp != arg);
837 * Pad to longword boundary (cf dissas).
839 if (i
= ((pend
- (unsigned char *)0) &
841 pend
+= (sizeof(int) - i
);
845 *p
++ = 0x39; /* cmpl (%esp), %ecx */
849 i
= ((p
- (unsigned char *)top
) + 11) &
851 *p
++ = 0x75; /* jne .+9+<pad> */
852 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
853 *p
++ = 0xC7; /* movl $0, 0(%esp) */
861 i
= ((p
- (unsigned char *)top
) + 2) &
863 *p
++ = 0xEB; /* jmp .+7+<pad> */
864 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
867 * Pad to longword boundary (cf dissas).
869 if (i
= (p
- (unsigned char *)top
) &
871 while (i
++ < sizeof(int))
872 *p
++ = 0x90; /* nop */
873 *p
++ = 0xC7; /* movl $1, 0(%esp) */
882 case NETF_OP(NETF_LT
):
889 * Pad to longword boundary (cf dissas).
891 if (i
= ((pend
- (unsigned char *)0) &
893 pend
+= (sizeof(int) - i
);
897 *p
++ = 0x39; /* cmpl (%esp), %ecx */
901 i
= ((p
- (unsigned char *)top
) + 11) &
903 *p
++ = 0x7C; /* jl .+9+<pad> */
904 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
905 *p
++ = 0xC7; /* movl $0, 0(%esp) */
913 i
= ((p
- (unsigned char *)top
) + 2) &
915 *p
++ = 0xEB; /* jmp .+7+<pad> */
916 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
919 * Pad to longword boundary (cf dissas).
921 if (i
= (p
- (unsigned char *)top
) &
923 while (i
++ < sizeof(int))
924 *p
++ = 0x90; /* nop */
925 *p
++ = 0xC7; /* movl $1, 0(%esp) */
934 case NETF_OP(NETF_LE
):
936 * *sp = (*sp <= arg);
941 * Pad to longword boundary (cf dissas).
943 if (i
= ((pend
- (unsigned char *)0) &
945 pend
+= (sizeof(int) - i
);
949 *p
++ = 0x39; /* cmpl (%esp), %ecx */
953 i
= ((p
- (unsigned char *)top
) + 11) &
955 *p
++ = 0x7E; /* jle .+9+<pad> */
956 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
957 *p
++ = 0xC7; /* movl $0, 0(%esp) */
965 i
= ((p
- (unsigned char *)top
) + 2) &
967 *p
++ = 0xEB; /* jmp .+7+<pad> */
968 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
971 * Pad to longword boundary (cf dissas).
973 if (i
= (p
- (unsigned char *)top
) &
975 while (i
++ < sizeof(int))
976 *p
++ = 0x90; /* nop */
977 *p
++ = 0xC7; /* movl $1, 0(%esp) */
986 case NETF_OP(NETF_GT
):
993 * Pad to longword boundary (cf dissas).
995 if (i
= ((pend
- (unsigned char *)0) &
997 pend
+= (sizeof(int) - i
);
1001 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1005 i
= ((p
- (unsigned char *)top
) + 11) &
1007 *p
++ = 0x7F; /* jg .+9+<pad> */
1008 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1009 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1017 i
= ((p
- (unsigned char *)top
) + 2) &
1019 *p
++ = 0xEB; /* jmp .+7+<pad> */
1020 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1023 * Pad to longword boundary (cf dissas).
1025 if (i
= (p
- (unsigned char *)top
) &
1027 while (i
++ < sizeof(int))
1028 *p
++ = 0x90; /* nop */
1029 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1038 case NETF_OP(NETF_GE
):
1040 * *sp = (*sp >= arg);
1045 * Pad to longword boundary (cf dissas).
1047 if (i
= ((pend
- (unsigned char *)0) &
1049 pend
+= (sizeof(int) - i
);
1053 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1057 i
= ((p
- (unsigned char *)top
) + 11) &
1059 *p
++ = 0x7D; /* jge .+9+<pad> */
1060 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1061 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1069 i
= ((p
- (unsigned char *)top
) + 2) &
1071 *p
++ = 0xEB; /* jmp .+7+<pad> */
1072 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1075 * Pad to longword boundary (cf dissas).
1077 if (i
= (p
- (unsigned char *)top
) &
1079 while (i
++ < sizeof(int))
1080 *p
++ = 0x90; /* nop */
1081 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1090 case NETF_OP(NETF_COR
):
1097 PEND_TRUE
- (pend
+ 5) >= 128)
1104 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1108 if (PEND_TRUE
- (p
+ 2) >= 128) {
1109 *p
++ = 0x0F; /* je end_true */
1111 *(p
+0) = PEND_TRUE
- (p
+ 4);
1112 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1113 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1114 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1118 *p
++ = 0x74; /* je end_true */
1119 *p
= PEND_TRUE
- (p
+ 1);
1123 *p
++ = 0x83; /* addl $4, %esp */
1128 case NETF_OP(NETF_CAND
):
1135 PEND_FALSE
- (pend
+ 5) >= 128)
1142 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1146 if (PEND_FALSE
- (p
+ 2) >= 128) {
1147 *p
++ = 0x0F; /* jne end_false */
1149 *(p
+0) = PEND_FALSE
- (p
+ 4);
1150 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1151 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1152 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1156 *p
++ = 0x75; /* jne end_false */
1157 *p
= PEND_FALSE
- (p
+ 1);
1161 *p
++ = 0x83; /* addl $4, %esp */
1166 case NETF_OP(NETF_CNOR
):
1173 PEND_FALSE
- (pend
+ 5) >= 128)
1180 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1184 if (PEND_FALSE
- (p
+ 2) >= 128) {
1185 *p
++ = 0x0F; /* je end_false */
1187 *(p
+0) = PEND_FALSE
- (p
+ 4);
1188 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1189 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1190 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1193 *p
++ = 0x74; /* je end_false */
1194 *p
= PEND_FALSE
- (p
+ 1);
1198 *p
++ = 0x83; /* addl $4, %esp */
1203 case NETF_OP(NETF_CNAND
):
1210 PEND_TRUE
- (pend
+ 5) >= 128)
1217 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1221 if (PEND_TRUE
- (p
+ 2) >= 128) {
1222 *p
++ = 0x0F; /* jne end_true */
1224 *(p
+0) = PEND_TRUE
- (p
+ 4);
1225 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1226 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1227 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1231 *p
++ = 0x75; /* jne end_true */
1232 *p
= PEND_TRUE
- (p
+ 1);
1236 *p
++ = 0x83; /* addl $4, %esp */
1241 case NETF_OP(NETF_LSH
):
1248 *p
++ = 0xD3; /* sall (%esp), %cl */
1254 case NETF_OP(NETF_RSH
):
1261 *p
++ = 0xD3; /* sarl (%esp), %cl */
1267 case NETF_OP(NETF_ADD
):
1274 *p
++ = 0x01; /* addl (%esp), %ecx */
1280 case NETF_OP(NETF_SUB
):
1287 *p
++ = 0x29; /* subl (%esp), %ecx */
1296 * return ((*sp) ? TRUE : FALSE);
1305 * Pad to longword boundary (cf dissas).
1307 i
= (pend
- (unsigned char *)0) & (sizeof(int) - 1);
1308 false_pad
= i
? sizeof(int) - i
: 0;
1309 pend
+= 4 + push
+ false_pad
;
1312 *p
++ = 0x83; /* cmpl %ecx, $0 */
1317 *p
++ = 0x83; /* cmpl (%esp), $0 */
1323 i
= ((p
- (unsigned char *)top
) + 9) &
1325 false_pad
= i
? sizeof(int) - i
: 0;
1326 *p
++ = 0x74; /* je end_false */
1327 *p
++ = 0x07 + false_pad
;
1329 *p
++ = 0xB8; /* movl $1, %eax */
1335 *p
++ = 0xEB; /* jmp .+2+<pad> */
1336 *p
++ = 0x02 + false_pad
;
1339 * Pad to longword boundary (cf dissas).
1341 for (i
= 0; i
< false_pad
; i
++)
1342 *p
++ = 0x90; /* nop */
1343 *p
++ = 0x31; /* xorl %eax, %eax */
1346 *p
++ = 0x8D; /* leal -<push>(%ebx), %esp */
1348 *p
++ = -((push
- 3) * 4);
1350 if (reg
[NET_REG_EDI
] >= 0)
1351 *p
++ = 0x5F; /* pop %edi */
1352 if (reg
[NET_REG_ESI
] >= 0)
1353 *p
++ = 0x5E; /* pop %esi */
1354 if (reg
[NET_REG_EBX
] >= 0)
1355 *p
++ = 0x5B; /* pop %ebx */
1356 *p
++ = 0xC9; /* leave */
1357 *p
++ = 0xC3; /* ret */
1361 * Prepare next loop if any.
1366 if (loop
== 1 && pend
== pend_old
) {
1368 *len
= pend
- (unsigned char *)0;
1369 top
= (filter_fct_t
)kalloc(*len
);
1370 p
= (unsigned char *)top
;
1371 pend_old
= p
+ (pend
- (unsigned char *)0);
1376 * Compute and optimize free registers usage.
1378 for (i
= 0; i
< NET_REG_MAX
; i
++)
1381 reg
[NET_REG_EAX
] = -2;
1383 reg
[NET_REG_EDX
] = -2;
1384 net_filter_optimize(net_o
, net_j
,
1390 for (i
= 0; i
< NET_REG_MAX
; i
++)
1402 kfree((vm_offset_t
)fp
, len
);
1406 * Try to compute how to use (if needed) extra registers to store
1407 * values read more than once.
1409 * Input : net_o is an array of used values (only .val is valid).
1410 * net_len is the length of net_o.
1411 * reg is an array of available registers (-2 ==> used register).
1412 * nbreg is the maximum number of registers.
1414 * Output : net_o is an array of register usage.
1415 * .used == 0 ==> do not used any register.
1416 * .used >= 2 ==> how many times the .reg register
1418 * reg is an array of used registers.
1419 * == -2 ==> unused or unavailable register.
1420 * >= 0 ==> used register.
1422 * N.B. This procedure is completely machine-independent and should take place
1423 * in a file of the device directory.
1426 net_filter_optimize(
1427 struct net_opt net_o
[],
1444 for (i
= 0; i
< nbreg
; i
++)
1451 * First step: set up used field.
1453 p
= &net_o
[net_len
];
1454 while (p
!= net_o
) {
1455 for (q
= p
--; q
< &net_o
[net_len
]; q
++)
1456 if (q
->val
== p
->val
) {
1457 p
->used
= q
->used
+ 1;
1460 if (q
== &net_o
[net_len
])
1465 * Second step: choose best register and update used field.
1468 if (net_o
[0].used
== 1)
1469 used
= net_o
[0].used
= 0;
1475 for (p
= &net_o
[1]; p
< &net_o
[net_len
]; p
++) {
1478 for (i
= 0; i
< avail
; i
++) {
1481 while (q
-- != net_o
)
1482 if (q
->used
> 0 && q
->reg
== i
) {
1491 if (q
->val
== p
->val
) {
1499 if (first
== avail
&& used
== avail
) {
1501 for (q
= p
+1; q
->val
!= p
->val
; p
++)
1515 else if (used
< avail
)
1525 * Third step: associate correct register number and keep max value.
1527 for (p
= net_o
; p
< &net_o
[net_len
]; p
++) {
1533 if (first
== p
->reg
) {
1544 * Forth step: invalidate useless registers.
1547 for (i
= 0; i
< nbreg
; i
++)
1551 } else if (used
< avail
) {
1553 for (i
= 0; i
< nbreg
; i
++)