2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1993 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
51 #include <kern/zalloc.h>
53 #define NET_REG_EAX 0 /* data segment register */
54 #define NET_REG_EDX 1 /* header segment register */
55 #define NET_REG_EBX 2 /* free register */
56 #define NET_REG_ESI 3 /* free register */
57 #define NET_REG_EDI 4 /* free register */
58 #define NET_REG_MAX 5 /* number of available registers */
61 filter_t val
; /* value */
62 unsigned char reg
; /* register associated */
63 unsigned char used
; /* how many times it will be used */
66 boolean_t net_filter_enable
= FALSE
;
69 * Forward declarations.
71 void net_filter_optimize(
72 struct net_opt net_o
[],
78 * Compilation of a source network filter into i386 instructions.
92 unsigned char *pend_old
;
94 unsigned int use_header
;
95 unsigned int use_data
;
96 unsigned int push_ecx
;
98 struct net_opt net_o
[NET_MAX_FILTER
];
107 * Addresses of end_true and end_false from the end of the program.
109 #define PEND_TRUE (pend_old - (11 + push + false_pad))
110 #define PEND_FALSE (pend_old - (4 + push))
113 * Don't produce anything if net_filter generation is not enabled.
115 if (!net_filter_enable
) {
117 return ((filter_fct_t
)0);
121 * called as (*filter)(data, data_count, header)
125 * %eax -> data (if needed);
126 * %edx -> header (if needed);
129 p
= (unsigned char *)0;
134 false_pad
= sizeof(int) - 1;
137 * The compiler needs 3 passes to produce the compiled net_filter:
138 * 0) compute without optimization the maximum size of the object
140 * 1) try to reduce the size of the object procedure (many runs),
141 * 2) produce final object code (one run).
147 else if (loop
== 1) {
148 if (reg
[NET_REG_EBX
] == -1) {
149 /* push and pop it */
154 if (reg
[NET_REG_ESI
] == -1) {
155 /* push and pop it */
159 if (reg
[NET_REG_EDI
] == -1) {
160 /* push and pop it */
176 *p
++ = 0x55; /* pushl %ebp */
177 *p
++ = 0x89; /* movl %esp, %ebp */
179 if (reg
[NET_REG_EBX
] == -1)
180 *p
++ = 0x53; /* pushl %ebx */
181 if (reg
[NET_REG_ESI
] == -1)
182 *p
++ = 0x56; /* pushl %esi */
183 if (reg
[NET_REG_EDI
] == -1)
184 *p
++ = 0x57; /* pushl %edi */
185 *p
++ = 0xB9; /* movl $1, %ecx */
191 *p
++ = 0x8B; /* movl 0x8(%ebp), %eax */
196 *p
++ = 0x8B; /* movl 0x10(%ebp), %edx */
205 while (fp
- fpstart
< fplen
)
223 *p
++ = 0x59; /* popl %ecx */
238 *p
++ = 0x51; /* pushl %ecx */
241 *p
++ = 0x31; /* xorl %ecx, %ecx */
258 *p
++ = 0x51; /* pushl %ecx */
261 *p
++ = 0xB9; /* movl *fp, %ecx */
262 *p
++ = *(unsigned char *)fp
;
263 *p
++ = *(((unsigned char *)fp
) + 1);
273 * if (arg >= data_count)
275 * arg = data_word[arg];
285 PEND_FALSE
- (pend
+ 5) >= 128)
295 *p
++ = 0x59; /* popl %ecx */
296 *p
++ = 0x39; /* cmpl 0xC(%ebp), %ecx */
300 if (PEND_FALSE
- (p
+ 2) >= 128) {
301 *p
++ = 0x0F; /* jle end_false */
303 *(p
+0) = PEND_FALSE
- (p
+ 4);
304 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
305 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
306 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
310 *p
++ = 0x7E; /* jle end_false */
311 *p
= PEND_FALSE
- (p
+ 1);
315 *p
++ = 0x0F; /* movzwl 0(%eax,%ecx,2), %ecx */
322 case NETF_PUSHHDRIND
:
325 * if (arg >= (NET_HDW_HDR_MAX /
326 * sizeof(unsigned short))
328 * arg = header_word[arg];
338 PEND_FALSE
- (pend
+ 8) >= 128)
348 *p
++ = 0x59; /* popl %ecx */
349 *p
++ = 0x81; /* cmpl %ecx, <value> */
351 *p
++ = NET_HDW_HDR_MAX
/
352 sizeof(unsigned short);
353 *p
++ = (NET_HDW_HDR_MAX
/
354 sizeof(unsigned short)) >> 8;
355 *p
++ = (NET_HDW_HDR_MAX
/
356 sizeof(unsigned short)) >> 16;
357 *p
++ = (NET_HDW_HDR_MAX
/
358 sizeof(unsigned short)) >> 24;
360 if (PEND_FALSE
- (p
+ 2) >= 128) {
361 *p
++ = 0x0F; /* jge end_false */
363 *(p
+0) = PEND_FALSE
- (p
+ 4);
364 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
365 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
366 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
370 *p
++ = 0x7D; /* jge end_false */
371 *p
= PEND_FALSE
- (p
+ 1);
375 *p
++ = 0x0F; /* movzwl 0(%edx,%ecx,2), %ecx */
383 if (arg
>= NETF_PUSHSTK
) {
394 pend
+= (arg
< 128) ? 4 : 7;
399 *p
++ = 0x51; /* pushl %ecx */
402 *p
++ = 0x8B; /* movl arg(%esp), %ecx */
416 } else if (arg
>= NETF_PUSHHDR
) {
419 * arg = header_word[arg];
433 assert(net_i
< net_j
);
435 assert(reg
[NET_REG_EDX
]
437 assert(pn
->used
== 0 ||
440 assert(pn
->val
== arg
+
450 pend
+= (arg
< 128) ? 5 : 8;
451 if (loop
== 1 && pn
->used
> 1 &&
453 net_o
[reg
[pn
->reg
]].val
!=
455 reg
[pn
->reg
] = net_i
;
462 *p
++ = 0x51; /* pushl %ecx */
467 assert(net_i
< net_j
);
469 assert(reg
[NET_REG_EDX
] == -2);
470 assert(pn
->used
== 0 ||
472 assert(pn
->val
== arg
+ NETF_PUSHHDR
);
475 net_o
[reg
[pn
->reg
]].val
==
480 /* movl %eax, %ecx */
485 /* movl %ebx, %ecx */
490 /* movl %esi, %ecx */
495 /* movl %edi, %ecx */
502 *p
++ = 0x0F;/* movzwl arg(%edx),%ecx */
518 (reg
[pn
->reg
] == -1 ||
519 net_o
[reg
[pn
->reg
]].val
!=
521 reg
[pn
->reg
] = net_i
;
523 assert(net_o
[net_i
].reg
!=
525 switch (net_o
[net_i
].reg
) {
527 /* movl %ecx, %eax */
531 /* movl %ecx, %ebx */
535 /* movl %ecx, %esi */
539 /* movl %ecx, %edi */
546 arg
-= NETF_PUSHWORD
;
548 * if (arg >= data_count)
550 * arg = data_word[arg];
563 assert(net_i
< net_j
);
565 assert(reg
[NET_REG_EAX
]
567 assert(pn
->used
== 0 ||
570 assert(pn
->val
== arg
+
581 pend
+= (arg
< 128) ? 4 : 7;
593 if (loop
== 1 && pn
->used
> 1 &&
595 net_o
[reg
[pn
->reg
]].val
!=
597 reg
[pn
->reg
] = net_i
;
604 *p
++ = 0x51; /* pushl %ecx */
609 assert(net_i
< net_j
);
611 assert(reg
[NET_REG_EAX
] == -2);
612 assert(pn
->used
== 0 ||
614 assert(pn
->val
== arg
+ NETF_PUSHWORD
);
617 net_o
[reg
[pn
->reg
]].val
==
622 /* movl %edx, %ecx */
627 /* movl %ebx, %ecx */
632 /* movl %esi, %ecx */
637 /* movl %edi, %ecx */
644 /* cmpl 0xC(%ebp), <arg> */
661 if (PEND_FALSE
- (p
+ 2) >= 128) {
662 *p
++ = 0x0F;/* jle end_false */
664 *(p
+0) = PEND_FALSE
- (p
+ 4);
665 *(p
+1) = (PEND_FALSE
- (p
+ 4))
667 *(p
+2) = (PEND_FALSE
- (p
+ 4))
669 *(p
+3) = (PEND_FALSE
- (p
+ 4))
674 *p
++ = 0x7E;/* jle end_false */
675 *p
= PEND_FALSE
- (p
+ 1);
679 *p
++ = 0x0F;/* movzwl arg(%eax),%ecx */
695 (reg
[pn
->reg
] == -1 ||
696 net_o
[reg
[pn
->reg
]].val
!=
698 reg
[pn
->reg
] = net_i
;
700 assert(net_o
[net_i
].reg
!=
702 switch (net_o
[net_i
].reg
) {
704 /* movl %ecx, %edx */
708 /* movl %ecx, %ebx */
712 /* movl %ecx, %esi */
716 /* movl %ecx, %edi */
726 case NETF_OP(NETF_NOP
):
733 case NETF_OP(NETF_AND
):
740 *p
++ = 0x21; /* andl (%esp), %ecx */
746 case NETF_OP(NETF_OR
):
753 *p
++ = 0x09; /* orl (%esp), %ecx */
759 case NETF_OP(NETF_XOR
):
766 *p
++ = 0x31; /* xorl (%esp), %ecx */
772 case NETF_OP(NETF_EQ
):
774 * *sp = (*sp == arg);
779 * Pad to longword boundary (cf dissas).
781 if (i
= ((pend
- (unsigned char *)0) &
783 pend
+= (sizeof(int) - i
);
787 *p
++ = 0x39; /* cmpl (%esp), %ecx */
791 i
= ((p
- (unsigned char *)top
) + 11) &
793 *p
++ = 0x74; /* je .+9+<pad> */
794 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
795 *p
++ = 0xC7; /* movl $0, 0(%esp) */
803 i
= ((p
- (unsigned char *)top
) + 2) &
805 *p
++ = 0xEB; /* jmp .+7+<pad> */
806 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
809 * Pad to longword boundary (cf dissas).
811 if (i
= (p
- (unsigned char *)top
) &
813 while (i
++ < sizeof(int))
814 *p
++ = 0x90; /* nop */
815 *p
++ = 0xC7; /* movl $1, 0(%esp) */
824 case NETF_OP(NETF_NEQ
):
826 * *sp = (*sp != arg);
831 * Pad to longword boundary (cf dissas).
833 if (i
= ((pend
- (unsigned char *)0) &
835 pend
+= (sizeof(int) - i
);
839 *p
++ = 0x39; /* cmpl (%esp), %ecx */
843 i
= ((p
- (unsigned char *)top
) + 11) &
845 *p
++ = 0x75; /* jne .+9+<pad> */
846 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
847 *p
++ = 0xC7; /* movl $0, 0(%esp) */
855 i
= ((p
- (unsigned char *)top
) + 2) &
857 *p
++ = 0xEB; /* jmp .+7+<pad> */
858 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
861 * Pad to longword boundary (cf dissas).
863 if (i
= (p
- (unsigned char *)top
) &
865 while (i
++ < sizeof(int))
866 *p
++ = 0x90; /* nop */
867 *p
++ = 0xC7; /* movl $1, 0(%esp) */
876 case NETF_OP(NETF_LT
):
883 * Pad to longword boundary (cf dissas).
885 if (i
= ((pend
- (unsigned char *)0) &
887 pend
+= (sizeof(int) - i
);
891 *p
++ = 0x39; /* cmpl (%esp), %ecx */
895 i
= ((p
- (unsigned char *)top
) + 11) &
897 *p
++ = 0x7C; /* jl .+9+<pad> */
898 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
899 *p
++ = 0xC7; /* movl $0, 0(%esp) */
907 i
= ((p
- (unsigned char *)top
) + 2) &
909 *p
++ = 0xEB; /* jmp .+7+<pad> */
910 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
913 * Pad to longword boundary (cf dissas).
915 if (i
= (p
- (unsigned char *)top
) &
917 while (i
++ < sizeof(int))
918 *p
++ = 0x90; /* nop */
919 *p
++ = 0xC7; /* movl $1, 0(%esp) */
928 case NETF_OP(NETF_LE
):
930 * *sp = (*sp <= arg);
935 * Pad to longword boundary (cf dissas).
937 if (i
= ((pend
- (unsigned char *)0) &
939 pend
+= (sizeof(int) - i
);
943 *p
++ = 0x39; /* cmpl (%esp), %ecx */
947 i
= ((p
- (unsigned char *)top
) + 11) &
949 *p
++ = 0x7E; /* jle .+9+<pad> */
950 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
951 *p
++ = 0xC7; /* movl $0, 0(%esp) */
959 i
= ((p
- (unsigned char *)top
) + 2) &
961 *p
++ = 0xEB; /* jmp .+7+<pad> */
962 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
965 * Pad to longword boundary (cf dissas).
967 if (i
= (p
- (unsigned char *)top
) &
969 while (i
++ < sizeof(int))
970 *p
++ = 0x90; /* nop */
971 *p
++ = 0xC7; /* movl $1, 0(%esp) */
980 case NETF_OP(NETF_GT
):
987 * Pad to longword boundary (cf dissas).
989 if (i
= ((pend
- (unsigned char *)0) &
991 pend
+= (sizeof(int) - i
);
995 *p
++ = 0x39; /* cmpl (%esp), %ecx */
999 i
= ((p
- (unsigned char *)top
) + 11) &
1001 *p
++ = 0x7F; /* jg .+9+<pad> */
1002 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1003 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1011 i
= ((p
- (unsigned char *)top
) + 2) &
1013 *p
++ = 0xEB; /* jmp .+7+<pad> */
1014 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1017 * Pad to longword boundary (cf dissas).
1019 if (i
= (p
- (unsigned char *)top
) &
1021 while (i
++ < sizeof(int))
1022 *p
++ = 0x90; /* nop */
1023 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1032 case NETF_OP(NETF_GE
):
1034 * *sp = (*sp >= arg);
1039 * Pad to longword boundary (cf dissas).
1041 if (i
= ((pend
- (unsigned char *)0) &
1043 pend
+= (sizeof(int) - i
);
1047 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1051 i
= ((p
- (unsigned char *)top
) + 11) &
1053 *p
++ = 0x7D; /* jge .+9+<pad> */
1054 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1055 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1063 i
= ((p
- (unsigned char *)top
) + 2) &
1065 *p
++ = 0xEB; /* jmp .+7+<pad> */
1066 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1069 * Pad to longword boundary (cf dissas).
1071 if (i
= (p
- (unsigned char *)top
) &
1073 while (i
++ < sizeof(int))
1074 *p
++ = 0x90; /* nop */
1075 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1084 case NETF_OP(NETF_COR
):
1091 PEND_TRUE
- (pend
+ 5) >= 128)
1098 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1102 if (PEND_TRUE
- (p
+ 2) >= 128) {
1103 *p
++ = 0x0F; /* je end_true */
1105 *(p
+0) = PEND_TRUE
- (p
+ 4);
1106 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1107 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1108 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1112 *p
++ = 0x74; /* je end_true */
1113 *p
= PEND_TRUE
- (p
+ 1);
1117 *p
++ = 0x83; /* addl $4, %esp */
1122 case NETF_OP(NETF_CAND
):
1129 PEND_FALSE
- (pend
+ 5) >= 128)
1136 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1140 if (PEND_FALSE
- (p
+ 2) >= 128) {
1141 *p
++ = 0x0F; /* jne end_false */
1143 *(p
+0) = PEND_FALSE
- (p
+ 4);
1144 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1145 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1146 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1150 *p
++ = 0x75; /* jne end_false */
1151 *p
= PEND_FALSE
- (p
+ 1);
1155 *p
++ = 0x83; /* addl $4, %esp */
1160 case NETF_OP(NETF_CNOR
):
1167 PEND_FALSE
- (pend
+ 5) >= 128)
1174 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1178 if (PEND_FALSE
- (p
+ 2) >= 128) {
1179 *p
++ = 0x0F; /* je end_false */
1181 *(p
+0) = PEND_FALSE
- (p
+ 4);
1182 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1183 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1184 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1187 *p
++ = 0x74; /* je end_false */
1188 *p
= PEND_FALSE
- (p
+ 1);
1192 *p
++ = 0x83; /* addl $4, %esp */
1197 case NETF_OP(NETF_CNAND
):
1204 PEND_TRUE
- (pend
+ 5) >= 128)
1211 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1215 if (PEND_TRUE
- (p
+ 2) >= 128) {
1216 *p
++ = 0x0F; /* jne end_true */
1218 *(p
+0) = PEND_TRUE
- (p
+ 4);
1219 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1220 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1221 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1225 *p
++ = 0x75; /* jne end_true */
1226 *p
= PEND_TRUE
- (p
+ 1);
1230 *p
++ = 0x83; /* addl $4, %esp */
1235 case NETF_OP(NETF_LSH
):
1242 *p
++ = 0xD3; /* sall (%esp), %cl */
1248 case NETF_OP(NETF_RSH
):
1255 *p
++ = 0xD3; /* sarl (%esp), %cl */
1261 case NETF_OP(NETF_ADD
):
1268 *p
++ = 0x01; /* addl (%esp), %ecx */
1274 case NETF_OP(NETF_SUB
):
1281 *p
++ = 0x29; /* subl (%esp), %ecx */
1290 * return ((*sp) ? TRUE : FALSE);
1299 * Pad to longword boundary (cf dissas).
1301 i
= (pend
- (unsigned char *)0) & (sizeof(int) - 1);
1302 false_pad
= i
? sizeof(int) - i
: 0;
1303 pend
+= 4 + push
+ false_pad
;
1306 *p
++ = 0x83; /* cmpl %ecx, $0 */
1311 *p
++ = 0x83; /* cmpl (%esp), $0 */
1317 i
= ((p
- (unsigned char *)top
) + 9) &
1319 false_pad
= i
? sizeof(int) - i
: 0;
1320 *p
++ = 0x74; /* je end_false */
1321 *p
++ = 0x07 + false_pad
;
1323 *p
++ = 0xB8; /* movl $1, %eax */
1329 *p
++ = 0xEB; /* jmp .+2+<pad> */
1330 *p
++ = 0x02 + false_pad
;
1333 * Pad to longword boundary (cf dissas).
1335 for (i
= 0; i
< false_pad
; i
++)
1336 *p
++ = 0x90; /* nop */
1337 *p
++ = 0x31; /* xorl %eax, %eax */
1340 *p
++ = 0x8D; /* leal -<push>(%ebx), %esp */
1342 *p
++ = -((push
- 3) * 4);
1344 if (reg
[NET_REG_EDI
] >= 0)
1345 *p
++ = 0x5F; /* pop %edi */
1346 if (reg
[NET_REG_ESI
] >= 0)
1347 *p
++ = 0x5E; /* pop %esi */
1348 if (reg
[NET_REG_EBX
] >= 0)
1349 *p
++ = 0x5B; /* pop %ebx */
1350 *p
++ = 0xC9; /* leave */
1351 *p
++ = 0xC3; /* ret */
1355 * Prepare next loop if any.
1360 if (loop
== 1 && pend
== pend_old
) {
1362 *len
= pend
- (unsigned char *)0;
1363 top
= (filter_fct_t
)kalloc(*len
);
1364 p
= (unsigned char *)top
;
1365 pend_old
= p
+ (pend
- (unsigned char *)0);
1370 * Compute and optimize free registers usage.
1372 for (i
= 0; i
< NET_REG_MAX
; i
++)
1375 reg
[NET_REG_EAX
] = -2;
1377 reg
[NET_REG_EDX
] = -2;
1378 net_filter_optimize(net_o
, net_j
,
1384 for (i
= 0; i
< NET_REG_MAX
; i
++)
1396 kfree((vm_offset_t
)fp
, len
);
1400 * Try to compute how to use (if needed) extra registers to store
1401 * values read more than once.
1403 * Input : net_o is an array of used values (only .val is valid).
1404 * net_len is the length of net_o.
1405 * reg is an array of available registers (-2 ==> used register).
1406 * nbreg is the maximum number of registers.
1408 * Output : net_o is an array of register usage.
1409 * .used == 0 ==> do not used any register.
1410 * .used >= 2 ==> how many times the .reg register
1412 * reg is an array of used registers.
1413 * == -2 ==> unused or unavailable register.
1414 * >= 0 ==> used register.
1416 * N.B. This procedure is completely machine-independent and should take place
1417 * in a file of the device directory.
1420 net_filter_optimize(
1421 struct net_opt net_o
[],
1438 for (i
= 0; i
< nbreg
; i
++)
1445 * First step: set up used field.
1447 p
= &net_o
[net_len
];
1448 while (p
!= net_o
) {
1449 for (q
= p
--; q
< &net_o
[net_len
]; q
++)
1450 if (q
->val
== p
->val
) {
1451 p
->used
= q
->used
+ 1;
1454 if (q
== &net_o
[net_len
])
1459 * Second step: choose best register and update used field.
1462 if (net_o
[0].used
== 1)
1463 used
= net_o
[0].used
= 0;
1469 for (p
= &net_o
[1]; p
< &net_o
[net_len
]; p
++) {
1472 for (i
= 0; i
< avail
; i
++) {
1475 while (q
-- != net_o
)
1476 if (q
->used
> 0 && q
->reg
== i
) {
1485 if (q
->val
== p
->val
) {
1493 if (first
== avail
&& used
== avail
) {
1495 for (q
= p
+1; q
->val
!= p
->val
; p
++)
1509 else if (used
< avail
)
1519 * Third step: associate correct register number and keep max value.
1521 for (p
= net_o
; p
< &net_o
[net_len
]; p
++) {
1527 if (first
== p
->reg
) {
1538 * Forth step: invalidate useless registers.
1541 for (i
= 0; i
< nbreg
; i
++)
1545 } else if (used
< avail
) {
1547 for (i
= 0; i
< nbreg
; i
++)