The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/osfmk/i386/net_filter.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    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
   13  * file.
   14  * 
   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.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * @OSF_COPYRIGHT@
   27  */
   28 /* 
   29  * Mach Operating System
   30  * Copyright (c) 1993 Carnegie Mellon University
   31  * All Rights Reserved.
   32  * 
   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.
   38  * 
   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.
   42  * 
   43  * Carnegie Mellon requests users of this software to return to
   44  * 
   45  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   46  *  School of Computer Science
   47  *  Carnegie Mellon University
   48  *  Pittsburgh PA 15213-3890
   49  * 
   50  * any improvements or extensions that they make and grant Carnegie Mellon
   51  * the rights to redistribute these changes.
   52  */
   53 
   54 #include <kern/zalloc.h>
   55 
   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 */
   62 
   63 struct net_opt {
   64         filter_t        val;    /* value */
   65         unsigned char   reg;    /* register associated */
   66         unsigned char   used;   /* how many times it will be used */
   67 };
   68 
   69 boolean_t net_filter_enable = FALSE;
   70 
   71 /*
   72  * Forward declarations.
   73  */
   74 void net_filter_optimize(
   75         struct net_opt  net_o[],
   76         unsigned        net_len,
   77         int             reg[],
   78         unsigned        nbreg);
   79 
   80 /*
   81  *      Compilation of a source network filter into i386 instructions.
   82  */
   83 filter_fct_t
   84 net_filter_alloc(
   85         filter_t        *fpstart,
   86         unsigned int    fplen,
   87         unsigned int    *len)
   88 {
   89         filter_t        *fp;
   90         unsigned int    op;
   91         unsigned int    arg;
   92         unsigned char   *p;
   93         filter_fct_t    top;
   94         unsigned char   *pend;
   95         unsigned char   *pend_old;
   96         unsigned int    loop;
   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];
  102         int             net_i;
  103         unsigned        net_j;
  104         unsigned        i;
  105         unsigned        push;
  106         unsigned        false_pad;
  107         struct net_opt  *pn;
  108 
  109         /*
  110          * Addresses of end_true and end_false from the end of the program.
  111          */
  112 #define PEND_TRUE       (pend_old - (11 + push + false_pad))
  113 #define PEND_FALSE      (pend_old - (4 + push))
  114 
  115         /*
  116          * Don't produce anything if net_filter generation is not enabled.
  117          */
  118         if (!net_filter_enable) {
  119                 *len = 0;
  120                 return ((filter_fct_t)0);
  121         }
  122 
  123         /*
  124          * called as (*filter)(data, data_count, header)
  125          *
  126          * %esp -> stack;
  127          * %ecx -> arg;
  128          * %eax -> data (if needed);
  129          * %edx -> header (if needed);
  130          */
  131         loop = 0;
  132         p = (unsigned char *)0;
  133         pend = 0;
  134         use_header = 0;
  135         use_data = 0;
  136         net_j = 0;
  137         false_pad = sizeof(int) - 1;
  138 
  139         /*
  140          * The compiler needs 3 passes to produce the compiled net_filter:
  141          * 0) compute without optimization the maximum size of the object
  142          *      routine (one run),
  143          * 1) try to reduce the size of the object procedure (many runs),
  144          * 2) produce final object code (one run).
  145          */
  146         for (;;) {
  147                 if (loop == 0)
  148                         pend += 14;
  149 
  150                 else if (loop == 1) {
  151                         if (reg[NET_REG_EBX] == -1) {
  152                                 /* push and pop it */
  153                                 pend++;
  154                                 push = 1;
  155                         } else
  156                                 push = 0;
  157                         if (reg[NET_REG_ESI] == -1) {
  158                                 /* push and pop it */
  159                                 pend++;
  160                                 push++;
  161                         }
  162                         if (reg[NET_REG_EDI] == -1) {
  163                                 /* push and pop it */
  164                                 pend++;
  165                                 push++;
  166                         }
  167                         if (push) {
  168                                 /* restore %esp */
  169                                 push += 3;
  170                         }
  171 
  172                         if (use_data)
  173                                 pend += 3;
  174                         if (use_header)
  175                                 pend += 3;
  176                         pend += 8;
  177 
  178                 } else {
  179                         *p++ = 0x55;    /* pushl %ebp */
  180                         *p++ = 0x89;    /* movl %esp, %ebp */
  181                         *p++ = 0xE5;
  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 */
  189                         *p++ = 0x01;
  190                         *p++ = 0x00;
  191                         *p++ = 0x00;
  192                         *p++ = 0x00;
  193                         if (use_data) {
  194                                 *p++ = 0x8B;    /* movl 0x8(%ebp), %eax */
  195                                 *p++ = 0x45;
  196                                 *p++ = 0x08;
  197                         }
  198                         if (use_header) {
  199                                 *p++ = 0x8B;    /* movl 0x10(%ebp), %edx */
  200                                 *p++ = 0x55;
  201                                 *p++ = 0x10;
  202                         }
  203                 }
  204                 push_ecx = 1;
  205                 net_i = -1;
  206 
  207                 fp = fpstart;
  208                 while (fp - fpstart < fplen)
  209                 {
  210                         arg = *fp++;
  211                         op = NETF_OP(arg);
  212                         arg = NETF_ARG(arg);
  213 
  214                         switch (arg) {
  215                         case NETF_NOPUSH:
  216                                 /*
  217                                  * arg = *sp++;
  218                                  */
  219                                 if (push_ecx) {
  220                                         push_ecx = 0;
  221                                         break;
  222                                 }
  223                                 if (loop < 2)
  224                                         pend++;
  225                                 else
  226                                         *p++ = 0x59;    /* popl %ecx */
  227                                 break;
  228 
  229                         case NETF_PUSHZERO:
  230                                 /*
  231                                  * arg = 0;
  232                                  */
  233                                 if (loop < 2) {
  234                                         if (push_ecx) {
  235                                                 pend++;
  236                                                 push_ecx = 0;
  237                                         }
  238                                         pend += 2;
  239                                 } else {
  240                                         if (push_ecx) {
  241                                                 *p++ = 0x51; /* pushl %ecx */
  242                                                 push_ecx = 0;
  243                                         }
  244                                         *p++ = 0x31;    /* xorl %ecx, %ecx */
  245                                         *p++ = 0xC9;
  246                                 }
  247                                 break;
  248 
  249                         case NETF_PUSHLIT:
  250                                 /*
  251                                  * arg = *fp++;
  252                                  */
  253                                 if (loop < 2) {
  254                                         if (push_ecx) {
  255                                                 pend++;
  256                                                 push_ecx = 0;
  257                                         }
  258                                         pend += 5;
  259                                 } else {
  260                                         if (push_ecx) {
  261                                                 *p++ = 0x51; /* pushl %ecx */
  262                                                 push_ecx = 0;
  263                                         }
  264                                         *p++ = 0xB9;    /* movl *fp, %ecx */
  265                                         *p++ = *(unsigned char *)fp;
  266                                         *p++ = *(((unsigned char *)fp) + 1);
  267                                         *p++ = 0x0;
  268                                         *p++ = 0x0;
  269                                 }
  270                                 fp++;
  271                                 break;
  272 
  273                         case NETF_PUSHIND:
  274                                 /*
  275                                  * arg = *sp++;
  276                                  * if (arg >= data_count)
  277                                  *     return FALSE;
  278                                  * arg = data_word[arg];
  279                                  */
  280                                 if (loop < 2) {
  281                                         if (push_ecx)
  282                                                 push_ecx = 0;
  283                                         else
  284                                                 pend++;
  285                                         if (loop == 0)
  286                                                 use_data = 1;
  287                                         if (loop == 0 ||
  288                                             PEND_FALSE - (pend + 5) >= 128)
  289                                                 pend += 14;
  290                                         else
  291                                                 pend += 10;
  292                                         break;
  293                                 }
  294 
  295                                 if (push_ecx)
  296                                         push_ecx = 0;
  297                                 else
  298                                         *p++ = 0x59; /* popl %ecx */
  299                                 *p++ = 0x39; /* cmpl 0xC(%ebp), %ecx */
  300                                 *p++ = 0x4D;
  301                                 *p++ = 0x0C;
  302 
  303                                 if (PEND_FALSE - (p + 2) >= 128) {
  304                                         *p++ = 0x0F;    /* jle end_false */
  305                                         *p++ = 0x8E;
  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;
  310                                         p += 4;
  311 
  312                                 } else {
  313                                         *p++ = 0x7E; /* jle end_false */
  314                                         *p = PEND_FALSE - (p + 1);
  315                                         p++;
  316                                 }
  317 
  318                                 *p++ = 0x0F; /* movzwl 0(%eax,%ecx,2), %ecx */
  319                                 *p++ = 0xB7;
  320                                 *p++ = 0x4C;
  321                                 *p++ = 0x48;
  322                                 *p++ = 0x00;
  323                                 break;
  324 
  325                         case NETF_PUSHHDRIND:
  326                                 /*
  327                                  * arg = *sp++;
  328                                  * if (arg >= (NET_HDW_HDR_MAX /
  329                                  *             sizeof(unsigned short))
  330                                  *     return FALSE;
  331                                  * arg = header_word[arg];
  332                                  */
  333                                 if (loop < 2) {
  334                                         if (push_ecx)
  335                                                 push_ecx = 0;
  336                                         else
  337                                                 pend++;
  338                                         if (loop == 0)
  339                                                 use_header = 1;
  340                                         if (loop == 0 ||
  341                                             PEND_FALSE - (pend + 8) >= 128)
  342                                                 pend += 17;
  343                                         else
  344                                                 pend += 13;
  345                                         break;
  346                                 }
  347 
  348                                 if (push_ecx)
  349                                         push_ecx = 0;
  350                                 else
  351                                         *p++ = 0x59;    /* popl %ecx */
  352                                 *p++ = 0x81;    /* cmpl %ecx, <value> */
  353                                 *p++ = 0xF9;
  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;
  362 
  363                                 if (PEND_FALSE - (p + 2) >= 128) {
  364                                         *p++ = 0x0F;    /* jge end_false */
  365                                         *p++ = 0x8D;
  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;
  370                                         p += 4;
  371 
  372                                 } else {
  373                                         *p++ = 0x7D;    /* jge end_false */
  374                                         *p = PEND_FALSE - (p + 1);
  375                                         p++;
  376                                 }
  377 
  378                                 *p++ = 0x0F; /* movzwl 0(%edx,%ecx,2), %ecx */
  379                                 *p++ = 0xB7;
  380                                 *p++ = 0x4C;
  381                                 *p++ = 0x4A;
  382                                 *p++ = 0x00;
  383                                 break;
  384 
  385                         default:
  386                                 if (arg >= NETF_PUSHSTK) {
  387                                         arg -= NETF_PUSHSTK;
  388                                         /*
  389                                          * arg = sp[arg];
  390                                          */
  391                                         arg <<= 2;
  392                                         if (loop < 2) {
  393                                                 if (push_ecx) {
  394                                                         pend++;
  395                                                         push_ecx = 0;
  396                                                 }
  397                                                 pend += (arg < 128) ? 4 : 7;
  398                                                 break;
  399                                         }
  400 
  401                                         if (push_ecx) {
  402                                                 *p++ = 0x51; /* pushl %ecx */
  403                                                 push_ecx = 0;
  404                                         }
  405                                         *p++ = 0x8B; /* movl arg(%esp), %ecx */
  406                                         if (arg < 128) {
  407                                                 *p++ = 0x4C;
  408                                                 *p++ = 0x24;
  409                                                 *p++ = arg;
  410                                         } else {
  411                                                 *p++ = 0x8C;
  412                                                 *p++ = 0x24;
  413                                                 *p++ = arg;
  414                                                 *p++ = arg >> 8;
  415                                                 *p++ = arg >> 16;
  416                                                 *p++ = arg >> 24;
  417                                         }
  418                                 
  419                                 } else if (arg >= NETF_PUSHHDR) {
  420                                         arg -= NETF_PUSHHDR;
  421                                         /*
  422                                          * arg = header_word[arg];
  423                                          */
  424                                         arg <<= 1;
  425                                         if (loop < 2) {
  426                                                 if (push_ecx) {
  427                                                         pend++;
  428                                                         push_ecx = 0;
  429                                                 }
  430                                                 if (loop == 0) {
  431                                                         use_header = 1;
  432                                                         net_o[net_j++].val =
  433                                                             arg + NETF_PUSHHDR;
  434                                                 } else {
  435                                                         net_i++;
  436                                                         assert(net_i < net_j);
  437                                                         pn = &net_o[net_i];
  438                                                         assert(reg[NET_REG_EDX]
  439                                                                == -2);
  440                                                         assert(pn->used == 0 ||
  441                                                                reg[pn->reg]
  442                                                                != -2);
  443                                                         assert(pn->val == arg +
  444                                                                NETF_PUSHHDR);
  445                                                         if (pn->used > 0 &&
  446                                                             reg[pn->reg] >= 0 &&
  447                                                             net_o[reg[pn->reg]]
  448                                                             .val == pn->val) {
  449                                                                 pend += 2;
  450                                                                 break;
  451                                                         }
  452                                                 }
  453                                                 pend += (arg < 128) ? 5 : 8;
  454                                                 if (loop == 1 && pn->used > 1 &&
  455                                                     (reg[pn->reg] < 0 ||
  456                                                      net_o[reg[pn->reg]].val !=
  457                                                      pn->val)) {
  458                                                         reg[pn->reg] = net_i;
  459                                                         pend += 2;
  460                                                 }
  461                                                 break;
  462                                         }
  463 
  464                                         if (push_ecx) {
  465                                                 *p++ = 0x51; /* pushl %ecx */
  466                                                 push_ecx = 0;
  467                                         }
  468 
  469                                         net_i++;
  470                                         assert(net_i < net_j);
  471                                         pn = &net_o[net_i];
  472                                         assert(reg[NET_REG_EDX] == -2);
  473                                         assert(pn->used == 0 ||
  474                                                reg[pn->reg] != -2);
  475                                         assert(pn->val == arg + NETF_PUSHHDR);
  476                                         if (pn->used > 0 &&
  477                                             reg[pn->reg] >= 0 &&
  478                                             net_o[reg[pn->reg]].val ==
  479                                             pn->val) {
  480                                                 *p++ = 0x89;
  481                                                 switch (pn->reg) {
  482                                                 case NET_REG_EAX:
  483                                                         /* movl %eax, %ecx */
  484                                                         *p++ = 0xC1;
  485                                                         break;
  486 
  487                                                 case NET_REG_EBX:
  488                                                         /* movl %ebx, %ecx */
  489                                                         *p++ = 0xD9;
  490                                                         break;
  491 
  492                                                 case NET_REG_ESI:
  493                                                         /* movl %esi, %ecx */
  494                                                         *p++ = 0xF1;
  495                                                         break;
  496 
  497                                                 case NET_REG_EDI:
  498                                                         /* movl %edi, %ecx */
  499                                                         *p++ = 0xF9;
  500                                                         break;
  501                                                 }
  502                                                 break;
  503                                         }
  504 
  505                                         *p++ = 0x0F;/* movzwl arg(%edx),%ecx */
  506                                         *p++ = 0xB7;
  507                                         if (arg < 128) {
  508                                                 *p++ = 0x4C;
  509                                                 *p++ = 0x22;
  510                                                 *p++ = arg;
  511                                         } else {
  512                                                 *p++ = 0x8C;
  513                                                 *p++ = 0x22;
  514                                                 *p++ = arg;
  515                                                 *p++ = arg >> 8;
  516                                                 *p++ = arg >> 16;
  517                                                 *p++ = arg >> 24;
  518                                         }
  519 
  520                                         if (pn->used > 1 &&
  521                                             (reg[pn->reg] == -1 ||
  522                                              net_o[reg[pn->reg]].val !=
  523                                              pn->val)) {
  524                                                 reg[pn->reg] = net_i;
  525                                                 *p++ = 0x89;
  526                                                 assert(net_o[net_i].reg !=
  527                                                        NET_REG_EDX);
  528                                                 switch (net_o[net_i].reg) {
  529                                                 case NET_REG_EAX:
  530                                                         /* movl %ecx, %eax */
  531                                                         *p++ = 0xC8;
  532                                                         break;
  533                                                 case NET_REG_EBX:
  534                                                         /* movl %ecx, %ebx */
  535                                                         *p++ = 0xCB;
  536                                                         break;
  537                                                 case NET_REG_ESI:
  538                                                         /* movl %ecx, %esi */
  539                                                         *p++ = 0xCE;
  540                                                         break;
  541                                                 case NET_REG_EDI:
  542                                                         /* movl %ecx, %edi */
  543                                                         *p++ = 0xCF;
  544                                                         break;
  545                                                 }
  546                                         }
  547 
  548                                 } else {
  549                                         arg -= NETF_PUSHWORD;
  550                                         /*
  551                                          *     if (arg >= data_count)
  552                                          *         return FALSE;
  553                                          *     arg = data_word[arg];
  554                                          */
  555                                         if (loop < 2) {
  556                                                 if (push_ecx) {
  557                                                         pend++;
  558                                                         push_ecx = 0;
  559                                                 }
  560                                                 if (loop == 0) {
  561                                                         use_data = 1;
  562                                                         net_o[net_j++].val =
  563                                                             arg + NETF_PUSHWORD;
  564                                                 } else {
  565                                                         net_i++;
  566                                                         assert(net_i < net_j);
  567                                                         pn = &net_o[net_i];
  568                                                         assert(reg[NET_REG_EAX]
  569                                                                == -2);
  570                                                         assert(pn->used == 0 ||
  571                                                                reg[pn->reg]
  572                                                                != -2);
  573                                                         assert(pn->val == arg +
  574                                                                NETF_PUSHWORD);
  575                                                         if (pn->used > 0 &&
  576                                                             reg[pn->reg] >= 0 &&
  577                                                             net_o[reg[pn->reg]]
  578                                                             .val == pn->val) {
  579                                                                 pend += 2;
  580                                                                 break;
  581                                                         }
  582                                                 }
  583                                                 arg <<= 1;
  584                                                 pend += (arg < 128) ? 4 : 7;
  585                                                 if (loop == 0 ||
  586                                                     (PEND_FALSE -
  587                                                      (pend + 2)) >= 128)
  588                                                         pend += 6;
  589                                                 else
  590                                                         pend += 2;
  591 
  592                                                 if (arg < 128)
  593                                                         pend += 5;
  594                                                 else
  595                                                         pend += 8;
  596                                                 if (loop == 1 && pn->used > 1 &&
  597                                                     (reg[pn->reg] < 0 ||
  598                                                      net_o[reg[pn->reg]].val !=
  599                                                      pn->val)) {
  600                                                         reg[pn->reg] = net_i;
  601                                                         pend += 2;
  602                                                 }
  603                                                 break;
  604                                         }
  605 
  606                                         if (push_ecx) {
  607                                                 *p++ = 0x51; /* pushl %ecx */
  608                                                 push_ecx = 0;
  609                                         }
  610 
  611                                         net_i++;
  612                                         assert(net_i < net_j);
  613                                         pn = &net_o[net_i];
  614                                         assert(reg[NET_REG_EAX] == -2);
  615                                         assert(pn->used == 0 ||
  616                                                reg[pn->reg] != -2);
  617                                         assert(pn->val == arg + NETF_PUSHWORD);
  618                                         if (pn->used > 0 &&
  619                                             reg[pn->reg] >= 0 &&
  620                                             net_o[reg[pn->reg]].val ==
  621                                             pn->val) {
  622                                                 *p++ = 0x89;
  623                                                 switch (pn->reg) {
  624                                                 case NET_REG_EDX:
  625                                                         /* movl %edx, %ecx */
  626                                                         *p++ = 0xD1;
  627                                                         break;
  628 
  629                                                 case NET_REG_EBX:
  630                                                         /* movl %ebx, %ecx */
  631                                                         *p++ = 0xD9;
  632                                                         break;
  633 
  634                                                 case NET_REG_ESI:
  635                                                         /* movl %esi, %ecx */
  636                                                         *p++ = 0xF1;
  637                                                         break;
  638 
  639                                                 case NET_REG_EDI:
  640                                                         /* movl %edi, %ecx */
  641                                                         *p++ = 0xF9;
  642                                                         break;
  643                                                 }
  644                                                 break;
  645                                         }
  646 
  647                                         /* cmpl 0xC(%ebp), <arg> */
  648                                         arg <<= 1;
  649                                         if (arg < 128) {
  650                                                 *p++ = 0x83;
  651                                                 *p++ = 0x7D;
  652                                                 *p++ = 0x0C;
  653                                                 *p++ = arg;
  654                                         } else {
  655                                                 *p++ = 0x81;
  656                                                 *p++ = 0x7D;
  657                                                 *p++ = 0x0C;
  658                                                 *p++ = arg;
  659                                                 *p++ = arg >> 8;
  660                                                 *p++ = arg >> 16;
  661                                                 *p++ = arg >> 24;
  662                                         }
  663 
  664                                         if (PEND_FALSE - (p + 2) >= 128) {
  665                                                 *p++ = 0x0F;/* jle end_false */
  666                                                 *p++ = 0x8E;
  667                                                 *(p+0) =  PEND_FALSE - (p + 4);
  668                                                 *(p+1) = (PEND_FALSE - (p + 4))
  669                                                           >> 8;
  670                                                 *(p+2) = (PEND_FALSE - (p + 4))
  671                                                           >> 16;
  672                                                 *(p+3) = (PEND_FALSE - (p + 4))
  673                                                           >> 24;
  674                                                 p += 4;
  675 
  676                                         } else {
  677                                                 *p++ = 0x7E;/* jle end_false */
  678                                                 *p = PEND_FALSE - (p + 1);
  679                                                 p++;
  680                                         }
  681 
  682                                         *p++ = 0x0F;/* movzwl arg(%eax),%ecx */
  683                                         *p++ = 0xB7;
  684                                         if (arg < 128) {
  685                                                 *p++ = 0x4C;
  686                                                 *p++ = 0x20;
  687                                                 *p++ = arg;
  688                                         } else {
  689                                                 *p++ = 0x8C;
  690                                                 *p++ = 0x20;
  691                                                 *p++ = arg;
  692                                                 *p++ = arg >> 8;
  693                                                 *p++ = arg >> 16;
  694                                                 *p++ = arg >> 24;
  695                                         }
  696 
  697                                         if (pn->used > 1 &&
  698                                             (reg[pn->reg] == -1 ||
  699                                              net_o[reg[pn->reg]].val !=
  700                                              pn->val)) {
  701                                                 reg[pn->reg] = net_i;
  702                                                 *p++ = 0x89;
  703                                                 assert(net_o[net_i].reg !=
  704                                                        NET_REG_EAX);
  705                                                 switch (net_o[net_i].reg) {
  706                                                 case NET_REG_EDX:
  707                                                         /* movl %ecx, %edx */
  708                                                         *p++ = 0xCA;
  709                                                         break;
  710                                                 case NET_REG_EBX:
  711                                                         /* movl %ecx, %ebx */
  712                                                         *p++ = 0xCB;
  713                                                         break;
  714                                                 case NET_REG_ESI:
  715                                                         /* movl %ecx, %esi */
  716                                                         *p++ = 0xCE;
  717                                                         break;
  718                                                 case NET_REG_EDI:
  719                                                         /* movl %ecx, %edi */
  720                                                         *p++ = 0xCF;
  721                                                         break;
  722                                                 }
  723                                         }
  724                                 }
  725                                 break;
  726                         }
  727 
  728                         switch (op) {
  729                         case NETF_OP(NETF_NOP):
  730                                 /*
  731                                  * *--sp = arg;
  732                                  */
  733                                 push_ecx = 1;
  734                                 break;
  735 
  736                         case NETF_OP(NETF_AND):
  737                                 /*
  738                                  * *sp &= arg;
  739                                  */
  740                                 if (loop < 2)
  741                                         pend += 3;
  742                                 else {
  743                                         *p++ = 0x21;    /* andl (%esp), %ecx */
  744                                         *p++ = 0x0C;
  745                                         *p++ = 0x24;
  746                                 }
  747                                 break;
  748 
  749                         case NETF_OP(NETF_OR):
  750                                 /*
  751                                  * *sp |= arg;
  752                                  */
  753                                 if (loop < 2)
  754                                         pend += 3;
  755                                 else {
  756                                         *p++ = 0x09;    /* orl (%esp), %ecx */
  757                                         *p++ = 0x0C;
  758                                         *p++ = 0x24;
  759                                 }
  760                                 break;
  761 
  762                         case NETF_OP(NETF_XOR):
  763                                 /*
  764                                  * sp ^= arg;
  765                                  */
  766                                 if (loop < 2)
  767                                         pend += 3;
  768                                 else {
  769                                         *p++ = 0x31;    /* xorl (%esp), %ecx */
  770                                         *p++ = 0x0C;
  771                                         *p++ = 0x24;
  772                                 }
  773                                 break;
  774 
  775                         case NETF_OP(NETF_EQ):
  776                                 /*
  777                                  * *sp = (*sp == arg);
  778                                  */
  779                                 if (loop < 2) {
  780                                         pend += 14;
  781                                         /*
  782                                          * Pad to longword boundary (cf dissas).
  783                                          */
  784                                         if (i = ((pend - (unsigned char *)0) &
  785                                                  (sizeof(int) - 1)))
  786                                                 pend += (sizeof(int) - i);
  787                                         pend += 7;
  788                                         break;
  789                                 }
  790                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
  791                                 *p++ = 0x0C;
  792                                 *p++ = 0x24;
  793 
  794                                 i = ((p - (unsigned char *)top) + 11) &
  795                                         (sizeof(int) - 1);
  796                                 *p++ = 0x74;    /* je .+9+<pad> */
  797                                 *p++ = 0x09 + (i ? sizeof(int) - i : 0);
  798                                 *p++ = 0xC7;    /* movl $0, 0(%esp) */
  799                                 *p++ = 0x04;
  800                                 *p++ = 0x24;
  801                                 *p++ = 0x00;
  802                                 *p++ = 0x00;
  803                                 *p++ = 0x00;
  804                                 *p++ = 0x00;
  805 
  806                                 i = ((p - (unsigned char *)top) + 2) &
  807                                         (sizeof(int) - 1);
  808                                 *p++ = 0xEB;    /* jmp .+7+<pad> */
  809                                 *p++ = 0x07 + (i ? sizeof(int) - i : 0);
  810 
  811                                 /*
  812                                  * Pad to longword boundary (cf dissas).
  813                                  */
  814                                 if (i = (p - (unsigned char *)top) &
  815                                     (sizeof(int) - 1))
  816                                         while (i++ < sizeof(int))
  817                                                 *p++ = 0x90; /* nop */
  818                                 *p++ = 0xC7;    /* movl $1, 0(%esp) */
  819                                 *p++ = 0x04;
  820                                 *p++ = 0x24;
  821                                 *p++ = 0x01;
  822                                 *p++ = 0x00;
  823                                 *p++ = 0x00;
  824                                 *p++ = 0x00;
  825                                 break;
  826 
  827                         case NETF_OP(NETF_NEQ):
  828                                 /*
  829                                  * *sp = (*sp != arg);
  830                                  */
  831                                 if (loop < 2) {
  832                                         pend += 14;
  833                                         /*
  834                                          * Pad to longword boundary (cf dissas).
  835                                          */
  836                                         if (i = ((pend - (unsigned char *)0) &
  837                                                  (sizeof(int) - 1)))
  838                                                 pend += (sizeof(int) - i);
  839                                         pend += 7;
  840                                         break;
  841                                 }
  842                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
  843                                 *p++ = 0x0C;
  844                                 *p++ = 0x24;
  845 
  846                                 i = ((p - (unsigned char *)top) + 11) &
  847                                         (sizeof(int) - 1);
  848                                 *p++ = 0x75;    /* jne .+9+<pad> */
  849                                 *p++ = 0x09 + (i ? sizeof(int) - i : 0);
  850                                 *p++ = 0xC7;    /* movl $0, 0(%esp) */
  851                                 *p++ = 0x04;
  852                                 *p++ = 0x24;
  853                                 *p++ = 0x00;
  854                                 *p++ = 0x00;
  855                                 *p++ = 0x00;
  856                                 *p++ = 0x00;
  857 
  858                                 i = ((p - (unsigned char *)top) + 2) &
  859                                         (sizeof(int) - 1);
  860                                 *p++ = 0xEB;    /* jmp .+7+<pad> */
  861                                 *p++ = 0x07 + (i ? sizeof(int) - i : 0);
  862 
  863                                 /*
  864                                  * Pad to longword boundary (cf dissas).
  865                                  */
  866                                 if (i = (p - (unsigned char *)top) &
  867                                     (sizeof(int) - 1))
  868                                         while (i++ < sizeof(int))
  869                                                 *p++ = 0x90; /* nop */
  870                                 *p++ = 0xC7;    /* movl $1, 0(%esp) */
  871                                 *p++ = 0x04;
  872                                 *p++ = 0x24;
  873                                 *p++ = 0x01;
  874                                 *p++ = 0x00;
  875                                 *p++ = 0x00;
  876                                 *p++ = 0x00;
  877                                 break;
  878 
  879                         case NETF_OP(NETF_LT):
  880                                 /*
  881                                  * *sp = (*sp < arg);
  882                                  */
  883                                 if (loop < 2) {
  884                                         pend += 14;
  885                                         /*
  886                                          * Pad to longword boundary (cf dissas).
  887                                          */
  888                                         if (i = ((pend - (unsigned char *)0) &
  889                                                  (sizeof(int) - 1)))
  890                                                 pend += (sizeof(int) - i);
  891                                         pend += 7;
  892                                         break;
  893                                 }
  894                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
  895                                 *p++ = 0x0C;
  896                                 *p++ = 0x24;
  897 
  898                                 i = ((p - (unsigned char *)top) + 11) &
  899                                         (sizeof(int) - 1);
  900                                 *p++ = 0x7C;    /* jl .+9+<pad> */
  901                                 *p++ = 0x09 + (i ? sizeof(int) - i : 0);
  902                                 *p++ = 0xC7;    /* movl $0, 0(%esp) */
  903                                 *p++ = 0x04;
  904                                 *p++ = 0x24;
  905                                 *p++ = 0x00;
  906                                 *p++ = 0x00;
  907                                 *p++ = 0x00;
  908                                 *p++ = 0x00;
  909 
  910                                 i = ((p - (unsigned char *)top) + 2) &
  911                                         (sizeof(int) - 1);
  912                                 *p++ = 0xEB;    /* jmp .+7+<pad> */
  913                                 *p++ = 0x07 + (i ? sizeof(int) - i : 0);
  914 
  915                                 /*
  916                                  * Pad to longword boundary (cf dissas).
  917                                  */
  918                                 if (i = (p - (unsigned char *)top) &
  919                                     (sizeof(int) - 1))
  920                                         while (i++ < sizeof(int))
  921                                                 *p++ = 0x90; /* nop */
  922                                 *p++ = 0xC7;    /* movl $1, 0(%esp) */
  923                                 *p++ = 0x04;
  924                                 *p++ = 0x24;
  925                                 *p++ = 0x01;
  926                                 *p++ = 0x00;
  927                                 *p++ = 0x00;
  928                                 *p++ = 0x00;
  929                                 break;
  930 
  931                         case NETF_OP(NETF_LE):
  932                                 /*
  933                                  * *sp = (*sp <= arg);
  934                                  */
  935                                 if (loop < 2) {
  936                                         pend += 14;
  937                                         /*
  938                                          * Pad to longword boundary (cf dissas).
  939                                          */
  940                                         if (i = ((pend - (unsigned char *)0) &
  941                                                  (sizeof(int) - 1)))
  942                                                 pend += (sizeof(int) - i);
  943                                         pend += 7;
  944                                         break;
  945                                 }
  946                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
  947                                 *p++ = 0x0C;
  948                                 *p++ = 0x24;
  949 
  950                                 i = ((p - (unsigned char *)top) + 11) &
  951                                         (sizeof(int) - 1);
  952                                 *p++ = 0x7E;    /* jle .+9+<pad> */
  953                                 *p++ = 0x09 + (i ? sizeof(int) - i : 0);
  954                                 *p++ = 0xC7;    /* movl $0, 0(%esp) */
  955                                 *p++ = 0x04;
  956                                 *p++ = 0x24;
  957                                 *p++ = 0x00;
  958                                 *p++ = 0x00;
  959                                 *p++ = 0x00;
  960                                 *p++ = 0x00;
  961 
  962                                 i = ((p - (unsigned char *)top) + 2) &
  963                                         (sizeof(int) - 1);
  964                                 *p++ = 0xEB;    /* jmp .+7+<pad> */
  965                                 *p++ = 0x07 + (i ? sizeof(int) - i : 0);
  966 
  967                                 /*
  968                                  * Pad to longword boundary (cf dissas).
  969                                  */
  970                                 if (i = (p - (unsigned char *)top) &
  971                                     (sizeof(int) - 1))
  972                                         while (i++ < sizeof(int))
  973                                                 *p++ = 0x90; /* nop */
  974                                 *p++ = 0xC7;    /* movl $1, 0(%esp) */
  975                                 *p++ = 0x04;
  976                                 *p++ = 0x24;
  977                                 *p++ = 0x01;
  978                                 *p++ = 0x00;
  979                                 *p++ = 0x00;
  980                                 *p++ = 0x00;
  981                                 break;
  982 
  983                         case NETF_OP(NETF_GT):
  984                                 /*
  985                                  * *sp = (*sp > arg);
  986                                  */
  987                                 if (loop < 2) {
  988                                         pend += 14;
  989                                         /*
  990                                          * Pad to longword boundary (cf dissas).
  991                                          */
  992                                         if (i = ((pend - (unsigned char *)0) &
  993                                                  (sizeof(int) - 1)))
  994                                                 pend += (sizeof(int) - i);
  995                                         pend += 7;
  996                                         break;
  997                                 }
  998                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
  999                                 *p++ = 0x0C;
 1000                                 *p++ = 0x24;
 1001 
 1002                                 i = ((p - (unsigned char *)top) + 11) &
 1003                                         (sizeof(int) - 1);
 1004                                 *p++ = 0x7F;    /* jg .+9+<pad> */
 1005                                 *p++ = 0x09 + (i ? sizeof(int) - i : 0);
 1006                                 *p++ = 0xC7;    /* movl $0, 0(%esp) */
 1007                                 *p++ = 0x04;
 1008                                 *p++ = 0x24;
 1009                                 *p++ = 0x00;
 1010                                 *p++ = 0x00;
 1011                                 *p++ = 0x00;
 1012                                 *p++ = 0x00;
 1013 
 1014                                 i = ((p - (unsigned char *)top) + 2) &
 1015                                         (sizeof(int) - 1);
 1016                                 *p++ = 0xEB;    /* jmp .+7+<pad> */
 1017                                 *p++ = 0x07 + (i ? sizeof(int) - i : 0);
 1018 
 1019                                 /*
 1020                                  * Pad to longword boundary (cf dissas).
 1021                                  */
 1022                                 if (i = (p - (unsigned char *)top) &
 1023                                     (sizeof(int) - 1))
 1024                                         while (i++ < sizeof(int))
 1025                                                 *p++ = 0x90; /* nop */
 1026                                 *p++ = 0xC7;    /* movl $1, 0(%esp) */
 1027                                 *p++ = 0x04;
 1028                                 *p++ = 0x24;
 1029                                 *p++ = 0x01;
 1030                                 *p++ = 0x00;
 1031                                 *p++ = 0x00;
 1032                                 *p++ = 0x00;
 1033                                 break;
 1034 
 1035                         case NETF_OP(NETF_GE):
 1036                                 /*
 1037                                  * *sp = (*sp >= arg);
 1038                                  */
 1039                                 if (loop < 2) {
 1040                                         pend += 14;
 1041                                         /*
 1042                                          * Pad to longword boundary (cf dissas).
 1043                                          */
 1044                                         if (i = ((pend - (unsigned char *)0) &
 1045                                                  (sizeof(int) - 1)))
 1046                                                 pend += (sizeof(int) - i);
 1047                                         pend += 7;
 1048                                         break;
 1049                                 }
 1050                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
 1051                                 *p++ = 0x0C;
 1052                                 *p++ = 0x24;
 1053 
 1054                                 i = ((p - (unsigned char *)top) + 11) &
 1055                                         (sizeof(int) - 1);
 1056                                 *p++ = 0x7D;    /* jge .+9+<pad> */
 1057                                 *p++ = 0x09 + (i ? sizeof(int) - i : 0);
 1058                                 *p++ = 0xC7;    /* movl $0, 0(%esp) */
 1059                                 *p++ = 0x04;
 1060                                 *p++ = 0x24;
 1061                                 *p++ = 0x00;
 1062                                 *p++ = 0x00;
 1063                                 *p++ = 0x00;
 1064                                 *p++ = 0x00;
 1065 
 1066                                 i = ((p - (unsigned char *)top) + 2) &
 1067                                         (sizeof(int) - 1);
 1068                                 *p++ = 0xEB;    /* jmp .+7+<pad> */
 1069                                 *p++ = 0x07 + (i ? sizeof(int) - i : 0);
 1070 
 1071                                 /*
 1072                                  * Pad to longword boundary (cf dissas).
 1073                                  */
 1074                                 if (i = (p - (unsigned char *)top) &
 1075                                     (sizeof(int) - 1))
 1076                                         while (i++ < sizeof(int))
 1077                                                 *p++ = 0x90; /* nop */
 1078                                 *p++ = 0xC7;    /* movl $1, 0(%esp) */
 1079                                 *p++ = 0x04;
 1080                                 *p++ = 0x24;
 1081                                 *p++ = 0x01;
 1082                                 *p++ = 0x00;
 1083                                 *p++ = 0x00;
 1084                                 *p++ = 0x00;
 1085                                 break;
 1086 
 1087                         case NETF_OP(NETF_COR):
 1088                                 /*
 1089                                  * if (*sp++ == arg)
 1090                                  *     return (TRUE);
 1091                                  */
 1092                                 if (loop < 2) {
 1093                                         if (loop == 0 ||
 1094                                             PEND_TRUE - (pend + 5) >= 128)
 1095                                                 pend += 12;
 1096                                         else
 1097                                                 pend += 8;
 1098                                         break;
 1099                                 }
 1100 
 1101                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
 1102                                 *p++ = 0x0C;
 1103                                 *p++ = 0x24;
 1104 
 1105                                 if (PEND_TRUE - (p + 2) >= 128) {
 1106                                         *p++ = 0x0F;    /* je end_true */
 1107                                         *p++ = 0x84;
 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;
 1112                                         p += 4;
 1113 
 1114                                 } else {
 1115                                         *p++ = 0x74;    /* je end_true */
 1116                                         *p = PEND_TRUE - (p + 1);
 1117                                         p++;
 1118                                 }
 1119 
 1120                                 *p++ = 0x83;    /* addl $4, %esp */
 1121                                 *p++ = 0xC4;
 1122                                 *p++ = 0x04;
 1123                                 break;
 1124 
 1125                         case NETF_OP(NETF_CAND):
 1126                                 /*
 1127                                  * if (*sp++ != arg)
 1128                                  *     return (FALSE);
 1129                                  */
 1130                                 if (loop < 2) {
 1131                                         if (loop == 0 ||
 1132                                             PEND_FALSE - (pend + 5) >= 128)
 1133                                                 pend += 12;
 1134                                         else
 1135                                                 pend += 8;
 1136                                         break;
 1137                                 }
 1138 
 1139                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
 1140                                 *p++ = 0x0C;
 1141                                 *p++ = 0x24;
 1142 
 1143                                 if (PEND_FALSE - (p + 2) >= 128) {
 1144                                         *p++ = 0x0F;    /* jne end_false */
 1145                                         *p++ = 0x85;
 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;
 1150                                         p += 4;
 1151 
 1152                                 } else {
 1153                                         *p++ = 0x75;    /* jne end_false */
 1154                                         *p = PEND_FALSE - (p + 1);
 1155                                         p++;
 1156                                 }
 1157 
 1158                                 *p++ = 0x83;    /* addl $4, %esp */
 1159                                 *p++ = 0xC4;
 1160                                 *p++ = 0x04;
 1161                                 break;
 1162 
 1163                         case NETF_OP(NETF_CNOR):
 1164                                 /*
 1165                                  * if (*sp++ == arg)
 1166                                  *     return (FALSE);
 1167                                  */
 1168                                 if (loop < 2) {
 1169                                         if (loop == 0 ||
 1170                                             PEND_FALSE - (pend + 5) >= 128)
 1171                                                 pend += 12;
 1172                                         else
 1173                                                 pend += 8;
 1174                                         break;
 1175                                 }
 1176 
 1177                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
 1178                                 *p++ = 0x0C;
 1179                                 *p++ = 0x24;
 1180 
 1181                                 if (PEND_FALSE - (p + 2) >= 128) {
 1182                                         *p++ = 0x0F;    /* je end_false */
 1183                                         *p++ = 0x84;
 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;
 1188                                         p += 4;
 1189                                 } else {
 1190                                         *p++ = 0x74;    /* je end_false */
 1191                                         *p = PEND_FALSE - (p + 1);
 1192                                         p++;
 1193                                 }
 1194 
 1195                                 *p++ = 0x83;    /* addl $4, %esp */
 1196                                 *p++ = 0xC4;
 1197                                 *p++ = 0x04;
 1198                                 break;
 1199 
 1200                         case NETF_OP(NETF_CNAND):
 1201                                 /*
 1202                                  * if (*sp++ != arg)
 1203                                  *     return (TRUE);
 1204                                  */
 1205                                 if (loop < 2) {
 1206                                         if (loop == 0 ||
 1207                                             PEND_TRUE - (pend + 5) >= 128)
 1208                                                 pend += 12;
 1209                                         else
 1210                                                 pend += 8;
 1211                                         break;
 1212                                 }
 1213 
 1214                                 *p++ = 0x39;    /* cmpl (%esp), %ecx */
 1215                                 *p++ = 0x0C;
 1216                                 *p++ = 0x24;
 1217 
 1218                                 if (PEND_TRUE - (p + 2) >= 128) {
 1219                                         *p++ = 0x0F;    /* jne end_true */
 1220                                         *p++ = 0x85;
 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;
 1225                                         p += 4;
 1226 
 1227                                 } else {
 1228                                         *p++ = 0x75;    /* jne end_true */
 1229                                         *p = PEND_TRUE - (p + 1);
 1230                                         p++;
 1231                                 }
 1232 
 1233                                 *p++ = 0x83;    /* addl $4, %esp */
 1234                                 *p++ = 0xC4;
 1235                                 *p++ = 0x04;
 1236                                 break;
 1237 
 1238                         case NETF_OP(NETF_LSH):
 1239                                 /*
 1240                                  * *sp <<= arg;
 1241                                  */
 1242                                 if (loop < 2)
 1243                                         pend += 3;
 1244                                 else {
 1245                                         *p++ = 0xD3;    /* sall (%esp), %cl */
 1246                                         *p++ = 0x24;
 1247                                         *p++ = 0x24;
 1248                                 }
 1249                                 break;
 1250 
 1251                         case NETF_OP(NETF_RSH):
 1252                                 /*
 1253                                  * *sp >>= arg;
 1254                                  */
 1255                                 if (loop < 2)
 1256                                         pend += 3;
 1257                                 else {
 1258                                         *p++ = 0xD3;    /* sarl (%esp), %cl */
 1259                                         *p++ = 0x3C;
 1260                                         *p++ = 0x24;
 1261                                 }
 1262                                 break;
 1263 
 1264                         case NETF_OP(NETF_ADD):
 1265                                 /*
 1266                                  * *sp += arg;
 1267                                  */ 
 1268                                 if (loop < 2)
 1269                                         pend += 3;
 1270                                 else {
 1271                                         *p++ = 0x01;    /* addl (%esp), %ecx */
 1272                                         *p++ = 0x0C;
 1273                                         *p++ = 0x24;
 1274                                 }
 1275                                 break;
 1276 
 1277                         case NETF_OP(NETF_SUB):
 1278                                 /*
 1279                                  * *sp -= arg;
 1280                                  */
 1281                                 if (loop < 2)
 1282                                         pend += 3;
 1283                                 else {
 1284                                         *p++ = 0x29;    /* subl (%esp), %ecx */
 1285                                         *p++ = 0x0C;
 1286                                         *p++ = 0x24;
 1287                                 }
 1288                                 break;
 1289                         }
 1290                 }
 1291 
 1292                 /*
 1293                  * return ((*sp) ? TRUE : FALSE);
 1294                  */
 1295                 if (loop < 2) {
 1296                         if (push_ecx) {
 1297                                 pend += 12;
 1298                                 push_ecx = 0;
 1299                         } else
 1300                                 pend += 13;
 1301                         /*
 1302                          * Pad to longword boundary (cf dissas).
 1303                          */
 1304                         i = (pend - (unsigned char *)0) & (sizeof(int) - 1);
 1305                         false_pad = i ? sizeof(int) - i : 0;
 1306                         pend += 4 + push + false_pad;
 1307                 } else {
 1308                         if (push_ecx) {
 1309                                 *p++ = 0x83;    /* cmpl %ecx, $0 */
 1310                                 *p++ = 0xF9;
 1311                                 *p++ = 0x00;
 1312                                 push_ecx = 0;
 1313                         } else {
 1314                                 *p++ = 0x83;    /* cmpl (%esp), $0 */
 1315                                 *p++ = 0x3C;
 1316                                 *p++ = 0x24;
 1317                                 *p++ = 0x00;
 1318                         }
 1319 
 1320                         i = ((p - (unsigned char *)top) + 9) &
 1321                                 (sizeof(int) - 1);
 1322                         false_pad = i ? sizeof(int) - i : 0;
 1323                         *p++ = 0x74;    /* je end_false */
 1324                         *p++ = 0x07 + false_pad;
 1325 
 1326                         *p++ = 0xB8;    /* movl $1, %eax */
 1327                         *p++ = 0x01;
 1328                         *p++ = 0x00;
 1329                         *p++ = 0x00;
 1330                         *p++ = 0x00;
 1331 
 1332                         *p++ = 0xEB;    /* jmp .+2+<pad> */
 1333                         *p++ = 0x02 + false_pad;
 1334 
 1335                         /*
 1336                          * Pad to longword boundary (cf dissas).
 1337                          */
 1338                         for (i = 0; i < false_pad; i++)
 1339                                 *p++ = 0x90; /* nop */
 1340                         *p++ = 0x31;    /* xorl %eax, %eax */
 1341                         *p++ = 0xC0;
 1342                         if (push) {
 1343                                 *p++ = 0x8D;    /* leal -<push>(%ebx), %esp */
 1344                                 *p++ = 0x65;
 1345                                 *p++ = -((push - 3) * 4);
 1346                         }
 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 */
 1355                 }
 1356 
 1357                 /*
 1358                  * Prepare next loop if any.
 1359                  */
 1360                 if (loop == 2)
 1361                         break;
 1362 
 1363                 if (loop == 1 && pend == pend_old) {
 1364                         loop = 2;
 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);
 1369                 } else {
 1370                         if (loop == 0) {
 1371                                 loop = 1;
 1372                                 /*
 1373                                  * Compute and optimize free registers usage.
 1374                                  */
 1375                                 for (i = 0; i < NET_REG_MAX; i++)
 1376                                         reg[i] = -1;
 1377                                 if (use_data)
 1378                                         reg[NET_REG_EAX] = -2;
 1379                                 if (use_header)
 1380                                         reg[NET_REG_EDX] = -2;
 1381                                 net_filter_optimize(net_o, net_j,
 1382                                                     reg, NET_REG_MAX);
 1383                         }
 1384                         pend_old = pend;
 1385                         pend = 0;
 1386                 }
 1387                 for (i = 0; i < NET_REG_MAX; i++)
 1388                         if (reg[i] != -2)
 1389                                 reg[i] = -1;
 1390         }
 1391         return (top);
 1392 }
 1393 
 1394 void
 1395 net_filter_free(
 1396         filter_fct_t    fp,
 1397         unsigned int    len)
 1398 {
 1399         kfree((vm_offset_t)fp, len);
 1400 }
 1401 
 1402 /*
 1403  * Try to compute how to use (if needed) extra registers to store
 1404  * values read more than once.
 1405  *
 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.
 1410  *
 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
 1414  *                                              will be used.
 1415  *              reg is an array of used registers.
 1416  *                      == -2 ==> unused or unavailable register.
 1417  *                      >=  0 ==> used register.
 1418  *
 1419  * N.B. This procedure is completely machine-independent and should take place
 1420  *              in a file of the device directory.
 1421  */
 1422 void
 1423 net_filter_optimize(
 1424         struct net_opt  net_o[],
 1425         unsigned        net_len,
 1426         int             reg[],
 1427         unsigned        nbreg)
 1428 {
 1429         unsigned        i;
 1430         unsigned        j;
 1431         unsigned        nbnet;
 1432         unsigned        avail;
 1433         unsigned        used;
 1434         unsigned        first;
 1435         unsigned        max;
 1436         unsigned        last;
 1437         struct net_opt  *p;
 1438         struct net_opt  *q;
 1439 
 1440         avail = 0;
 1441         for (i = 0; i < nbreg; i++)
 1442                 if (reg[i] != -2)
 1443                         avail++;
 1444         if (avail == 0)
 1445                 return;
 1446 
 1447         /*
 1448          * First step: set up used field.
 1449          */
 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;
 1455                                 break;
 1456                         }
 1457                 if (q == &net_o[net_len])
 1458                         p->used = 1;
 1459         }
 1460 
 1461         /*
 1462          * Second step: choose best register and update used field.
 1463          */
 1464         if (net_len > 0) {
 1465                 if (net_o[0].used == 1)
 1466                         used = net_o[0].used = 0;
 1467                 else {
 1468                         net_o[0].reg = 0;
 1469                         used = 1;
 1470                 }
 1471 
 1472                 for (p = &net_o[1]; p < &net_o[net_len]; p++) {
 1473                         max = 0;
 1474                         first = avail;
 1475                         for (i = 0; i < avail; i++) {
 1476                                 q = p;
 1477                                 j = 0;
 1478                                 while (q-- != net_o)
 1479                                         if (q->used > 0 && q->reg == i) {
 1480                                                 if (q->used == 1)
 1481                                                         first = i;
 1482                                                 j = 1;
 1483                                                 break;
 1484                                         }
 1485                                 if (j == 0)
 1486                                         continue;
 1487 
 1488                                 if (q->val == p->val) {
 1489                                         p->reg = i;
 1490                                         break;
 1491                                 }
 1492 
 1493                                 if (p->used == 1)
 1494                                         continue;
 1495 
 1496                                 if (first == avail && used == avail) {
 1497                                         j = 1;
 1498                                         for (q = p+1; q->val != p->val; p++)
 1499                                                 j++;
 1500                                         if (j > max) {
 1501                                                 max = j;
 1502                                                 last = i;
 1503                                         }
 1504                                 }
 1505                         }
 1506                         if (i < avail)
 1507                                 continue;
 1508 
 1509                         if (p->used > 1) {
 1510                                 if (first != avail)
 1511                                         p->reg = first;
 1512                                 else if (used < avail)
 1513                                         p->reg = used++;
 1514                                 else
 1515                                         p->reg = last;
 1516                         } else
 1517                                 p->used = 0;
 1518                 }
 1519         }
 1520 
 1521         /*
 1522          * Third step: associate correct register number and keep max value.
 1523          */
 1524         for (p = net_o; p < &net_o[net_len]; p++) {
 1525                 if (p->used == 0)
 1526                         continue;
 1527                 i = first = 0;
 1528                 for (;;) {
 1529                         if (reg[i] != -2) {
 1530                                 if (first == p->reg) {
 1531                                         p->reg = i;
 1532                                         break;
 1533                                 }
 1534                                 first++;
 1535                         }
 1536                         i++;
 1537                 }
 1538         }
 1539 
 1540         /*
 1541          * Forth step: invalidate useless registers.
 1542          */
 1543         if (net_len == 0) {
 1544                 for (i = 0; i < nbreg; i++)
 1545                         if (reg[i] != -2)
 1546                                 reg[i] = -2;
 1547 
 1548         } else if (used < avail) {
 1549                 first = 0;
 1550                 for (i = 0; i < nbreg; i++)
 1551                         if (reg[i] != -2)
 1552                                 if (first >= used)
 1553                                         reg[i] = -2;
 1554                                 else
 1555                                         first++;
 1556         }
 1557 }

Cache object: e71ebc4e53d5fa582f24bbe16d1be97b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.