1227569Sphilip/*- 2301388Sarybchik * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy) 3284555Sarybchik * Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org> 4227569Sphilip * All rights reserved. 5227569Sphilip * 6284555Sarybchik * Redistribution and use in source and binary forms, with or without 7227569Sphilip * modification, are permitted provided that the following conditions 8284555Sarybchik * are met: 9284555Sarybchik * 10284555Sarybchik * 1. Redistributions of source code must retain the above copyright 11284555Sarybchik * notice, this list of conditions and the following disclaimer. 12284555Sarybchik * 2. Redistributions in binary form must reproduce the above copyright 13284555Sarybchik * notice, this list of conditions and the following disclaimer in the 14284555Sarybchik * documentation and/or other materials provided with the distribution. 15284555Sarybchik * 3. Neither the name of the Politecnico di Torino nor the names of its 16284555Sarybchik * contributors may be used to endorse or promote products derived from 17284555Sarybchik * this software without specific prior written permission. 18284555Sarybchik * 19284555Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20284555Sarybchik * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21284555Sarybchik * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22284555Sarybchik * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23284555Sarybchik * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24284555Sarybchik * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25284555Sarybchik * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26284555Sarybchik * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27284555Sarybchik * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28284555Sarybchik * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29227569Sphilip * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30227569Sphilip * 31228078Sphilip * $FreeBSD$ 32228078Sphilip */ 33228078Sphilip 34227569Sphilip#ifndef _BPF_JIT_MACHDEP_H_ 35227569Sphilip#define _BPF_JIT_MACHDEP_H_ 36227569Sphilip 37293927Sarybchik/* 38227569Sphilip * Registers 39227569Sphilip */ 40227569Sphilip#define EAX 0 41227569Sphilip#define ECX 1 42227569Sphilip#define EDX 2 43284555Sarybchik#define EBX 3 44284555Sarybchik#define ESP 4 45227569Sphilip#define EBP 5 46284555Sarybchik#define ESI 6 47284555Sarybchik#define EDI 7 48284555Sarybchik 49284555Sarybchik#define AX 0 50284555Sarybchik#define CX 1 51284555Sarybchik#define DX 2 52284555Sarybchik#define BX 3 53284555Sarybchik#define SP 4 54284555Sarybchik#define BP 5 55284555Sarybchik#define SI 6 56284555Sarybchik#define DI 7 57284555Sarybchik 58293975Sarybchik#define AL 0 59284555Sarybchik#define CL 1 60284555Sarybchik#define DL 2 61284555Sarybchik#define BL 3 62284555Sarybchik 63284555Sarybchik/* Optimization flags */ 64284555Sarybchik#define BPF_JIT_FRET 0x01 65284555Sarybchik#define BPF_JIT_FPKT 0x02 66284555Sarybchik#define BPF_JIT_FMEM 0x04 67284555Sarybchik#define BPF_JIT_FJMP 0x08 68284555Sarybchik#define BPF_JIT_FADK 0x10 69284555Sarybchik 70284555Sarybchik#define BPF_JIT_FLAG_ALL \ 71284555Sarybchik (BPF_JIT_FPKT | BPF_JIT_FMEM | BPF_JIT_FJMP | BPF_JIT_FADK) 72284555Sarybchik 73284555Sarybchik/* A stream of native binary code */ 74284555Sarybchiktypedef struct bpf_bin_stream { 75284555Sarybchik /* Current native instruction pointer. */ 76284555Sarybchik int cur_ip; 77284555Sarybchik 78293975Sarybchik /* 79293975Sarybchik * Current BPF instruction pointer, i.e. position in 80293975Sarybchik * the BPF program reached by the jitter. 81293975Sarybchik */ 82293975Sarybchik int bpf_pc; 83293975Sarybchik 84293975Sarybchik /* Instruction buffer, contains the generated native code. */ 85293975Sarybchik char *ibuf; 86293975Sarybchik 87293975Sarybchik /* Jumps reference table. */ 88293975Sarybchik u_int *refs; 89293975Sarybchik} bpf_bin_stream; 90293975Sarybchik 91293975Sarybchik/* 92293975Sarybchik * Prototype of the emit functions. 93293975Sarybchik * 94293975Sarybchik * Different emit functions are used to create the reference table and 95293975Sarybchik * to generate the actual filtering code. This allows to have simpler 96293975Sarybchik * instruction macros. 97293975Sarybchik * The first parameter is the stream that will receive the data. 98301324Sarybchik * The second one is a variable containing the data. 99284555Sarybchik * The third one is the length, that can be 1, 2, or 4 since it is possible 100284555Sarybchik * to emit a byte, a short, or a word at a time. 101284555Sarybchik */ 102227569Sphiliptypedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n); 103284555Sarybchik 104284555Sarybchik/* 105227569Sphilip * Native instruction macros 106227569Sphilip */ 107227569Sphilip 108227569Sphilip/* movl i32,r32 */ 109227569Sphilip#define MOVid(i32, r32) do { \ 110301340Sarybchik emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \ 111227569Sphilip emitm(&stream, i32, 4); \ 112294377Sarybchik} while (0) 113284555Sarybchik 114227569Sphilip/* movl sr32,dr32 */ 115227569Sphilip#define MOVrd(sr32, dr32) do { \ 116284555Sarybchik emitm(&stream, 0x89, 1); \ 117284555Sarybchik emitm(&stream, \ 118227569Sphilip (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 119227569Sphilip} while (0) 120227569Sphilip 121227569Sphilip/* movl off(sr32),dr32 */ 122227569Sphilip#define MOVodd(off, sr32, dr32) do { \ 123227569Sphilip emitm(&stream, 0x8b, 1); \ 124227569Sphilip emitm(&stream, \ 125227569Sphilip (1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 126227569Sphilip emitm(&stream, off, 1); \ 127284555Sarybchik} while (0) 128284555Sarybchik 129301340Sarybchik/* movl (sr32,or32,1),dr32 */ 130294006Sarybchik#define MOVobd(sr32, or32, dr32) do { \ 131294377Sarybchik emitm(&stream, 0x8b, 1); \ 132294006Sarybchik emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \ 133294006Sarybchik emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 134294006Sarybchik} while (0) 135294006Sarybchik 136294006Sarybchik/* movw (sr32,or32,1),dr16 */ 137284555Sarybchik#define MOVobw(sr32, or32, dr16) do { \ 138294006Sarybchik emitm(&stream, 0x8b66, 2); \ 139284555Sarybchik emitm(&stream, ((dr16 & 0x7) << 3) | 4, 1); \ 140294006Sarybchik emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 141294006Sarybchik} while (0) 142284555Sarybchik 143284555Sarybchik/* movb (sr32,or32,1),dr8 */ 144284555Sarybchik#define MOVobb(sr32, or32, dr8) do { \ 145284555Sarybchik emitm(&stream, 0x8a, 1); \ 146294377Sarybchik emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \ 147294377Sarybchik emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 148301340Sarybchik} while (0) 149294377Sarybchik 150294377Sarybchik/* movl sr32,(dr32,or32,1) */ 151294377Sarybchik#define MOVomd(sr32, dr32, or32) do { \ 152294377Sarybchik emitm(&stream, 0x89, 1); \ 153294377Sarybchik emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \ 154294377Sarybchik emitm(&stream, ((or32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 155294377Sarybchik} while (0) 156294377Sarybchik 157294377Sarybchik/* bswapl dr32 */ 158294377Sarybchik#define BSWAP(dr32) do { \ 159294377Sarybchik emitm(&stream, 0xf, 1); \ 160294377Sarybchik emitm(&stream, (0x19 << 3) | dr32, 1); \ 161294377Sarybchik} while (0) 162294377Sarybchik 163294377Sarybchik/* xchgb %al,%ah */ 164294377Sarybchik#define SWAP_AX() do { \ 165294377Sarybchik emitm(&stream, 0xc486, 2); \ 166293927Sarybchik} while (0) 167227569Sphilip 168227569Sphilip/* pushl r32 */ 169227569Sphilip#define PUSH(r32) do { \ 170227569Sphilip emitm(&stream, (5 << 4) | (0 << 3) | (r32 & 0x7), 1); \ 171227569Sphilip} while (0) 172227569Sphilip 173227569Sphilip/* popl r32 */ 174227569Sphilip#define POP(r32) do { \ 175293927Sarybchik emitm(&stream, (5 << 4) | (1 << 3) | (r32 & 0x7), 1); \ 176227569Sphilip} while (0) 177227569Sphilip 178227569Sphilip/* leave */ 179227569Sphilip#define LEAVE() do { \ 180227569Sphilip emitm(&stream, 0xc9, 1); \ 181227569Sphilip} while (0) 182227569Sphilip 183227569Sphilip/* ret */ 184227569Sphilip#define RET() do { \ 185227569Sphilip emitm(&stream, 0xc3, 1); \ 186227569Sphilip} while (0) 187227569Sphilip 188227569Sphilip/* addl sr32,dr32 */ 189227569Sphilip#define ADDrd(sr32, dr32) do { \ 190227569Sphilip emitm(&stream, 0x01, 1); \ 191227569Sphilip emitm(&stream, \ 192227569Sphilip (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 193301340Sarybchik} while (0) 194280563Sarybchik 195280563Sarybchik/* addl i32,%eax */ 196227569Sphilip#define ADD_EAXi(i32) do { \ 197280563Sarybchik emitm(&stream, 0x05, 1); \ 198280563Sarybchik emitm(&stream, i32, 4); \ 199280563Sarybchik} while (0) 200280535Sarybchik 201284555Sarybchik/* addl i8,r32 */ 202284555Sarybchik#define ADDib(i8, r32) do { \ 203227569Sphilip emitm(&stream, 0x83, 1); \ 204227569Sphilip emitm(&stream, (24 << 3) | r32, 1); \ 205227569Sphilip emitm(&stream, i8, 1); \ 206284555Sarybchik} while (0) 207284555Sarybchik 208301340Sarybchik/* subl sr32,dr32 */ 209284555Sarybchik#define SUBrd(sr32, dr32) do { \ 210284555Sarybchik emitm(&stream, 0x29, 1); \ 211284555Sarybchik emitm(&stream, \ 212284555Sarybchik (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 213284555Sarybchik} while (0) 214284555Sarybchik 215284555Sarybchik/* subl i32,%eax */ 216284555Sarybchik#define SUB_EAXi(i32) do { \ 217294381Sarybchik emitm(&stream, 0x2d, 1); \ 218342524Sarybchik emitm(&stream, i32, 4); \ 219342524Sarybchik} while (0) 220284555Sarybchik 221284555Sarybchik/* subl i8,r32 */ 222284555Sarybchik#define SUBib(i8, r32) do { \ 223294377Sarybchik emitm(&stream, 0x83, 1); \ 224294377Sarybchik emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \ 225301340Sarybchik emitm(&stream, i8, 1); \ 226294377Sarybchik} while (0) 227294377Sarybchik 228294377Sarybchik/* mull r32 */ 229294377Sarybchik#define MULrd(r32) do { \ 230294377Sarybchik emitm(&stream, 0xf7, 1); \ 231294377Sarybchik emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \ 232294377Sarybchik} while (0) 233294377Sarybchik 234294377Sarybchik/* divl r32 */ 235294377Sarybchik#define DIVrd(r32) do { \ 236294377Sarybchik emitm(&stream, 0xf7, 1); \ 237301372Sarybchik emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \ 238342524Sarybchik} while (0) 239342524Sarybchik 240294377Sarybchik/* andb i8,r8 */ 241294377Sarybchik#define ANDib(i8, r8) do { \ 242294377Sarybchik if (r8 == AL) { \ 243227569Sphilip emitm(&stream, 0x24, 1); \ 244227569Sphilip } else { \ 245227569Sphilip emitm(&stream, 0x80, 1); \ 246227569Sphilip emitm(&stream, (7 << 5) | r8, 1); \ 247227569Sphilip } \ 248227569Sphilip emitm(&stream, i8, 1); \ 249227569Sphilip} while (0) 250227569Sphilip 251227569Sphilip/* andl i32,r32 */ 252227569Sphilip#define ANDid(i32, r32) do { \ 253227569Sphilip if (r32 == EAX) { \ 254227569Sphilip emitm(&stream, 0x25, 1); \ 255227569Sphilip } else { \ 256227569Sphilip emitm(&stream, 0x81, 1); \ 257227569Sphilip emitm(&stream, (7 << 5) | r32, 1); \ 258284555Sarybchik } \ 259227569Sphilip emitm(&stream, i32, 4); \ 260227569Sphilip} while (0) 261227569Sphilip 262227569Sphilip/* andl sr32,dr32 */ 263227569Sphilip#define ANDrd(sr32, dr32) do { \ 264227569Sphilip emitm(&stream, 0x21, 1); \ 265227569Sphilip emitm(&stream, \ 266293927Sarybchik (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 267227569Sphilip} while (0) 268227569Sphilip 269227569Sphilip/* testl i32,r32 */ 270227569Sphilip#define TESTid(i32, r32) do { \ 271293927Sarybchik if (r32 == EAX) { \ 272227569Sphilip emitm(&stream, 0xa9, 1); \ 273227569Sphilip } else { \ 274227569Sphilip emitm(&stream, 0xf7, 1); \ 275301340Sarybchik emitm(&stream, (3 << 6) | r32, 1); \ 276293927Sarybchik } \ 277227569Sphilip emitm(&stream, i32, 4); \ 278227569Sphilip} while (0) 279227569Sphilip 280227569Sphilip/* testl sr32,dr32 */ 281227569Sphilip#define TESTrd(sr32, dr32) do { \ 282227569Sphilip emitm(&stream, 0x85, 1); \ 283227569Sphilip emitm(&stream, \ 284227569Sphilip (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 285227569Sphilip} while (0) 286284555Sarybchik 287227569Sphilip/* orl sr32,dr32 */ 288227569Sphilip#define ORrd(sr32, dr32) do { \ 289284555Sarybchik emitm(&stream, 0x09, 1); \ 290227569Sphilip emitm(&stream, \ 291227569Sphilip (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 292227569Sphilip} while (0) 293227569Sphilip 294227569Sphilip/* orl i32,r32 */ 295284555Sarybchik#define ORid(i32, r32) do { \ 296284555Sarybchik if (r32 == EAX) { \ 297227569Sphilip emitm(&stream, 0x0d, 1); \ 298227569Sphilip } else { \ 299227569Sphilip emitm(&stream, 0x81, 1); \ 300227569Sphilip emitm(&stream, (25 << 3) | r32, 1); \ 301293927Sarybchik } \ 302227569Sphilip emitm(&stream, i32, 4); \ 303227569Sphilip} while (0) 304227569Sphilip 305227569Sphilip/* shll i8,r32 */ 306293927Sarybchik#define SHLib(i8, r32) do { \ 307284555Sarybchik emitm(&stream, 0xc1, 1); \ 308284555Sarybchik emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \ 309284555Sarybchik emitm(&stream, i8, 1); \ 310284555Sarybchik} while (0) 311301340Sarybchik 312293927Sarybchik/* shll %cl,dr32 */ 313284555Sarybchik#define SHL_CLrb(dr32) do { \ 314284555Sarybchik emitm(&stream, 0xd3, 1); \ 315284555Sarybchik emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \ 316284555Sarybchik} while (0) 317284555Sarybchik 318284555Sarybchik/* shrl i8,r32 */ 319284555Sarybchik#define SHRib(i8, r32) do { \ 320284555Sarybchik emitm(&stream, 0xc1, 1); \ 321284555Sarybchik emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \ 322284555Sarybchik emitm(&stream, i8, 1); \ 323284555Sarybchik} while (0) 324284555Sarybchik 325293927Sarybchik/* shrl %cl,dr32 */ 326284555Sarybchik#define SHR_CLrb(dr32) do { \ 327284555Sarybchik emitm(&stream, 0xd3, 1); \ 328284555Sarybchik emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \ 329284555Sarybchik} while (0) 330293927Sarybchik 331284555Sarybchik/* negl r32 */ 332284555Sarybchik#define NEGd(r32) do { \ 333284555Sarybchik emitm(&stream, 0xf7, 1); \ 334284555Sarybchik emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \ 335284555Sarybchik} while (0) 336284555Sarybchik 337301340Sarybchik/* cmpl sr32,dr32 */ 338293927Sarybchik#define CMPrd(sr32, dr32) do { \ 339284555Sarybchik emitm(&stream, 0x39, 1); \ 340284555Sarybchik emitm(&stream, \ 341284555Sarybchik (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 342284555Sarybchik} while (0) 343284555Sarybchik 344284555Sarybchik/* cmpl i32,dr32 */ 345284555Sarybchik#define CMPid(i32, dr32) do { \ 346284555Sarybchik if (dr32 == EAX){ \ 347284555Sarybchik emitm(&stream, 0x3d, 1); \ 348284555Sarybchik emitm(&stream, i32, 4); \ 349284555Sarybchik } else { \ 350284555Sarybchik emitm(&stream, 0x81, 1); \ 351284555Sarybchik emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \ 352284555Sarybchik emitm(&stream, i32, 4); \ 353284555Sarybchik } \ 354284555Sarybchik} while (0) 355284555Sarybchik 356284555Sarybchik/* jb off8 */ 357284555Sarybchik#define JBb(off8) do { \ 358284555Sarybchik emitm(&stream, 0x72, 1); \ 359293927Sarybchik emitm(&stream, off8, 1); \ 360284555Sarybchik} while (0) 361284555Sarybchik 362284555Sarybchik/* jae off8 */ 363284555Sarybchik#define JAEb(off8) do { \ 364284555Sarybchik emitm(&stream, 0x73, 1); \ 365293927Sarybchik emitm(&stream, off8, 1); \ 366284555Sarybchik} while (0) 367284555Sarybchik 368284555Sarybchik/* jne off8 */ 369284555Sarybchik#define JNEb(off8) do { \ 370284555Sarybchik emitm(&stream, 0x75, 1); \ 371284555Sarybchik emitm(&stream, off8, 1); \ 372301340Sarybchik} while (0) 373284555Sarybchik 374293927Sarybchik/* ja off8 */ 375284555Sarybchik#define JAb(off8) do { \ 376284555Sarybchik emitm(&stream, 0x77, 1); \ 377284555Sarybchik emitm(&stream, off8, 1); \ 378284555Sarybchik} while (0) 379284555Sarybchik 380284555Sarybchik/* jmp off32 */ 381284555Sarybchik#define JMP(off32) do { \ 382284555Sarybchik emitm(&stream, 0xe9, 1); \ 383284555Sarybchik emitm(&stream, off32, 4); \ 384284555Sarybchik} while (0) 385284555Sarybchik 386284555Sarybchik/* xorl r32,r32 */ 387284555Sarybchik#define ZEROrd(r32) do { \ 388284555Sarybchik emitm(&stream, 0x31, 1); \ 389284555Sarybchik emitm(&stream, (3 << 6) | ((r32 & 0x7) << 3) | (r32 & 0x7), 1); \ 390284555Sarybchik} while (0) 391284555Sarybchik 392284555Sarybchik/* 393284555Sarybchik * Conditional long jumps 394284555Sarybchik */ 395284555Sarybchik#define JB 0x82 396284555Sarybchik#define JAE 0x83 397284555Sarybchik#define JE 0x84 398284555Sarybchik#define JNE 0x85 399293927Sarybchik#define JBE 0x86 400284555Sarybchik#define JA 0x87 401284555Sarybchik 402284555Sarybchik#define JCC(t, f) do { \ 403284555Sarybchik if (ins->jt != 0 && ins->jf != 0) { \ 404284555Sarybchik /* 5 is the size of the following jmp */ \ 405293927Sarybchik emitm(&stream, ((t) << 8) | 0x0f, 2); \ 406227569Sphilip emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \ 407227569Sphilip stream.refs[stream.bpf_pc] + 5, 4); \ 408227569Sphilip JMP(stream.refs[stream.bpf_pc + ins->jf] - \ 409301340Sarybchik stream.refs[stream.bpf_pc]); \ 410293927Sarybchik } else if (ins->jt != 0) { \ 411227569Sphilip emitm(&stream, ((t) << 8) | 0x0f, 2); \ 412227569Sphilip emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \ 413227569Sphilip stream.refs[stream.bpf_pc], 4); \ 414227569Sphilip } else { \ 415227569Sphilip emitm(&stream, ((f) << 8) | 0x0f, 2); \ 416227569Sphilip emitm(&stream, stream.refs[stream.bpf_pc + ins->jf] - \ 417227569Sphilip stream.refs[stream.bpf_pc], 4); \ 418227569Sphilip } \ 419227569Sphilip} while (0) 420227569Sphilip 421227569Sphilip#define JUMP(off) do { \ 422227569Sphilip if ((off) != 0) \ 423227569Sphilip JMP(stream.refs[stream.bpf_pc + (off)] - \ 424227569Sphilip stream.refs[stream.bpf_pc]); \ 425227569Sphilip} while (0) 426227569Sphilip 427227569Sphilip#endif /* _BPF_JIT_MACHDEP_H_ */ 428227569Sphilip