Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Nov 2009 00:19:09 +0000 (UTC)
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r199619 - in head/sys: amd64/amd64 i386/i386
Message-ID:  <200911210019.nAL0J91R060525@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Sat Nov 21 00:19:09 2009
New Revision: 199619
URL: http://svn.freebsd.org/changeset/base/199619

Log:
  Add an experimental and rudimentary JIT optimizer to reduce unncessary
  overhead from short BPF filter programs such as "get the first 96 bytes".

Modified:
  head/sys/amd64/amd64/bpf_jit_machdep.c
  head/sys/amd64/amd64/bpf_jit_machdep.h
  head/sys/i386/i386/bpf_jit_machdep.c
  head/sys/i386/i386/bpf_jit_machdep.h

Modified: head/sys/amd64/amd64/bpf_jit_machdep.c
==============================================================================
--- head/sys/amd64/amd64/bpf_jit_machdep.c	Fri Nov 20 23:14:08 2009	(r199618)
+++ head/sys/amd64/amd64/bpf_jit_machdep.c	Sat Nov 21 00:19:09 2009	(r199619)
@@ -57,18 +57,19 @@ __FBSDID("$FreeBSD$");
 bpf_filter_func	bpf_jit_compile(struct bpf_insn *, u_int, size_t *);
 
 /*
- * emit routine to update the jump table
+ * Emit routine to update the jump table.
  */
 static void
 emit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
 {
 
-	(stream->refs)[stream->bpf_pc] += len;
+	if (stream->refs != NULL)
+		(stream->refs)[stream->bpf_pc] += len;
 	stream->cur_ip += len;
 }
 
 /*
- * emit routine to output the actual binary code
+ * Emit routine to output the actual binary code.
  */
 static void
 emit_code(bpf_bin_stream *stream, u_int value, u_int len)
@@ -95,37 +96,79 @@ emit_code(bpf_bin_stream *stream, u_int 
 }
 
 /*
- * Function that does the real stuff
+ * Scan the filter program and find possible optimization.
+ */
+static int
+bpf_jit_optimize(struct bpf_insn *prog, u_int nins)
+{
+	const struct bpf_insn *p;
+	int flags;
+	u_int i;
+
+	/* Do we return immediately? */
+	if (BPF_CLASS(prog[0].code) == BPF_RET)
+		return (BPF_JIT_FLAG_RET);
+
+	for (flags = 0, i = 0; i < nins; i++) {
+		p = &prog[i];
+
+		/* Do we need reference table? */
+		if ((flags & BPF_JIT_FLAG_JMP) == 0 &&
+		    BPF_CLASS(p->code) == BPF_JMP)
+			flags |= BPF_JIT_FLAG_JMP;
+
+		/* Do we need scratch memory? */
+		if ((flags & BPF_JIT_FLAG_MEM) == 0 &&
+		    (p->code == BPF_ST || p->code == BPF_STX ||
+		    p->code == (BPF_LD|BPF_MEM) ||
+		    p->code == (BPF_LDX|BPF_MEM)))
+			flags |= BPF_JIT_FLAG_MEM;
+
+		if (flags == BPF_JIT_FLAG_ALL)
+			break;
+	}
+
+	return (flags);
+}
+
+/*
+ * Function that does the real stuff.
  */
 bpf_filter_func
 bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
 {
 	bpf_bin_stream stream;
 	struct bpf_insn *ins;
+	int flags, flag_ret, flag_jmp, flag_mem;
 	u_int i, pass;
 
+	flags = bpf_jit_optimize(prog, nins);
+	flag_ret = (flags & BPF_JIT_FLAG_RET) != 0;
+	flag_jmp = (flags & BPF_JIT_FLAG_JMP) != 0;
+	flag_mem = (flags & BPF_JIT_FLAG_MEM) != 0;
+
 	/*
 	 * NOTE: Do not modify the name of this variable, as it's used by
 	 * the macros to emit code.
 	 */
 	emit_func emitm;
 
+	memset(&stream, 0, sizeof(stream));
+
 	/* Allocate the reference table for the jumps. */
+	if (flag_jmp) {
 #ifdef _KERNEL
-	stream.refs = malloc((nins + 1) * sizeof(u_int), M_BPFJIT,
-	    M_NOWAIT | M_ZERO);
+		stream.refs = malloc((nins + 1) * sizeof(u_int), M_BPFJIT,
+		    M_NOWAIT | M_ZERO);
 #else
-	stream.refs = malloc((nins + 1) * sizeof(u_int));
+		stream.refs = malloc((nins + 1) * sizeof(u_int));
 #endif
-	if (stream.refs == NULL)
-		return (NULL);
+		if (stream.refs == NULL)
+			return (NULL);
 #ifndef _KERNEL
-	memset(stream.refs, 0, (nins + 1) * sizeof(u_int));
+		memset(stream.refs, 0, (nins + 1) * sizeof(u_int));
 #endif
-
-	stream.cur_ip = 0;
-	stream.bpf_pc = 0;
-	stream.ibuf = NULL;
+	}
 
 	/*
 	 * The first pass will emit the lengths of the instructions
@@ -137,12 +180,16 @@ bpf_jit_compile(struct bpf_insn *prog, u
 		ins = prog;
 
 		/* Create the procedure header. */
-		PUSH(RBP);
-		MOVrq(RSP, RBP);
-		SUBib(BPF_MEMWORDS * sizeof(uint32_t), RSP);
-		MOVrq2(RDI, R8);
-		MOVrd2(ESI, R9D);
-		MOVrd(EDX, EDI);
+		if (flag_mem) {
+			PUSH(RBP);
+			MOVrq(RSP, RBP);
+			SUBib(BPF_MEMWORDS * sizeof(uint32_t), RSP);
+		}
+		if (!flag_ret) {
+			MOVrq2(RDI, R8);
+			MOVrd2(ESI, R9D);
+			MOVrd(EDX, EDI);
+		}
 
 		for (i = 0; i < nins; i++) {
 			stream.bpf_pc++;
@@ -157,11 +204,15 @@ bpf_jit_compile(struct bpf_insn *prog, u
 
 			case BPF_RET|BPF_K:
 				MOVid(ins->k, EAX);
-				LEAVE_RET();
+				if (flag_mem)
+					LEAVE();
+				RET();
 				break;
 
 			case BPF_RET|BPF_A:
-				LEAVE_RET();
+				if (flag_mem)
+					LEAVE();
+				RET();
 				break;
 
 			case BPF_LD|BPF_W|BPF_ABS:
@@ -171,9 +222,15 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				MOVrd(EDI, ECX);
 				SUBrd(ESI, ECX);
 				CMPid(sizeof(int32_t), ECX);
-				JAEb(4);
-				ZEROrd(EAX);
-				LEAVE_RET();
+				if (flag_mem) {
+					JAEb(4);
+					ZEROrd(EAX);
+					LEAVE();
+				} else {
+					JAEb(3);
+					ZEROrd(EAX);
+				}
+				RET();
 				MOVrq3(R8, RCX);
 				MOVobd(RCX, RSI, EAX);
 				BSWAP(EAX);
@@ -187,8 +244,12 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				MOVrd(EDI, ECX);
 				SUBrd(ESI, ECX);
 				CMPid(sizeof(int16_t), ECX);
-				JAEb(2);
-				LEAVE_RET();
+				if (flag_mem) {
+					JAEb(2);
+					LEAVE();
+				} else
+					JAEb(1);
+				RET();
 				MOVrq3(R8, RCX);
 				MOVobw(RCX, RSI, AX);
 				SWAP_AX();
@@ -198,8 +259,12 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				ZEROrd(EAX);
 				MOVid(ins->k, ESI);
 				CMPrd(EDI, ESI);
-				JBb(2);
-				LEAVE_RET();
+				if (flag_mem) {
+					JBb(2);
+					LEAVE();
+				} else
+					JBb(1);
+				RET();
 				MOVrq3(R8, RCX);
 				MOVobb(RCX, RSI, AL);
 				break;
@@ -224,9 +289,15 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				MOVrd(EDI, ECX);
 				SUBrd(ESI, ECX);
 				CMPid(sizeof(int32_t), ECX);
-				JAEb(4);
-				ZEROrd(EAX);
-				LEAVE_RET();
+				if (flag_mem) {
+					JAEb(4);
+					ZEROrd(EAX);
+					LEAVE();
+				} else {
+					JAEb(3);
+					ZEROrd(EAX);
+				}
+				RET();
 				MOVrq3(R8, RCX);
 				MOVobd(RCX, RSI, EAX);
 				BSWAP(EAX);
@@ -245,8 +316,12 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				MOVrd(EDI, ECX);
 				SUBrd(ESI, ECX);
 				CMPid(sizeof(int16_t), ECX);
-				JAEb(2);
-				LEAVE_RET();
+				if (flag_mem) {
+					JAEb(2);
+					LEAVE();
+				} else
+					JAEb(1);
+				RET();
 				MOVrq3(R8, RCX);
 				MOVobw(RCX, RSI, AX);
 				SWAP_AX();
@@ -260,8 +335,12 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				MOVrd(EDI, ECX);
 				SUBrd(EDX, ECX);
 				CMPrd(ESI, ECX);
-				JAb(2);
-				LEAVE_RET();
+				if (flag_mem) {
+					JAb(2);
+					LEAVE();
+				} else
+					JAb(1);
+				RET();
 				MOVrq3(R8, RCX);
 				ADDrd(EDX, ESI);
 				MOVobb(RCX, RSI, AL);
@@ -270,9 +349,15 @@ bpf_jit_compile(struct bpf_insn *prog, u
 			case BPF_LDX|BPF_MSH|BPF_B:
 				MOVid(ins->k, ESI);
 				CMPrd(EDI, ESI);
-				JBb(4);
-				ZEROrd(EAX);
-				LEAVE_RET();
+				if (flag_mem) {
+					JBb(4);
+					ZEROrd(EAX);
+					LEAVE();
+				} else {
+					JBb(3);
+					ZEROrd(EAX);
+				}
+				RET();
 				ZEROrd(EDX);
 				MOVrq3(R8, RCX);
 				MOVobb(RCX, RSI, DL);
@@ -390,9 +475,15 @@ bpf_jit_compile(struct bpf_insn *prog, u
 
 			case BPF_ALU|BPF_DIV|BPF_X:
 				TESTrd(EDX, EDX);
-				JNEb(4);
-				ZEROrd(EAX);
-				LEAVE_RET();
+				if (flag_mem) {
+					JNEb(4);
+					ZEROrd(EAX);
+					LEAVE();
+				} else {
+					JNEb(3);
+					ZEROrd(EAX);
+				}
+				RET();
 				MOVrd(EDX, ECX);
 				ZEROrd(EDX);
 				DIVrd(ECX);
@@ -492,8 +583,9 @@ bpf_jit_compile(struct bpf_insn *prog, u
 		 * Modify the reference table to contain the offsets and
 		 * not the lengths of the instructions.
 		 */
-		for (i = 1; i < nins + 1; i++)
-			stream.refs[i] += stream.refs[i - 1];
+		if (flag_jmp)
+			for (i = 1; i < nins + 1; i++)
+				stream.refs[i] += stream.refs[i - 1];
 
 		/* Reset the counters. */
 		stream.cur_ip = 0;
@@ -507,10 +599,14 @@ bpf_jit_compile(struct bpf_insn *prog, u
 	 * The reference table is needed only during compilation,
 	 * now we can free it.
 	 */
+	if (flag_jmp)
 #ifdef _KERNEL
-	free(stream.refs, M_BPFJIT);
+		free(stream.refs, M_BPFJIT);
 #else
-	free(stream.refs);
+		free(stream.refs);
+#endif
+
+#ifndef _KERNEL
 	if (stream.ibuf != NULL &&
 	    mprotect(stream.ibuf, *size, PROT_READ | PROT_EXEC) != 0) {
 		munmap(stream.ibuf, *size);

Modified: head/sys/amd64/amd64/bpf_jit_machdep.h
==============================================================================
--- head/sys/amd64/amd64/bpf_jit_machdep.h	Fri Nov 20 23:14:08 2009	(r199618)
+++ head/sys/amd64/amd64/bpf_jit_machdep.h	Sat Nov 21 00:19:09 2009	(r199619)
@@ -85,7 +85,15 @@
 #define DL	2
 #define BL	3
 
-/* A stream of native binary code.*/
+/* Optimization flags */
+#define	BPF_JIT_FLAG_RET	0x01
+#define	BPF_JIT_FLAG_JMP	0x02
+#define	BPF_JIT_FLAG_MEM	0x04
+
+#define	BPF_JIT_FLAG_ALL	\
+    (BPF_JIT_FLAG_JMP | BPF_JIT_FLAG_MEM)
+
+/* A stream of native binary code */
 typedef struct bpf_bin_stream {
 	/* Current native instruction pointer. */
 	int		cur_ip;
@@ -117,7 +125,7 @@ typedef struct bpf_bin_stream {
 typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
 
 /*
- * native Instruction Macros
+ * Native instruction macros
  */
 
 /* movl i32,r32 */
@@ -220,9 +228,14 @@ typedef void (*emit_func)(bpf_bin_stream
 	emitm(&stream, (5 << 4) | (0 << 3) | (r64 & 0x7), 1);		\
 } while (0)
 
-/* leave/ret */
-#define LEAVE_RET() do {						\
-	emitm(&stream, 0xc3c9, 2);					\
+/* leaveq */
+#define LEAVE() do {							\
+	emitm(&stream, 0xc9, 1);					\
+} while (0)
+
+/* retq */
+#define RET() do {							\
+	emitm(&stream, 0xc3, 1);					\
 } while (0)
 
 /* addl sr32,dr32 */

Modified: head/sys/i386/i386/bpf_jit_machdep.c
==============================================================================
--- head/sys/i386/i386/bpf_jit_machdep.c	Fri Nov 20 23:14:08 2009	(r199618)
+++ head/sys/i386/i386/bpf_jit_machdep.c	Sat Nov 21 00:19:09 2009	(r199619)
@@ -57,18 +57,19 @@ __FBSDID("$FreeBSD$");
 bpf_filter_func	bpf_jit_compile(struct bpf_insn *, u_int, size_t *);
 
 /*
- * emit routine to update the jump table
+ * Emit routine to update the jump table.
  */
 static void
 emit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
 {
 
-	(stream->refs)[stream->bpf_pc] += len;
+	if (stream->refs != NULL)
+		(stream->refs)[stream->bpf_pc] += len;
 	stream->cur_ip += len;
 }
 
 /*
- * emit routine to output the actual binary code
+ * Emit routine to output the actual binary code.
  */
 static void
 emit_code(bpf_bin_stream *stream, u_int value, u_int len)
@@ -95,37 +96,79 @@ emit_code(bpf_bin_stream *stream, u_int 
 }
 
 /*
- * Function that does the real stuff
+ * Scan the filter program and find possible optimization.
+ */
+static int
+bpf_jit_optimize(struct bpf_insn *prog, u_int nins)
+{
+	const struct bpf_insn *p;
+	int flags;
+	u_int i;
+
+	/* Do we return immediately? */
+	if (BPF_CLASS(prog[0].code) == BPF_RET)
+		return (BPF_JIT_FLAG_RET);
+
+	for (flags = 0, i = 0; i < nins; i++) {
+		p = &prog[i];
+
+		/* Do we need reference table? */
+		if ((flags & BPF_JIT_FLAG_JMP) == 0 &&
+		    BPF_CLASS(p->code) == BPF_JMP)
+			flags |= BPF_JIT_FLAG_JMP;
+
+		/* Do we need scratch memory? */
+		if ((flags & BPF_JIT_FLAG_MEM) == 0 &&
+		    (p->code == BPF_ST || p->code == BPF_STX ||
+		    p->code == (BPF_LD|BPF_MEM) ||
+		    p->code == (BPF_LDX|BPF_MEM)))
+			flags |= BPF_JIT_FLAG_MEM;
+
+		if (flags == BPF_JIT_FLAG_ALL)
+			break;
+	}
+
+	return (flags);
+}
+
+/*
+ * Function that does the real stuff.
  */
 bpf_filter_func
 bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
 {
 	bpf_bin_stream stream;
 	struct bpf_insn *ins;
+	int flags, flag_ret, flag_jmp, flag_mem;
 	u_int i, pass;
 
+	flags = bpf_jit_optimize(prog, nins);
+	flag_ret = (flags & BPF_JIT_FLAG_RET) != 0;
+	flag_jmp = (flags & BPF_JIT_FLAG_JMP) != 0;
+	flag_mem = (flags & BPF_JIT_FLAG_MEM) != 0;
+
 	/*
 	 * NOTE: Do not modify the name of this variable, as it's used by
 	 * the macros to emit code.
 	 */
 	emit_func emitm;
 
+	memset(&stream, 0, sizeof(stream));
+
 	/* Allocate the reference table for the jumps. */
+	if (flag_jmp) {
 #ifdef _KERNEL
-	stream.refs = malloc((nins + 1) * sizeof(u_int), M_BPFJIT,
-	    M_NOWAIT | M_ZERO);
+		stream.refs = malloc((nins + 1) * sizeof(u_int), M_BPFJIT,
+		    M_NOWAIT | M_ZERO);
 #else
-	stream.refs = malloc((nins + 1) * sizeof(u_int));
+		stream.refs = malloc((nins + 1) * sizeof(u_int));
 #endif
-	if (stream.refs == NULL)
-		return (NULL);
+		if (stream.refs == NULL)
+			return (NULL);
 #ifndef _KERNEL
-	memset(stream.refs, 0, (nins + 1) * sizeof(u_int));
+		memset(stream.refs, 0, (nins + 1) * sizeof(u_int));
 #endif
-
-	stream.cur_ip = 0;
-	stream.bpf_pc = 0;
-	stream.ibuf = NULL;
+	}
 
 	/*
 	 * The first pass will emit the lengths of the instructions
@@ -137,14 +180,19 @@ bpf_jit_compile(struct bpf_insn *prog, u
 		ins = prog;
 
 		/* Create the procedure header. */
-		PUSH(EBP);
-		MOVrd(ESP, EBP);
-		SUBib(BPF_MEMWORDS * sizeof(uint32_t), ESP);
-		PUSH(EDI);
-		PUSH(ESI);
-		PUSH(EBX);
-		MOVodd(8, EBP, EBX);
-		MOVodd(16, EBP, EDI);
+		if (!flag_ret) {
+			PUSH(EBP);
+			MOVrd(ESP, EBP);
+		}
+		if (flag_mem)
+			SUBib(BPF_MEMWORDS * sizeof(uint32_t), ESP);
+		if (!flag_ret) {
+			PUSH(EDI);
+			PUSH(ESI);
+			PUSH(EBX);
+			MOVodd(8, EBP, EBX);
+			MOVodd(16, EBP, EDI);
+		}
 
 		for (i = 0; i < nins; i++) {
 			stream.bpf_pc++;
@@ -159,17 +207,23 @@ bpf_jit_compile(struct bpf_insn *prog, u
 
 			case BPF_RET|BPF_K:
 				MOVid(ins->k, EAX);
-				POP(EBX);
-				POP(ESI);
-				POP(EDI);
-				LEAVE_RET();
+				if (!flag_ret) {
+					POP(EBX);
+					POP(ESI);
+					POP(EDI);
+					LEAVE();
+				}
+				RET();
 				break;
 
 			case BPF_RET|BPF_A:
-				POP(EBX);
-				POP(ESI);
-				POP(EDI);
-				LEAVE_RET();
+				if (!flag_ret) {
+					POP(EBX);
+					POP(ESI);
+					POP(EDI);
+					LEAVE();
+				}
+				RET();
 				break;
 
 			case BPF_LD|BPF_W|BPF_ABS:
@@ -184,7 +238,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				MOVobd(EBX, ESI, EAX);
 				BSWAP(EAX);
 				break;
@@ -201,7 +256,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				MOVobw(EBX, ESI, AX);
 				SWAP_AX();
 				break;
@@ -214,7 +270,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				MOVobb(EBX, ESI, AL);
 				break;
 
@@ -243,7 +300,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				MOVobd(EBX, ESI, EAX);
 				BSWAP(EAX);
 				break;
@@ -265,7 +323,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				MOVobw(EBX, ESI, AX);
 				SWAP_AX();
 				break;
@@ -282,7 +341,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				ADDrd(EDX, ESI);
 				MOVobb(EBX, ESI, AL);
 				break;
@@ -295,7 +355,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				ZEROrd(EDX);
 				MOVobb(EBX, ESI, DL);
 				ANDib(0x0f, DL);
@@ -425,7 +486,8 @@ bpf_jit_compile(struct bpf_insn *prog, u
 				POP(EBX);
 				POP(ESI);
 				POP(EDI);
-				LEAVE_RET();
+				LEAVE();
+				RET();
 				MOVrd(EDX, ECX);
 				ZEROrd(EDX);
 				DIVrd(ECX);
@@ -525,8 +587,9 @@ bpf_jit_compile(struct bpf_insn *prog, u
 		 * Modify the reference table to contain the offsets and
 		 * not the lengths of the instructions.
 		 */
-		for (i = 1; i < nins + 1; i++)
-			stream.refs[i] += stream.refs[i - 1];
+		if (flag_jmp)
+			for (i = 1; i < nins + 1; i++)
+				stream.refs[i] += stream.refs[i - 1];
 
 		/* Reset the counters. */
 		stream.cur_ip = 0;
@@ -540,10 +603,14 @@ bpf_jit_compile(struct bpf_insn *prog, u
 	 * The reference table is needed only during compilation,
 	 * now we can free it.
 	 */
+	if (flag_jmp)
 #ifdef _KERNEL
-	free(stream.refs, M_BPFJIT);
+		free(stream.refs, M_BPFJIT);
 #else
-	free(stream.refs);
+		free(stream.refs);
+#endif
+
+#ifndef _KERNEL
 	if (stream.ibuf != NULL &&
 	    mprotect(stream.ibuf, *size, PROT_READ | PROT_EXEC) != 0) {
 		munmap(stream.ibuf, *size);

Modified: head/sys/i386/i386/bpf_jit_machdep.h
==============================================================================
--- head/sys/i386/i386/bpf_jit_machdep.h	Fri Nov 20 23:14:08 2009	(r199618)
+++ head/sys/i386/i386/bpf_jit_machdep.h	Sat Nov 21 00:19:09 2009	(r199619)
@@ -60,7 +60,15 @@
 #define DL	2
 #define BL	3
 
-/* A stream of native binary code.*/
+/* Optimization flags */
+#define	BPF_JIT_FLAG_RET	0x01
+#define	BPF_JIT_FLAG_JMP	0x02
+#define	BPF_JIT_FLAG_MEM	0x04
+
+#define	BPF_JIT_FLAG_ALL	\
+    (BPF_JIT_FLAG_JMP | BPF_JIT_FLAG_MEM)
+
+/* A stream of native binary code */
 typedef struct bpf_bin_stream {
 	/* Current native instruction pointer. */
 	int		cur_ip;
@@ -92,7 +100,7 @@ typedef struct bpf_bin_stream {
 typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
 
 /*
- * native Instruction Macros
+ * Native instruction macros
  */
 
 /* movl i32,r32 */
@@ -165,9 +173,14 @@ typedef void (*emit_func)(bpf_bin_stream
 	emitm(&stream, (5 << 4) | (1 << 3) | (r32 & 0x7), 1);		\
 } while (0)
 
-/* leave/ret */
-#define LEAVE_RET() do {						\
-	emitm(&stream, 0xc3c9, 2);					\
+/* leave */
+#define LEAVE() do {							\
+	emitm(&stream, 0xc9, 1);					\
+} while (0)
+
+/* ret */
+#define RET() do {							\
+	emitm(&stream, 0xc3, 1);					\
 } while (0)
 
 /* addl sr32,dr32 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911210019.nAL0J91R060525>