2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 * Mach Operating System
28 * Copyright (c) 1993 Carnegie Mellon University
29 * All Rights Reserved.
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 * Carnegie Mellon requests users of this software to return to
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
52 #include <kern/zalloc.h>
54 #define NET_REG_EAX 0 /* data segment register */
55 #define NET_REG_EDX 1 /* header segment register */
56 #define NET_REG_EBX 2 /* free register */
57 #define NET_REG_ESI 3 /* free register */
58 #define NET_REG_EDI 4 /* free register */
59 #define NET_REG_MAX 5 /* number of available registers */
62 filter_t val
; /* value */
63 unsigned char reg
; /* register associated */
64 unsigned char used
; /* how many times it will be used */
67 boolean_t net_filter_enable
= FALSE
;
70 * Forward declarations.
72 void net_filter_optimize(
73 struct net_opt net_o
[],
79 * Compilation of a source network filter into i386 instructions.
93 unsigned char *pend_old
;
95 unsigned int use_header
;
96 unsigned int use_data
;
97 unsigned int push_ecx
;
99 struct net_opt net_o
[NET_MAX_FILTER
];
108 * Addresses of end_true and end_false from the end of the program.
110 #define PEND_TRUE (pend_old - (11 + push + false_pad))
111 #define PEND_FALSE (pend_old - (4 + push))
114 * Don't produce anything if net_filter generation is not enabled.
116 if (!net_filter_enable
) {
118 return ((filter_fct_t
)0);
122 * called as (*filter)(data, data_count, header)
126 * %eax -> data (if needed);
127 * %edx -> header (if needed);
130 p
= (unsigned char *)0;
135 false_pad
= sizeof(int) - 1;
138 * The compiler needs 3 passes to produce the compiled net_filter:
139 * 0) compute without optimization the maximum size of the object
141 * 1) try to reduce the size of the object procedure (many runs),
142 * 2) produce final object code (one run).
148 else if (loop
== 1) {
149 if (reg
[NET_REG_EBX
] == -1) {
150 /* push and pop it */
155 if (reg
[NET_REG_ESI
] == -1) {
156 /* push and pop it */
160 if (reg
[NET_REG_EDI
] == -1) {
161 /* push and pop it */
177 *p
++ = 0x55; /* pushl %ebp */
178 *p
++ = 0x89; /* movl %esp, %ebp */
180 if (reg
[NET_REG_EBX
] == -1)
181 *p
++ = 0x53; /* pushl %ebx */
182 if (reg
[NET_REG_ESI
] == -1)
183 *p
++ = 0x56; /* pushl %esi */
184 if (reg
[NET_REG_EDI
] == -1)
185 *p
++ = 0x57; /* pushl %edi */
186 *p
++ = 0xB9; /* movl $1, %ecx */
192 *p
++ = 0x8B; /* movl 0x8(%ebp), %eax */
197 *p
++ = 0x8B; /* movl 0x10(%ebp), %edx */
206 while (fp
- fpstart
< fplen
)
224 *p
++ = 0x59; /* popl %ecx */
239 *p
++ = 0x51; /* pushl %ecx */
242 *p
++ = 0x31; /* xorl %ecx, %ecx */
259 *p
++ = 0x51; /* pushl %ecx */
262 *p
++ = 0xB9; /* movl *fp, %ecx */
263 *p
++ = *(unsigned char *)fp
;
264 *p
++ = *(((unsigned char *)fp
) + 1);
274 * if (arg >= data_count)
276 * arg = data_word[arg];
286 PEND_FALSE
- (pend
+ 5) >= 128)
296 *p
++ = 0x59; /* popl %ecx */
297 *p
++ = 0x39; /* cmpl 0xC(%ebp), %ecx */
301 if (PEND_FALSE
- (p
+ 2) >= 128) {
302 *p
++ = 0x0F; /* jle end_false */
304 *(p
+0) = PEND_FALSE
- (p
+ 4);
305 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
306 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
307 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
311 *p
++ = 0x7E; /* jle end_false */
312 *p
= PEND_FALSE
- (p
+ 1);
316 *p
++ = 0x0F; /* movzwl 0(%eax,%ecx,2), %ecx */
323 case NETF_PUSHHDRIND
:
326 * if (arg >= (NET_HDW_HDR_MAX /
327 * sizeof(unsigned short))
329 * arg = header_word[arg];
339 PEND_FALSE
- (pend
+ 8) >= 128)
349 *p
++ = 0x59; /* popl %ecx */
350 *p
++ = 0x81; /* cmpl %ecx, <value> */
352 *p
++ = NET_HDW_HDR_MAX
/
353 sizeof(unsigned short);
354 *p
++ = (NET_HDW_HDR_MAX
/
355 sizeof(unsigned short)) >> 8;
356 *p
++ = (NET_HDW_HDR_MAX
/
357 sizeof(unsigned short)) >> 16;
358 *p
++ = (NET_HDW_HDR_MAX
/
359 sizeof(unsigned short)) >> 24;
361 if (PEND_FALSE
- (p
+ 2) >= 128) {
362 *p
++ = 0x0F; /* jge end_false */
364 *(p
+0) = PEND_FALSE
- (p
+ 4);
365 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
366 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
367 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
371 *p
++ = 0x7D; /* jge end_false */
372 *p
= PEND_FALSE
- (p
+ 1);
376 *p
++ = 0x0F; /* movzwl 0(%edx,%ecx,2), %ecx */
384 if (arg
>= NETF_PUSHSTK
) {
395 pend
+= (arg
< 128) ? 4 : 7;
400 *p
++ = 0x51; /* pushl %ecx */
403 *p
++ = 0x8B; /* movl arg(%esp), %ecx */
417 } else if (arg
>= NETF_PUSHHDR
) {
420 * arg = header_word[arg];
434 assert(net_i
< net_j
);
436 assert(reg
[NET_REG_EDX
]
438 assert(pn
->used
== 0 ||
441 assert(pn
->val
== arg
+
451 pend
+= (arg
< 128) ? 5 : 8;
452 if (loop
== 1 && pn
->used
> 1 &&
454 net_o
[reg
[pn
->reg
]].val
!=
456 reg
[pn
->reg
] = net_i
;
463 *p
++ = 0x51; /* pushl %ecx */
468 assert(net_i
< net_j
);
470 assert(reg
[NET_REG_EDX
] == -2);
471 assert(pn
->used
== 0 ||
473 assert(pn
->val
== arg
+ NETF_PUSHHDR
);
476 net_o
[reg
[pn
->reg
]].val
==
481 /* movl %eax, %ecx */
486 /* movl %ebx, %ecx */
491 /* movl %esi, %ecx */
496 /* movl %edi, %ecx */
503 *p
++ = 0x0F;/* movzwl arg(%edx),%ecx */
519 (reg
[pn
->reg
] == -1 ||
520 net_o
[reg
[pn
->reg
]].val
!=
522 reg
[pn
->reg
] = net_i
;
524 assert(net_o
[net_i
].reg
!=
526 switch (net_o
[net_i
].reg
) {
528 /* movl %ecx, %eax */
532 /* movl %ecx, %ebx */
536 /* movl %ecx, %esi */
540 /* movl %ecx, %edi */
547 arg
-= NETF_PUSHWORD
;
549 * if (arg >= data_count)
551 * arg = data_word[arg];
564 assert(net_i
< net_j
);
566 assert(reg
[NET_REG_EAX
]
568 assert(pn
->used
== 0 ||
571 assert(pn
->val
== arg
+
582 pend
+= (arg
< 128) ? 4 : 7;
594 if (loop
== 1 && pn
->used
> 1 &&
596 net_o
[reg
[pn
->reg
]].val
!=
598 reg
[pn
->reg
] = net_i
;
605 *p
++ = 0x51; /* pushl %ecx */
610 assert(net_i
< net_j
);
612 assert(reg
[NET_REG_EAX
] == -2);
613 assert(pn
->used
== 0 ||
615 assert(pn
->val
== arg
+ NETF_PUSHWORD
);
618 net_o
[reg
[pn
->reg
]].val
==
623 /* movl %edx, %ecx */
628 /* movl %ebx, %ecx */
633 /* movl %esi, %ecx */
638 /* movl %edi, %ecx */
645 /* cmpl 0xC(%ebp), <arg> */
662 if (PEND_FALSE
- (p
+ 2) >= 128) {
663 *p
++ = 0x0F;/* jle end_false */
665 *(p
+0) = PEND_FALSE
- (p
+ 4);
666 *(p
+1) = (PEND_FALSE
- (p
+ 4))
668 *(p
+2) = (PEND_FALSE
- (p
+ 4))
670 *(p
+3) = (PEND_FALSE
- (p
+ 4))
675 *p
++ = 0x7E;/* jle end_false */
676 *p
= PEND_FALSE
- (p
+ 1);
680 *p
++ = 0x0F;/* movzwl arg(%eax),%ecx */
696 (reg
[pn
->reg
] == -1 ||
697 net_o
[reg
[pn
->reg
]].val
!=
699 reg
[pn
->reg
] = net_i
;
701 assert(net_o
[net_i
].reg
!=
703 switch (net_o
[net_i
].reg
) {
705 /* movl %ecx, %edx */
709 /* movl %ecx, %ebx */
713 /* movl %ecx, %esi */
717 /* movl %ecx, %edi */
727 case NETF_OP(NETF_NOP
):
734 case NETF_OP(NETF_AND
):
741 *p
++ = 0x21; /* andl (%esp), %ecx */
747 case NETF_OP(NETF_OR
):
754 *p
++ = 0x09; /* orl (%esp), %ecx */
760 case NETF_OP(NETF_XOR
):
767 *p
++ = 0x31; /* xorl (%esp), %ecx */
773 case NETF_OP(NETF_EQ
):
775 * *sp = (*sp == arg);
780 * Pad to longword boundary (cf dissas).
782 if (i
= ((pend
- (unsigned char *)0) &
784 pend
+= (sizeof(int) - i
);
788 *p
++ = 0x39; /* cmpl (%esp), %ecx */
792 i
= ((p
- (unsigned char *)top
) + 11) &
794 *p
++ = 0x74; /* je .+9+<pad> */
795 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
796 *p
++ = 0xC7; /* movl $0, 0(%esp) */
804 i
= ((p
- (unsigned char *)top
) + 2) &
806 *p
++ = 0xEB; /* jmp .+7+<pad> */
807 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
810 * Pad to longword boundary (cf dissas).
812 if (i
= (p
- (unsigned char *)top
) &
814 while (i
++ < sizeof(int))
815 *p
++ = 0x90; /* nop */
816 *p
++ = 0xC7; /* movl $1, 0(%esp) */
825 case NETF_OP(NETF_NEQ
):
827 * *sp = (*sp != arg);
832 * Pad to longword boundary (cf dissas).
834 if (i
= ((pend
- (unsigned char *)0) &
836 pend
+= (sizeof(int) - i
);
840 *p
++ = 0x39; /* cmpl (%esp), %ecx */
844 i
= ((p
- (unsigned char *)top
) + 11) &
846 *p
++ = 0x75; /* jne .+9+<pad> */
847 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
848 *p
++ = 0xC7; /* movl $0, 0(%esp) */
856 i
= ((p
- (unsigned char *)top
) + 2) &
858 *p
++ = 0xEB; /* jmp .+7+<pad> */
859 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
862 * Pad to longword boundary (cf dissas).
864 if (i
= (p
- (unsigned char *)top
) &
866 while (i
++ < sizeof(int))
867 *p
++ = 0x90; /* nop */
868 *p
++ = 0xC7; /* movl $1, 0(%esp) */
877 case NETF_OP(NETF_LT
):
884 * Pad to longword boundary (cf dissas).
886 if (i
= ((pend
- (unsigned char *)0) &
888 pend
+= (sizeof(int) - i
);
892 *p
++ = 0x39; /* cmpl (%esp), %ecx */
896 i
= ((p
- (unsigned char *)top
) + 11) &
898 *p
++ = 0x7C; /* jl .+9+<pad> */
899 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
900 *p
++ = 0xC7; /* movl $0, 0(%esp) */
908 i
= ((p
- (unsigned char *)top
) + 2) &
910 *p
++ = 0xEB; /* jmp .+7+<pad> */
911 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
914 * Pad to longword boundary (cf dissas).
916 if (i
= (p
- (unsigned char *)top
) &
918 while (i
++ < sizeof(int))
919 *p
++ = 0x90; /* nop */
920 *p
++ = 0xC7; /* movl $1, 0(%esp) */
929 case NETF_OP(NETF_LE
):
931 * *sp = (*sp <= arg);
936 * Pad to longword boundary (cf dissas).
938 if (i
= ((pend
- (unsigned char *)0) &
940 pend
+= (sizeof(int) - i
);
944 *p
++ = 0x39; /* cmpl (%esp), %ecx */
948 i
= ((p
- (unsigned char *)top
) + 11) &
950 *p
++ = 0x7E; /* jle .+9+<pad> */
951 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
952 *p
++ = 0xC7; /* movl $0, 0(%esp) */
960 i
= ((p
- (unsigned char *)top
) + 2) &
962 *p
++ = 0xEB; /* jmp .+7+<pad> */
963 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
966 * Pad to longword boundary (cf dissas).
968 if (i
= (p
- (unsigned char *)top
) &
970 while (i
++ < sizeof(int))
971 *p
++ = 0x90; /* nop */
972 *p
++ = 0xC7; /* movl $1, 0(%esp) */
981 case NETF_OP(NETF_GT
):
988 * Pad to longword boundary (cf dissas).
990 if (i
= ((pend
- (unsigned char *)0) &
992 pend
+= (sizeof(int) - i
);
996 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1000 i
= ((p
- (unsigned char *)top
) + 11) &
1002 *p
++ = 0x7F; /* jg .+9+<pad> */
1003 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1004 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1012 i
= ((p
- (unsigned char *)top
) + 2) &
1014 *p
++ = 0xEB; /* jmp .+7+<pad> */
1015 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1018 * Pad to longword boundary (cf dissas).
1020 if (i
= (p
- (unsigned char *)top
) &
1022 while (i
++ < sizeof(int))
1023 *p
++ = 0x90; /* nop */
1024 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1033 case NETF_OP(NETF_GE
):
1035 * *sp = (*sp >= arg);
1040 * Pad to longword boundary (cf dissas).
1042 if (i
= ((pend
- (unsigned char *)0) &
1044 pend
+= (sizeof(int) - i
);
1048 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1052 i
= ((p
- (unsigned char *)top
) + 11) &
1054 *p
++ = 0x7D; /* jge .+9+<pad> */
1055 *p
++ = 0x09 + (i
? sizeof(int) - i
: 0);
1056 *p
++ = 0xC7; /* movl $0, 0(%esp) */
1064 i
= ((p
- (unsigned char *)top
) + 2) &
1066 *p
++ = 0xEB; /* jmp .+7+<pad> */
1067 *p
++ = 0x07 + (i
? sizeof(int) - i
: 0);
1070 * Pad to longword boundary (cf dissas).
1072 if (i
= (p
- (unsigned char *)top
) &
1074 while (i
++ < sizeof(int))
1075 *p
++ = 0x90; /* nop */
1076 *p
++ = 0xC7; /* movl $1, 0(%esp) */
1085 case NETF_OP(NETF_COR
):
1092 PEND_TRUE
- (pend
+ 5) >= 128)
1099 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1103 if (PEND_TRUE
- (p
+ 2) >= 128) {
1104 *p
++ = 0x0F; /* je end_true */
1106 *(p
+0) = PEND_TRUE
- (p
+ 4);
1107 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1108 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1109 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1113 *p
++ = 0x74; /* je end_true */
1114 *p
= PEND_TRUE
- (p
+ 1);
1118 *p
++ = 0x83; /* addl $4, %esp */
1123 case NETF_OP(NETF_CAND
):
1130 PEND_FALSE
- (pend
+ 5) >= 128)
1137 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1141 if (PEND_FALSE
- (p
+ 2) >= 128) {
1142 *p
++ = 0x0F; /* jne end_false */
1144 *(p
+0) = PEND_FALSE
- (p
+ 4);
1145 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1146 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1147 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1151 *p
++ = 0x75; /* jne end_false */
1152 *p
= PEND_FALSE
- (p
+ 1);
1156 *p
++ = 0x83; /* addl $4, %esp */
1161 case NETF_OP(NETF_CNOR
):
1168 PEND_FALSE
- (pend
+ 5) >= 128)
1175 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1179 if (PEND_FALSE
- (p
+ 2) >= 128) {
1180 *p
++ = 0x0F; /* je end_false */
1182 *(p
+0) = PEND_FALSE
- (p
+ 4);
1183 *(p
+1) = (PEND_FALSE
- (p
+ 4)) >> 8;
1184 *(p
+2) = (PEND_FALSE
- (p
+ 4)) >> 16;
1185 *(p
+3) = (PEND_FALSE
- (p
+ 4)) >> 24;
1188 *p
++ = 0x74; /* je end_false */
1189 *p
= PEND_FALSE
- (p
+ 1);
1193 *p
++ = 0x83; /* addl $4, %esp */
1198 case NETF_OP(NETF_CNAND
):
1205 PEND_TRUE
- (pend
+ 5) >= 128)
1212 *p
++ = 0x39; /* cmpl (%esp), %ecx */
1216 if (PEND_TRUE
- (p
+ 2) >= 128) {
1217 *p
++ = 0x0F; /* jne end_true */
1219 *(p
+0) = PEND_TRUE
- (p
+ 4);
1220 *(p
+1) = (PEND_TRUE
- (p
+ 4)) >> 8;
1221 *(p
+2) = (PEND_TRUE
- (p
+ 4)) >> 16;
1222 *(p
+3) = (PEND_TRUE
- (p
+ 4)) >> 24;
1226 *p
++ = 0x75; /* jne end_true */
1227 *p
= PEND_TRUE
- (p
+ 1);
1231 *p
++ = 0x83; /* addl $4, %esp */
1236 case NETF_OP(NETF_LSH
):
1243 *p
++ = 0xD3; /* sall (%esp), %cl */
1249 case NETF_OP(NETF_RSH
):
1256 *p
++ = 0xD3; /* sarl (%esp), %cl */
1262 case NETF_OP(NETF_ADD
):
1269 *p
++ = 0x01; /* addl (%esp), %ecx */
1275 case NETF_OP(NETF_SUB
):
1282 *p
++ = 0x29; /* subl (%esp), %ecx */
1291 * return ((*sp) ? TRUE : FALSE);
1300 * Pad to longword boundary (cf dissas).
1302 i
= (pend
- (unsigned char *)0) & (sizeof(int) - 1);
1303 false_pad
= i
? sizeof(int) - i
: 0;
1304 pend
+= 4 + push
+ false_pad
;
1307 *p
++ = 0x83; /* cmpl %ecx, $0 */
1312 *p
++ = 0x83; /* cmpl (%esp), $0 */
1318 i
= ((p
- (unsigned char *)top
) + 9) &
1320 false_pad
= i
? sizeof(int) - i
: 0;
1321 *p
++ = 0x74; /* je end_false */
1322 *p
++ = 0x07 + false_pad
;
1324 *p
++ = 0xB8; /* movl $1, %eax */
1330 *p
++ = 0xEB; /* jmp .+2+<pad> */
1331 *p
++ = 0x02 + false_pad
;
1334 * Pad to longword boundary (cf dissas).
1336 for (i
= 0; i
< false_pad
; i
++)
1337 *p
++ = 0x90; /* nop */
1338 *p
++ = 0x31; /* xorl %eax, %eax */
1341 *p
++ = 0x8D; /* leal -<push>(%ebx), %esp */
1343 *p
++ = -((push
- 3) * 4);
1345 if (reg
[NET_REG_EDI
] >= 0)
1346 *p
++ = 0x5F; /* pop %edi */
1347 if (reg
[NET_REG_ESI
] >= 0)
1348 *p
++ = 0x5E; /* pop %esi */
1349 if (reg
[NET_REG_EBX
] >= 0)
1350 *p
++ = 0x5B; /* pop %ebx */
1351 *p
++ = 0xC9; /* leave */
1352 *p
++ = 0xC3; /* ret */
1356 * Prepare next loop if any.
1361 if (loop
== 1 && pend
== pend_old
) {
1363 *len
= pend
- (unsigned char *)0;
1364 top
= (filter_fct_t
)kalloc(*len
);
1365 p
= (unsigned char *)top
;
1366 pend_old
= p
+ (pend
- (unsigned char *)0);
1371 * Compute and optimize free registers usage.
1373 for (i
= 0; i
< NET_REG_MAX
; i
++)
1376 reg
[NET_REG_EAX
] = -2;
1378 reg
[NET_REG_EDX
] = -2;
1379 net_filter_optimize(net_o
, net_j
,
1385 for (i
= 0; i
< NET_REG_MAX
; i
++)
1397 kfree((vm_offset_t
)fp
, len
);
1401 * Try to compute how to use (if needed) extra registers to store
1402 * values read more than once.
1404 * Input : net_o is an array of used values (only .val is valid).
1405 * net_len is the length of net_o.
1406 * reg is an array of available registers (-2 ==> used register).
1407 * nbreg is the maximum number of registers.
1409 * Output : net_o is an array of register usage.
1410 * .used == 0 ==> do not used any register.
1411 * .used >= 2 ==> how many times the .reg register
1413 * reg is an array of used registers.
1414 * == -2 ==> unused or unavailable register.
1415 * >= 0 ==> used register.
1417 * N.B. This procedure is completely machine-independent and should take place
1418 * in a file of the device directory.
1421 net_filter_optimize(
1422 struct net_opt net_o
[],
1439 for (i
= 0; i
< nbreg
; i
++)
1446 * First step: set up used field.
1448 p
= &net_o
[net_len
];
1449 while (p
!= net_o
) {
1450 for (q
= p
--; q
< &net_o
[net_len
]; q
++)
1451 if (q
->val
== p
->val
) {
1452 p
->used
= q
->used
+ 1;
1455 if (q
== &net_o
[net_len
])
1460 * Second step: choose best register and update used field.
1463 if (net_o
[0].used
== 1)
1464 used
= net_o
[0].used
= 0;
1470 for (p
= &net_o
[1]; p
< &net_o
[net_len
]; p
++) {
1473 for (i
= 0; i
< avail
; i
++) {
1476 while (q
-- != net_o
)
1477 if (q
->used
> 0 && q
->reg
== i
) {
1486 if (q
->val
== p
->val
) {
1494 if (first
== avail
&& used
== avail
) {
1496 for (q
= p
+1; q
->val
!= p
->val
; p
++)
1510 else if (used
< avail
)
1520 * Third step: associate correct register number and keep max value.
1522 for (p
= net_o
; p
< &net_o
[net_len
]; p
++) {
1528 if (first
== p
->reg
) {
1539 * Forth step: invalidate useless registers.
1542 for (i
= 0; i
< nbreg
; i
++)
1546 } else if (used
< avail
) {
1548 for (i
= 0; i
< nbreg
; i
++)