1153151Sjkim/*- 2181648Sjkim * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy) 3199492Sjkim * Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org> 4153151Sjkim * All rights reserved. 5153151Sjkim * 6153151Sjkim * Redistribution and use in source and binary forms, with or without 7153151Sjkim * modification, are permitted provided that the following conditions 8153151Sjkim * are met: 9153151Sjkim * 10153151Sjkim * 1. Redistributions of source code must retain the above copyright 11153151Sjkim * notice, this list of conditions and the following disclaimer. 12153151Sjkim * 2. Redistributions in binary form must reproduce the above copyright 13153151Sjkim * notice, this list of conditions and the following disclaimer in the 14153151Sjkim * documentation and/or other materials provided with the distribution. 15153151Sjkim * 3. Neither the name of the Politecnico di Torino nor the names of its 16153151Sjkim * contributors may be used to endorse or promote products derived from 17153151Sjkim * this software without specific prior written permission. 18153151Sjkim * 19153151Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20153151Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21153151Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22153151Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23153151Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24153151Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25153151Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26182173Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27153151Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28153151Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29153151Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30153151Sjkim * 31153151Sjkim * $FreeBSD$ 32153151Sjkim */ 33153151Sjkim 34153151Sjkim#ifndef _BPF_JIT_MACHDEP_H_ 35153151Sjkim#define _BPF_JIT_MACHDEP_H_ 36153151Sjkim 37153151Sjkim/* 38153151Sjkim * Registers 39153151Sjkim */ 40153151Sjkim#define EAX 0 41153151Sjkim#define ECX 1 42153151Sjkim#define EDX 2 43153151Sjkim#define EBX 3 44153151Sjkim#define ESP 4 45153151Sjkim#define EBP 5 46153151Sjkim#define ESI 6 47153151Sjkim#define EDI 7 48153151Sjkim 49153151Sjkim#define AX 0 50153151Sjkim#define CX 1 51153151Sjkim#define DX 2 52153151Sjkim#define BX 3 53153151Sjkim#define SP 4 54153151Sjkim#define BP 5 55153151Sjkim#define SI 6 56153151Sjkim#define DI 7 57153151Sjkim 58153151Sjkim#define AL 0 59153151Sjkim#define CL 1 60153151Sjkim#define DL 2 61153151Sjkim#define BL 3 62153151Sjkim 63199619Sjkim/* Optimization flags */ 64199721Sjkim#define BPF_JIT_FRET 0x01 65199721Sjkim#define BPF_JIT_FPKT 0x02 66199721Sjkim#define BPF_JIT_FMEM 0x04 67199721Sjkim#define BPF_JIT_FJMP 0x08 68199721Sjkim#define BPF_JIT_FADK 0x10 69199619Sjkim 70199619Sjkim#define BPF_JIT_FLAG_ALL \ 71199721Sjkim (BPF_JIT_FPKT | BPF_JIT_FMEM | BPF_JIT_FJMP | BPF_JIT_FADK) 72199619Sjkim 73199619Sjkim/* A stream of native binary code */ 74153151Sjkimtypedef struct bpf_bin_stream { 75153151Sjkim /* Current native instruction pointer. */ 76153151Sjkim int cur_ip; 77153151Sjkim 78153151Sjkim /* 79153151Sjkim * Current BPF instruction pointer, i.e. position in 80153151Sjkim * the BPF program reached by the jitter. 81153151Sjkim */ 82153151Sjkim int bpf_pc; 83153151Sjkim 84153151Sjkim /* Instruction buffer, contains the generated native code. */ 85153151Sjkim char *ibuf; 86153151Sjkim 87153151Sjkim /* Jumps reference table. */ 88153151Sjkim u_int *refs; 89153151Sjkim} bpf_bin_stream; 90153151Sjkim 91153151Sjkim/* 92153151Sjkim * Prototype of the emit functions. 93153151Sjkim * 94153151Sjkim * Different emit functions are used to create the reference table and 95153151Sjkim * to generate the actual filtering code. This allows to have simpler 96153151Sjkim * instruction macros. 97153151Sjkim * The first parameter is the stream that will receive the data. 98153151Sjkim * The second one is a variable containing the data. 99153151Sjkim * The third one is the length, that can be 1, 2, or 4 since it is possible 100153151Sjkim * to emit a byte, a short, or a word at a time. 101153151Sjkim */ 102153151Sjkimtypedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n); 103153151Sjkim 104153151Sjkim/* 105199619Sjkim * Native instruction macros 106153151Sjkim */ 107153151Sjkim 108179968Sjkim/* movl i32,r32 */ 109179968Sjkim#define MOVid(i32, r32) do { \ 110153151Sjkim emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \ 111153151Sjkim emitm(&stream, i32, 4); \ 112153151Sjkim} while (0) 113153151Sjkim 114179968Sjkim/* movl sr32,dr32 */ 115179968Sjkim#define MOVrd(sr32, dr32) do { \ 116179978Sjkim emitm(&stream, 0x89, 1); \ 117153151Sjkim emitm(&stream, \ 118179978Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 119153151Sjkim} while (0) 120153151Sjkim 121179968Sjkim/* movl off(sr32),dr32 */ 122179968Sjkim#define MOVodd(off, sr32, dr32) do { \ 123179978Sjkim emitm(&stream, 0x8b, 1); \ 124153151Sjkim emitm(&stream, \ 125153151Sjkim (1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 126153151Sjkim emitm(&stream, off, 1); \ 127153151Sjkim} while (0) 128153151Sjkim 129179968Sjkim/* movl (sr32,or32,1),dr32 */ 130179968Sjkim#define MOVobd(sr32, or32, dr32) do { \ 131179978Sjkim emitm(&stream, 0x8b, 1); \ 132153151Sjkim emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \ 133153151Sjkim emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 134153151Sjkim} while (0) 135153151Sjkim 136179968Sjkim/* movw (sr32,or32,1),dr16 */ 137179968Sjkim#define MOVobw(sr32, or32, dr16) do { \ 138179978Sjkim emitm(&stream, 0x8b66, 2); \ 139179968Sjkim emitm(&stream, ((dr16 & 0x7) << 3) | 4, 1); \ 140153151Sjkim emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 141153151Sjkim} while (0) 142153151Sjkim 143179968Sjkim/* movb (sr32,or32,1),dr8 */ 144179968Sjkim#define MOVobb(sr32, or32, dr8) do { \ 145153151Sjkim emitm(&stream, 0x8a, 1); \ 146153151Sjkim emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \ 147153151Sjkim emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \ 148153151Sjkim} while (0) 149153151Sjkim 150179968Sjkim/* movl sr32,(dr32,or32,1) */ 151179968Sjkim#define MOVomd(sr32, dr32, or32) do { \ 152153151Sjkim emitm(&stream, 0x89, 1); \ 153153151Sjkim emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \ 154153151Sjkim emitm(&stream, ((or32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 155153151Sjkim} while (0) 156153151Sjkim 157179968Sjkim/* bswapl dr32 */ 158153151Sjkim#define BSWAP(dr32) do { \ 159153151Sjkim emitm(&stream, 0xf, 1); \ 160153151Sjkim emitm(&stream, (0x19 << 3) | dr32, 1); \ 161153151Sjkim} while (0) 162153151Sjkim 163179968Sjkim/* xchgb %al,%ah */ 164153151Sjkim#define SWAP_AX() do { \ 165179978Sjkim emitm(&stream, 0xc486, 2); \ 166153151Sjkim} while (0) 167153151Sjkim 168179968Sjkim/* pushl r32 */ 169153151Sjkim#define PUSH(r32) do { \ 170153151Sjkim emitm(&stream, (5 << 4) | (0 << 3) | (r32 & 0x7), 1); \ 171153151Sjkim} while (0) 172153151Sjkim 173179968Sjkim/* popl r32 */ 174153151Sjkim#define POP(r32) do { \ 175153151Sjkim emitm(&stream, (5 << 4) | (1 << 3) | (r32 & 0x7), 1); \ 176153151Sjkim} while (0) 177153151Sjkim 178199619Sjkim/* leave */ 179199619Sjkim#define LEAVE() do { \ 180199619Sjkim emitm(&stream, 0xc9, 1); \ 181153151Sjkim} while (0) 182153151Sjkim 183199619Sjkim/* ret */ 184199619Sjkim#define RET() do { \ 185199619Sjkim emitm(&stream, 0xc3, 1); \ 186199619Sjkim} while (0) 187199619Sjkim 188179968Sjkim/* addl sr32,dr32 */ 189179968Sjkim#define ADDrd(sr32, dr32) do { \ 190179978Sjkim emitm(&stream, 0x01, 1); \ 191153151Sjkim emitm(&stream, \ 192179978Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 193153151Sjkim} while (0) 194153151Sjkim 195179968Sjkim/* addl i32,%eax */ 196153151Sjkim#define ADD_EAXi(i32) do { \ 197153151Sjkim emitm(&stream, 0x05, 1); \ 198153151Sjkim emitm(&stream, i32, 4); \ 199153151Sjkim} while (0) 200153151Sjkim 201179968Sjkim/* addl i8,r32 */ 202179968Sjkim#define ADDib(i8, r32) do { \ 203153151Sjkim emitm(&stream, 0x83, 1); \ 204153151Sjkim emitm(&stream, (24 << 3) | r32, 1); \ 205153151Sjkim emitm(&stream, i8, 1); \ 206153151Sjkim} while (0) 207153151Sjkim 208179968Sjkim/* subl sr32,dr32 */ 209179968Sjkim#define SUBrd(sr32, dr32) do { \ 210179978Sjkim emitm(&stream, 0x29, 1); \ 211153151Sjkim emitm(&stream, \ 212179978Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 213153151Sjkim} while (0) 214153151Sjkim 215179968Sjkim/* subl i32,%eax */ 216153151Sjkim#define SUB_EAXi(i32) do { \ 217153151Sjkim emitm(&stream, 0x2d, 1); \ 218153151Sjkim emitm(&stream, i32, 4); \ 219153151Sjkim} while (0) 220153151Sjkim 221199603Sjkim/* subl i8,r32 */ 222199603Sjkim#define SUBib(i8, r32) do { \ 223199603Sjkim emitm(&stream, 0x83, 1); \ 224199603Sjkim emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \ 225199603Sjkim emitm(&stream, i8, 1); \ 226199603Sjkim} while (0) 227199603Sjkim 228179968Sjkim/* mull r32 */ 229153151Sjkim#define MULrd(r32) do { \ 230153151Sjkim emitm(&stream, 0xf7, 1); \ 231153151Sjkim emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \ 232153151Sjkim} while (0) 233153151Sjkim 234179968Sjkim/* divl r32 */ 235153151Sjkim#define DIVrd(r32) do { \ 236153151Sjkim emitm(&stream, 0xf7, 1); \ 237153151Sjkim emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \ 238153151Sjkim} while (0) 239153151Sjkim 240179968Sjkim/* andb i8,r8 */ 241179968Sjkim#define ANDib(i8, r8) do { \ 242179978Sjkim if (r8 == AL) { \ 243179978Sjkim emitm(&stream, 0x24, 1); \ 244179978Sjkim } else { \ 245179978Sjkim emitm(&stream, 0x80, 1); \ 246179978Sjkim emitm(&stream, (7 << 5) | r8, 1); \ 247179978Sjkim } \ 248153151Sjkim emitm(&stream, i8, 1); \ 249153151Sjkim} while (0) 250153151Sjkim 251179968Sjkim/* andl i32,r32 */ 252179968Sjkim#define ANDid(i32, r32) do { \ 253153151Sjkim if (r32 == EAX) { \ 254153151Sjkim emitm(&stream, 0x25, 1); \ 255153151Sjkim } else { \ 256153151Sjkim emitm(&stream, 0x81, 1); \ 257153151Sjkim emitm(&stream, (7 << 5) | r32, 1); \ 258153151Sjkim } \ 259179978Sjkim emitm(&stream, i32, 4); \ 260153151Sjkim} while (0) 261153151Sjkim 262179968Sjkim/* andl sr32,dr32 */ 263179968Sjkim#define ANDrd(sr32, dr32) do { \ 264179978Sjkim emitm(&stream, 0x21, 1); \ 265153151Sjkim emitm(&stream, \ 266179978Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 267153151Sjkim} while (0) 268153151Sjkim 269181697Sjkim/* testl i32,r32 */ 270181697Sjkim#define TESTid(i32, r32) do { \ 271181697Sjkim if (r32 == EAX) { \ 272181697Sjkim emitm(&stream, 0xa9, 1); \ 273181697Sjkim } else { \ 274181697Sjkim emitm(&stream, 0xf7, 1); \ 275181697Sjkim emitm(&stream, (3 << 6) | r32, 1); \ 276181697Sjkim } \ 277181697Sjkim emitm(&stream, i32, 4); \ 278181697Sjkim} while (0) 279181697Sjkim 280181697Sjkim/* testl sr32,dr32 */ 281181697Sjkim#define TESTrd(sr32, dr32) do { \ 282181697Sjkim emitm(&stream, 0x85, 1); \ 283181697Sjkim emitm(&stream, \ 284181697Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 285181697Sjkim} while (0) 286181697Sjkim 287179968Sjkim/* orl sr32,dr32 */ 288179968Sjkim#define ORrd(sr32, dr32) do { \ 289179978Sjkim emitm(&stream, 0x09, 1); \ 290153151Sjkim emitm(&stream, \ 291179978Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 292153151Sjkim} while (0) 293153151Sjkim 294179968Sjkim/* orl i32,r32 */ 295179968Sjkim#define ORid(i32, r32) do { \ 296153151Sjkim if (r32 == EAX) { \ 297153151Sjkim emitm(&stream, 0x0d, 1); \ 298153151Sjkim } else { \ 299153151Sjkim emitm(&stream, 0x81, 1); \ 300153151Sjkim emitm(&stream, (25 << 3) | r32, 1); \ 301153151Sjkim } \ 302179978Sjkim emitm(&stream, i32, 4); \ 303153151Sjkim} while (0) 304153151Sjkim 305179968Sjkim/* shll i8,r32 */ 306179968Sjkim#define SHLib(i8, r32) do { \ 307153151Sjkim emitm(&stream, 0xc1, 1); \ 308153151Sjkim emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \ 309153151Sjkim emitm(&stream, i8, 1); \ 310153151Sjkim} while (0) 311153151Sjkim 312179968Sjkim/* shll %cl,dr32 */ 313153151Sjkim#define SHL_CLrb(dr32) do { \ 314153151Sjkim emitm(&stream, 0xd3, 1); \ 315153151Sjkim emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \ 316153151Sjkim} while (0) 317153151Sjkim 318179968Sjkim/* shrl i8,r32 */ 319179968Sjkim#define SHRib(i8, r32) do { \ 320153151Sjkim emitm(&stream, 0xc1, 1); \ 321153151Sjkim emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \ 322153151Sjkim emitm(&stream, i8, 1); \ 323153151Sjkim} while (0) 324153151Sjkim 325179968Sjkim/* shrl %cl,dr32 */ 326153151Sjkim#define SHR_CLrb(dr32) do { \ 327153151Sjkim emitm(&stream, 0xd3, 1); \ 328153151Sjkim emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \ 329153151Sjkim} while (0) 330153151Sjkim 331179968Sjkim/* negl r32 */ 332153151Sjkim#define NEGd(r32) do { \ 333153151Sjkim emitm(&stream, 0xf7, 1); \ 334153151Sjkim emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \ 335153151Sjkim} while (0) 336153151Sjkim 337179968Sjkim/* cmpl sr32,dr32 */ 338179968Sjkim#define CMPrd(sr32, dr32) do { \ 339179978Sjkim emitm(&stream, 0x39, 1); \ 340153151Sjkim emitm(&stream, \ 341179978Sjkim (3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \ 342153151Sjkim} while (0) 343153151Sjkim 344179968Sjkim/* cmpl i32,dr32 */ 345179968Sjkim#define CMPid(i32, dr32) do { \ 346153151Sjkim if (dr32 == EAX){ \ 347153151Sjkim emitm(&stream, 0x3d, 1); \ 348153151Sjkim emitm(&stream, i32, 4); \ 349153151Sjkim } else { \ 350153151Sjkim emitm(&stream, 0x81, 1); \ 351153151Sjkim emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \ 352153151Sjkim emitm(&stream, i32, 4); \ 353153151Sjkim } \ 354153151Sjkim} while (0) 355153151Sjkim 356181853Sjkim/* jb off8 */ 357181853Sjkim#define JBb(off8) do { \ 358181853Sjkim emitm(&stream, 0x72, 1); \ 359181853Sjkim emitm(&stream, off8, 1); \ 360181853Sjkim} while (0) 361181853Sjkim 362181853Sjkim/* jae off8 */ 363181853Sjkim#define JAEb(off8) do { \ 364181853Sjkim emitm(&stream, 0x73, 1); \ 365181853Sjkim emitm(&stream, off8, 1); \ 366181853Sjkim} while (0) 367181853Sjkim 368179968Sjkim/* jne off8 */ 369153151Sjkim#define JNEb(off8) do { \ 370153151Sjkim emitm(&stream, 0x75, 1); \ 371153151Sjkim emitm(&stream, off8, 1); \ 372153151Sjkim} while (0) 373153151Sjkim 374181853Sjkim/* ja off8 */ 375181853Sjkim#define JAb(off8) do { \ 376181853Sjkim emitm(&stream, 0x77, 1); \ 377153151Sjkim emitm(&stream, off8, 1); \ 378153151Sjkim} while (0) 379153151Sjkim 380153151Sjkim/* jmp off32 */ 381153151Sjkim#define JMP(off32) do { \ 382153151Sjkim emitm(&stream, 0xe9, 1); \ 383153151Sjkim emitm(&stream, off32, 4); \ 384153151Sjkim} while (0) 385153151Sjkim 386179978Sjkim/* xorl r32,r32 */ 387179978Sjkim#define ZEROrd(r32) do { \ 388153151Sjkim emitm(&stream, 0x31, 1); \ 389179978Sjkim emitm(&stream, (3 << 6) | ((r32 & 0x7) << 3) | (r32 & 0x7), 1); \ 390153151Sjkim} while (0) 391153151Sjkim 392181697Sjkim/* 393181697Sjkim * Conditional long jumps 394181697Sjkim */ 395181697Sjkim#define JB 0x82 396181697Sjkim#define JAE 0x83 397181697Sjkim#define JE 0x84 398181697Sjkim#define JNE 0x85 399181697Sjkim#define JBE 0x86 400181697Sjkim#define JA 0x87 401181697Sjkim 402181697Sjkim#define JCC(t, f) do { \ 403181697Sjkim if (ins->jt != 0 && ins->jf != 0) { \ 404181697Sjkim /* 5 is the size of the following jmp */ \ 405181697Sjkim emitm(&stream, ((t) << 8) | 0x0f, 2); \ 406181697Sjkim emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \ 407181697Sjkim stream.refs[stream.bpf_pc] + 5, 4); \ 408181697Sjkim JMP(stream.refs[stream.bpf_pc + ins->jf] - \ 409181697Sjkim stream.refs[stream.bpf_pc]); \ 410181697Sjkim } else if (ins->jt != 0) { \ 411181697Sjkim emitm(&stream, ((t) << 8) | 0x0f, 2); \ 412181697Sjkim emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \ 413181697Sjkim stream.refs[stream.bpf_pc], 4); \ 414181697Sjkim } else { \ 415181697Sjkim emitm(&stream, ((f) << 8) | 0x0f, 2); \ 416181697Sjkim emitm(&stream, stream.refs[stream.bpf_pc + ins->jf] - \ 417181697Sjkim stream.refs[stream.bpf_pc], 4); \ 418181697Sjkim } \ 419181697Sjkim} while (0) 420181697Sjkim 421207081Sjkim#define JUMP(off) do { \ 422207081Sjkim if ((off) != 0) \ 423207081Sjkim JMP(stream.refs[stream.bpf_pc + (off)] - \ 424207081Sjkim stream.refs[stream.bpf_pc]); \ 425207081Sjkim} while (0) 426207081Sjkim 427153151Sjkim#endif /* _BPF_JIT_MACHDEP_H_ */ 428