bpf_jit_machdep.c revision 181644
131921Sbrian/*-
231921Sbrian * Copyright (c) 2002 - 2003 NetGroup, Politecnico di Torino (Italy)
331921Sbrian * Copyright (c) 2005 Jung-uk Kim <jkim@FreeBSD.org>
431921Sbrian * All rights reserved.
531921Sbrian *
631921Sbrian * Redistribution and use in source and binary forms, with or without
731921Sbrian * modification, are permitted provided that the following conditions
831921Sbrian * are met:
931921Sbrian *
1031921Sbrian * 1. Redistributions of source code must retain the above copyright
1131921Sbrian * notice, this list of conditions and the following disclaimer.
1231921Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1331921Sbrian * notice, this list of conditions and the following disclaimer in the
1431921Sbrian * documentation and/or other materials provided with the distribution.
1531921Sbrian * 3. Neither the name of the Politecnico di Torino nor the names of its
1631921Sbrian * contributors may be used to endorse or promote products derived from
1731921Sbrian * this software without specific prior written permission.
1831921Sbrian *
1931921Sbrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2031921Sbrian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2131921Sbrian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2231921Sbrian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2331921Sbrian * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2431921Sbrian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2531921Sbrian * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2631921Sbrian * DATA, OR PROFITS; OR BUSINESS intERRUPTION) HOWEVER CAUSED AND ON ANY
2735773Scharnier * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2835773Scharnier * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2950471Speter * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3035773Scharnier */
3135773Scharnier
3227874Sbrian#include <sys/cdefs.h>
3327874Sbrian__FBSDID("$FreeBSD: head/sys/amd64/amd64/bpf_jit_machdep.c 181644 2008-08-12 20:10:45Z jkim $");
3427874Sbrian
3527874Sbrian#include "opt_bpf.h"
3627874Sbrian
3727874Sbrian#include <sys/param.h>
3827874Sbrian#include <sys/systm.h>
3927874Sbrian#include <sys/kernel.h>
4027874Sbrian#include <sys/types.h>
4127874Sbrian#include <sys/socket.h>
4227874Sbrian#include <sys/malloc.h>
4327874Sbrian
4457326Salfred#include <net/if.h>
4557326Salfred#include <net/bpf.h>
4627874Sbrian#include <net/bpf_jitter.h>
4727874Sbrian
4827874Sbrian#include <amd64/amd64/bpf_jit_machdep.h>
4927874Sbrian
5027874Sbrianbpf_filter_func	bpf_jit_compile(struct bpf_insn *, u_int, int *);
5127874Sbrian
5227874Sbrian/*
5327874Sbrian * emit routine to update the jump table
5427874Sbrian */
5527874Sbrianstatic void
5659175Sbrianemit_length(bpf_bin_stream *stream, u_int value, u_int len)
5727874Sbrian{
5827874Sbrian
5959022Sbrian	(stream->refs)[stream->bpf_pc] += len;
6059022Sbrian	stream->cur_ip += len;
6159175Sbrian}
6259022Sbrian
6359175Sbrian/*
6459175Sbrian * emit routine to output the actual binary code
6559175Sbrian */
6659022Sbrianstatic void
6759022Sbrianemit_code(bpf_bin_stream *stream, u_int value, u_int len)
6859022Sbrian{
6959022Sbrian
7059022Sbrian	switch (len) {
7127874Sbrian	case 1:
7227874Sbrian		stream->ibuf[stream->cur_ip] = (u_char)value;
7327874Sbrian		stream->cur_ip++;
7427874Sbrian		break;
7527874Sbrian
7628025Sbrian	case 2:
7728025Sbrian		*((u_short *)(stream->ibuf + stream->cur_ip)) = (u_short)value;
7827874Sbrian		stream->cur_ip += 2;
7927874Sbrian		break;
8027874Sbrian
8127874Sbrian	case 4:
8227874Sbrian		*((u_int *)(stream->ibuf + stream->cur_ip)) = value;
8327874Sbrian		stream->cur_ip += 4;
8428025Sbrian		break;
8527874Sbrian	}
8627874Sbrian
8727874Sbrian	return;
8827874Sbrian}
8927874Sbrian
9027874Sbrian/*
9127874Sbrian * Function that does the real stuff
9227874Sbrian */
9327874Sbrianbpf_filter_func
9427874Sbrianbpf_jit_compile(struct bpf_insn *prog, u_int nins, int *mem)
9527874Sbrian{
9627874Sbrian	struct bpf_insn *ins;
9727874Sbrian	u_int i, pass;
9827874Sbrian	bpf_bin_stream stream;
9927874Sbrian
10027874Sbrian	/*
10127874Sbrian	 * NOTE: do not modify the name of this variable, as it's used by
10227874Sbrian	 * the macros to emit code.
10327874Sbrian	 */
10427874Sbrian	emit_func emitm;
10527874Sbrian
10627874Sbrian	/* Do not compile an empty filter. */
10727874Sbrian	if (nins == 0)
10827874Sbrian		return NULL;
10927874Sbrian
11027874Sbrian	/* Allocate the reference table for the jumps */
11127874Sbrian	stream.refs = (u_int *)malloc((nins + 1) * sizeof(u_int),
11227874Sbrian	    M_BPFJIT, M_NOWAIT);
11327874Sbrian	if (stream.refs == NULL)
11427874Sbrian		return NULL;
11527874Sbrian
11627874Sbrian	/* Reset the reference table */
11727874Sbrian	for (i = 0; i < nins + 1; i++)
11827874Sbrian		stream.refs[i] = 0;
11927874Sbrian
12027874Sbrian	stream.cur_ip = 0;
12127874Sbrian	stream.bpf_pc = 0;
12227874Sbrian
12327874Sbrian	/*
12427874Sbrian	 * the first pass will emit the lengths of the instructions
12527874Sbrian	 * to create the reference table
12627874Sbrian	 */
12727874Sbrian	emitm = emit_length;
12859175Sbrian
12927874Sbrian	pass = 0;
13027874Sbrian	for (;;) {
13127874Sbrian		ins = prog;
13227874Sbrian
13327874Sbrian		/* create the procedure header */
13427874Sbrian		MOVrq2(RBX, R8);
13527874Sbrian		MOVrq(RDI, RBX);
13627874Sbrian		MOVrd2(ESI, R9D);
13727874Sbrian		MOVrd(EDX, EDI);
13827874Sbrian
13927874Sbrian		for (i = 0; i < nins; i++) {
14027874Sbrian			stream.bpf_pc++;
14127874Sbrian
14227874Sbrian			switch (ins->code) {
14327874Sbrian			default:
14427874Sbrian				return NULL;
14559175Sbrian
14627874Sbrian			case BPF_RET|BPF_K:
14727874Sbrian				MOVid(ins->k, EAX);
14827874Sbrian				MOVrq3(R8, RBX);
14959175Sbrian				RET();
15027874Sbrian				break;
15127874Sbrian
15227874Sbrian			case BPF_RET|BPF_A:
15327874Sbrian				MOVrq3(R8, RBX);
15427874Sbrian				RET();
15527874Sbrian				break;
15646073Simp
15727874Sbrian			case BPF_LD|BPF_W|BPF_ABS:
15827874Sbrian				MOVid(ins->k, ECX);
15927874Sbrian				MOVrd(ECX, ESI);
16027874Sbrian				ADDib(sizeof(int), ECX);
16146073Simp				CMPrd(EDI, ECX);
16259022Sbrian				JLEb(6);
16359175Sbrian				ZEROrd(EAX);
16459022Sbrian				MOVrq3(R8, RBX);
16559022Sbrian				RET();
16659022Sbrian				MOVobd(RBX, RSI, EAX);
16759022Sbrian				BSWAP(EAX);
16859022Sbrian				break;
16959022Sbrian
17027874Sbrian			case BPF_LD|BPF_H|BPF_ABS:
17127874Sbrian				ZEROrd(EAX);
17227874Sbrian				MOVid(ins->k, ECX);
17346073Simp				MOVrd(ECX, ESI);
17427874Sbrian				ADDib(sizeof(short), ECX);
17527874Sbrian				CMPrd(EDI, ECX);
17627874Sbrian				JLEb(4);
17727874Sbrian				MOVrq3(R8, RBX);
17846073Simp				RET();
17959022Sbrian				MOVobw(RBX, RSI, AX);
18059175Sbrian				SWAP_AX();
18127874Sbrian				break;
18259022Sbrian
18359022Sbrian			case BPF_LD|BPF_B|BPF_ABS:
18459175Sbrian				ZEROrd(EAX);
18559022Sbrian				MOVid(ins->k, ECX);
18659022Sbrian				CMPrd(EDI, ECX);
18759022Sbrian				JLEb(4);
18859022Sbrian				MOVrq3(R8, RBX);
18927874Sbrian				RET();
19027874Sbrian				MOVobb(RBX, RCX, AL);
19127874Sbrian				break;
19227874Sbrian
19327874Sbrian			case BPF_LD|BPF_W|BPF_LEN:
19427874Sbrian				MOVrd3(R9D, EAX);
19527874Sbrian				break;
19627874Sbrian
19727874Sbrian			case BPF_LDX|BPF_W|BPF_LEN:
19859175Sbrian				MOVrd3(R9D, EDX);
19927874Sbrian				break;
20027874Sbrian
20127874Sbrian			case BPF_LD|BPF_W|BPF_IND:
20259175Sbrian				MOVid(ins->k, ECX);
20327874Sbrian				ADDrd(EDX, ECX);
20427874Sbrian				MOVrd(ECX, ESI);
20559022Sbrian				ADDib(sizeof(int), ECX);
20627874Sbrian				CMPrd(EDI, ECX);
20727874Sbrian				JLEb(6);
20827874Sbrian				ZEROrd(EAX);
20927874Sbrian				MOVrq3(R8, RBX);
21027874Sbrian				RET();
21127874Sbrian				MOVobd(RBX, RSI, EAX);
21227874Sbrian				BSWAP(EAX);
21359175Sbrian				break;
21427874Sbrian
21527874Sbrian			case BPF_LD|BPF_H|BPF_IND:
21627874Sbrian				ZEROrd(EAX);
21727874Sbrian				MOVid(ins->k, ECX);
21827874Sbrian				ADDrd(EDX, ECX);
21927874Sbrian				MOVrd(ECX, ESI);
22027874Sbrian				ADDib(sizeof(short), ECX);
22127874Sbrian				CMPrd(EDI, ECX);
22227874Sbrian				JLEb(4);
22327874Sbrian				MOVrq3(R8, RBX);
22427874Sbrian				RET();
22527874Sbrian				MOVobw(RBX, RSI, AX);
22659175Sbrian				SWAP_AX();
22727874Sbrian				break;
22827874Sbrian
22927874Sbrian			case BPF_LD|BPF_B|BPF_IND:
23027874Sbrian				ZEROrd(EAX);
23127874Sbrian				MOVid(ins->k, ECX);
23227874Sbrian				ADDrd(EDX, ECX);
23327874Sbrian				CMPrd(EDI, ECX);
23427874Sbrian				JLEb(4);
23527874Sbrian				MOVrq3(R8, RBX);
23627874Sbrian				RET();
23727874Sbrian				MOVobb(RBX, RCX, AL);
23827874Sbrian				break;
23927874Sbrian
24027874Sbrian			case BPF_LDX|BPF_MSH|BPF_B:
24127874Sbrian				MOVid(ins->k, ECX);
24259175Sbrian				CMPrd(EDI, ECX);
24327874Sbrian				JLEb(6);
24427874Sbrian				ZEROrd(EAX);
24527874Sbrian				MOVrq3(R8, RBX);
24659175Sbrian				RET();
24727874Sbrian				ZEROrd(EDX);
24827874Sbrian				MOVobb(RBX, RCX, DL);
24927874Sbrian				ANDib(0xf, DL);
25027874Sbrian				SHLib(2, EDX);
25128025Sbrian				break;
25227874Sbrian
25327874Sbrian			case BPF_LD|BPF_IMM:
25427874Sbrian				MOVid(ins->k, EAX);
25527874Sbrian				break;
25627874Sbrian
25727874Sbrian			case BPF_LDX|BPF_IMM:
25827874Sbrian				MOVid(ins->k, EDX);
25959022Sbrian				break;
26060836Sbrian
26127874Sbrian			case BPF_LD|BPF_MEM:
26259022Sbrian				MOViq((uintptr_t)mem, RCX);
26327874Sbrian				MOVid(ins->k * 4, ESI);
26427874Sbrian				MOVobd(RCX, RSI, EAX);
26527874Sbrian				break;
26627874Sbrian
26759022Sbrian			case BPF_LDX|BPF_MEM:
26859022Sbrian				MOViq((uintptr_t)mem, RCX);
26960836Sbrian				MOVid(ins->k * 4, ESI);
27027874Sbrian				MOVobd(RCX, RSI, EDX);
27127874Sbrian				break;
27260836Sbrian
27327874Sbrian			case BPF_ST:
27427874Sbrian				/*
27527874Sbrian				 * XXX this command and the following could
27660836Sbrian				 * be optimized if the previous instruction
27727874Sbrian				 * was already of this type
27827874Sbrian				 */
27927874Sbrian				MOViq((uintptr_t)mem, RCX);
28027874Sbrian				MOVid(ins->k * 4, ESI);
28127874Sbrian				MOVomd(EAX, RCX, RSI);
28259175Sbrian				break;
28327874Sbrian
28428025Sbrian			case BPF_STX:
28528025Sbrian				MOViq((uintptr_t)mem, RCX);
28628025Sbrian				MOVid(ins->k * 4, ESI);
28728025Sbrian				MOVomd(EDX, RCX, RSI);
28827874Sbrian				break;
28959022Sbrian
29059022Sbrian			case BPF_JMP|BPF_JA:
29159022Sbrian				JMP(stream.refs[stream.bpf_pc + ins->k] -
29259022Sbrian				    stream.refs[stream.bpf_pc]);
29359022Sbrian				break;
29459022Sbrian
29559022Sbrian			case BPF_JMP|BPF_JGT|BPF_K:
29659175Sbrian				CMPid(ins->k, EAX);
29759022Sbrian				/* 5 is the size of the following JMP */
29859022Sbrian				JG(stream.refs[stream.bpf_pc + ins->jt] -
29928025Sbrian				    stream.refs[stream.bpf_pc] + 5 );
30028025Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jf] -
30127874Sbrian				    stream.refs[stream.bpf_pc]);
30259022Sbrian				break;
30359022Sbrian
30459022Sbrian			case BPF_JMP|BPF_JGE|BPF_K:
30559022Sbrian				CMPid(ins->k, EAX);
30659022Sbrian				JGE(stream.refs[stream.bpf_pc + ins->jt] -
30759022Sbrian				    stream.refs[stream.bpf_pc] + 5);
30859022Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jf] -
30959022Sbrian				    stream.refs[stream.bpf_pc]);
31059022Sbrian				break;
31159022Sbrian
31259175Sbrian			case BPF_JMP|BPF_JEQ|BPF_K:
31328025Sbrian				CMPid(ins->k, EAX);
31428025Sbrian				JE(stream.refs[stream.bpf_pc + ins->jt] -
31528025Sbrian				    stream.refs[stream.bpf_pc] + 5);
31628025Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jf] -
31727874Sbrian				    stream.refs[stream.bpf_pc]);
31828025Sbrian				break;
31928025Sbrian
32028025Sbrian			case BPF_JMP|BPF_JSET|BPF_K:
32127874Sbrian				MOVrd(EAX, ECX);
32228025Sbrian				ANDid(ins->k, ECX);
32359175Sbrian				JE(stream.refs[stream.bpf_pc + ins->jf] -
32427874Sbrian				    stream.refs[stream.bpf_pc] + 5);
32527874Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jt] -
32628025Sbrian				    stream.refs[stream.bpf_pc]);
32759175Sbrian				break;
32828025Sbrian
32928025Sbrian			case BPF_JMP|BPF_JGT|BPF_X:
33028025Sbrian				CMPrd(EDX, EAX);
33128025Sbrian				JA(stream.refs[stream.bpf_pc + ins->jt] -
33228025Sbrian				    stream.refs[stream.bpf_pc] + 5);
33328025Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jf] -
33459022Sbrian				    stream.refs[stream.bpf_pc]);
33559175Sbrian				break;
33659022Sbrian
33759022Sbrian			case BPF_JMP|BPF_JGE|BPF_X:
33859022Sbrian				CMPrd(EDX, EAX);
33959022Sbrian				JAE(stream.refs[stream.bpf_pc + ins->jt] -
34059022Sbrian				    stream.refs[stream.bpf_pc] + 5);
34159022Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jf] -
34228025Sbrian				    stream.refs[stream.bpf_pc]);
34328025Sbrian				break;
34428025Sbrian
34559022Sbrian			case BPF_JMP|BPF_JEQ|BPF_X:
34659175Sbrian				CMPrd(EDX, EAX);
34728025Sbrian				JE(stream.refs[stream.bpf_pc + ins->jt] -
34859022Sbrian				    stream.refs[stream.bpf_pc] + 5);
34959022Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jf] -
35059175Sbrian				    stream.refs[stream.bpf_pc]);
35159022Sbrian				break;
35259022Sbrian
35359022Sbrian			case BPF_JMP|BPF_JSET|BPF_X:
35459022Sbrian				MOVrd(EAX, ECX);
35528025Sbrian				ANDrd(EDX, ECX);
35628025Sbrian				JE(stream.refs[stream.bpf_pc + ins->jf] -
35728025Sbrian				    stream.refs[stream.bpf_pc] + 5);
35828025Sbrian				JMP(stream.refs[stream.bpf_pc + ins->jt] -
35928025Sbrian				    stream.refs[stream.bpf_pc]);
36028025Sbrian				break;
36128025Sbrian
36228025Sbrian			case BPF_ALU|BPF_ADD|BPF_X:
36328025Sbrian				ADDrd(EDX, EAX);
36459175Sbrian				break;
36528025Sbrian
36628025Sbrian			case BPF_ALU|BPF_SUB|BPF_X:
36744598Sbrian				SUBrd(EDX, EAX);
36859175Sbrian				break;
36944598Sbrian
37044598Sbrian			case BPF_ALU|BPF_MUL|BPF_X:
37144598Sbrian				MOVrd(EDX, ECX);
37244598Sbrian				MULrd(EDX);
37344598Sbrian				MOVrd(ECX, EDX);
37444598Sbrian				break;
37559022Sbrian
37659175Sbrian			case BPF_ALU|BPF_DIV|BPF_X:
37759022Sbrian				CMPid(0, EDX);
37859022Sbrian				JNEb(6);
37959022Sbrian				ZEROrd(EAX);
38059022Sbrian				MOVrq3(R8, RBX);
38159022Sbrian				RET();
38259022Sbrian				MOVrd(EDX, ECX);
38344598Sbrian				ZEROrd(EDX);
38444598Sbrian				DIVrd(ECX);
38544598Sbrian				MOVrd(ECX, EDX);
38659022Sbrian				break;
38759175Sbrian
38844598Sbrian			case BPF_ALU|BPF_AND|BPF_X:
38959022Sbrian				ANDrd(EDX, EAX);
39059022Sbrian				break;
39159175Sbrian
39259022Sbrian			case BPF_ALU|BPF_OR|BPF_X:
39359022Sbrian				ORrd(EDX, EAX);
39459022Sbrian				break;
39559022Sbrian
39644598Sbrian			case BPF_ALU|BPF_LSH|BPF_X:
39744598Sbrian				MOVrd(EDX, ECX);
39844598Sbrian				SHL_CLrb(EAX);
39944598Sbrian				break;
40044598Sbrian
40144598Sbrian			case BPF_ALU|BPF_RSH|BPF_X:
40244598Sbrian				MOVrd(EDX, ECX);
40344598Sbrian				SHR_CLrb(EAX);
40444598Sbrian				break;
40559175Sbrian
40644598Sbrian			case BPF_ALU|BPF_ADD|BPF_K:
40744598Sbrian				ADD_EAXi(ins->k);
40827874Sbrian				break;
40927874Sbrian
41027874Sbrian			case BPF_ALU|BPF_SUB|BPF_K:
41128025Sbrian				SUB_EAXi(ins->k);
41228025Sbrian				break;
41328025Sbrian
41428025Sbrian			case BPF_ALU|BPF_MUL|BPF_K:
41528025Sbrian				MOVrd(EDX, ECX);
41628025Sbrian				MOVid(ins->k, EDX);
41727874Sbrian				MULrd(EDX);
41828025Sbrian				MOVrd(ECX, EDX);
41928025Sbrian				break;
42028025Sbrian
42128025Sbrian			case BPF_ALU|BPF_DIV|BPF_K:
42228025Sbrian				MOVrd(EDX, ECX);
42328025Sbrian				ZEROrd(EDX);
42428025Sbrian				MOVid(ins->k, ESI);
42528025Sbrian				DIVrd(ESI);
42628025Sbrian				MOVrd(ECX, EDX);
42728025Sbrian				break;
42859175Sbrian
42959175Sbrian			case BPF_ALU|BPF_AND|BPF_K:
43059175Sbrian				ANDid(ins->k, EAX);
43128025Sbrian				break;
43228025Sbrian
43328025Sbrian			case BPF_ALU|BPF_OR|BPF_K:
43459175Sbrian				ORid(ins->k, EAX);
43528025Sbrian				break;
43628025Sbrian
43728025Sbrian			case BPF_ALU|BPF_LSH|BPF_K:
43828025Sbrian				SHLib((ins->k) & 0xff, EAX);
43959175Sbrian				break;
44028025Sbrian
44128025Sbrian			case BPF_ALU|BPF_RSH|BPF_K:
44227874Sbrian				SHRib((ins->k) & 0xff, EAX);
44328025Sbrian				break;
44428025Sbrian
44528025Sbrian			case BPF_ALU|BPF_NEG:
44628025Sbrian				NEGd(EAX);
44728025Sbrian				break;
44828025Sbrian
44944598Sbrian			case BPF_MISC|BPF_TAX:
45059175Sbrian				MOVrd(EAX, EDX);
45144598Sbrian				break;
45244598Sbrian
45328025Sbrian			case BPF_MISC|BPF_TXA:
45459175Sbrian				MOVrd(EDX, EAX);
45528025Sbrian				break;
45628025Sbrian			}
45728025Sbrian			ins++;
45859175Sbrian		}
45928025Sbrian
46028025Sbrian		pass++;
46128025Sbrian		if (pass == 2)
46259175Sbrian			break;
46359175Sbrian
46428025Sbrian		stream.ibuf = (char *)malloc(stream.cur_ip, M_BPFJIT, M_NOWAIT);
46528025Sbrian		if (stream.ibuf == NULL) {
46628025Sbrian			free(stream.refs, M_BPFJIT);
46759175Sbrian			return NULL;
46859175Sbrian		}
46928025Sbrian
47028025Sbrian		/*
47128025Sbrian		 * modify the reference table to contain the offsets and
47259175Sbrian		 * not the lengths of the instructions
47359175Sbrian		 */
47428025Sbrian		for (i = 1; i < nins + 1; i++)
47528025Sbrian			stream.refs[i] += stream.refs[i - 1];
47628025Sbrian
47759175Sbrian		/* Reset the counters */
47859175Sbrian		stream.cur_ip = 0;
47928025Sbrian		stream.bpf_pc = 0;
48028025Sbrian
48128025Sbrian		/* the second pass creates the actual code */
48227874Sbrian		emitm = emit_code;
48328025Sbrian	}
48427874Sbrian
48527874Sbrian	/*
48627874Sbrian	 * the reference table is needed only during compilation,
48727874Sbrian	 * now we can free it
48827874Sbrian	 */
48927874Sbrian	free(stream.refs, M_BPFJIT);
49027874Sbrian
49127874Sbrian	return (bpf_filter_func)stream.ibuf;
49227874Sbrian}
49327874Sbrian