BPF Dependent Features
**********************

Options
=======

-EB
     This option specifies that the assembler should emit big-endian eBPF.

-EL
     This option specifies that the assembler should emit little-endian eBPF.

Note that if no endianness option is specified in the command line, the host endianness is used.

Syntax
======

Special Characters
------------------

The presence of a ; on a line indicates the start of a comment that extends to the end of the current line.  If a # appears as the first character of a line, the whole line is treated as a comment.

Statements and assembly directives are separated by newlines.

Register Names
--------------

The eBPF processor provides ten general-purpose 64-bit registers, which are read-write, and a read-only frame pointer register:

%r0 .. %r9
     General-purpose registers.

%r10
     Frame pointer register.

Some registers have additional names, to reflect their role in the eBPF ABI:

%a
     This is %r0.

%ctx
     This is %r6.

%fp
     This is %r10.

Pseudo Maps
-----------

The LDDW instruction can take a literal pseudo map file descriptor as its second argument.  This uses the syntax %map_fd(N) where N is a signed number.

For example, to load the address of the pseudo map with file descriptor 2 in register r1 we would do:

             lddw %r1, %map_fd(2)

Machine Directives
==================

The BPF version of AS supports the following additional machine directives:

.word
     The .half directive produces a 16 bit value.

.word
     The .word directive produces a 32 bit value.

.dword
     The .dword directive produces a 64 bit value.

Opcodes
=======

In the instruction descriptions below the following field descriptors are used:

%d
     Destination general-purpose register whose role is to be destination of an operation.

%s
     Source general-purpose register whose role is to be the source of an operation.

disp16
     16-bit signed PC-relative offset, measured in number of 64-bit words, minus one.

disp32
     32-bit signed PC-relative offset, measured in number of 64-bit words, minus one.

offset16
     Signed 16-bit immediate.

imm32
     Signed 32-bit immediate.

imm64
     Signed 64-bit immediate.

Arithmetic instructions
.......................

The destination register in these instructions act like an accumulator.

add %d, (%s|imm32)
     64-bit arithmetic addition.

sub %d, (%s|imm32)
     64-bit arithmetic subtraction.

mul %d, (%s|imm32)
     64-bit arithmetic multiplication.

div %d, (%s|imm32)
     64-bit arithmetic integer division.

mod %d, (%s|imm32)
     64-bit integer remainder.

and %d, (%s|imm32)
     64-bit bit-wise ``and'' operation.

or %d, (%s|imm32)
     64-bit bit-wise ``or'' operation.

xor %d, (%s|imm32)
     64-bit bit-wise exclusive-or operation.

lsh %d, (%s|imm32)
     64-bit left shift, by %s or imm32 bits.

rsh %d, (%s|imm32)
     64-bit right logical shift, by %s or imm32 bits.

arsh %d, (%s|imm32)
     64-bit right arithmetic shift, by %s or imm32 bits.

neg %d
     64-bit arithmetic negation.

mov %d, (%s|imm32)
     Move the 64-bit value of %s in %d, or load imm32 in %d.

32-bit arithmetic instructions
..............................

The destination register in these instructions act as an accumulator.

add32 %d, (%s|imm32)
     32-bit arithmetic addition.

sub32 %d, (%s|imm32)
     32-bit arithmetic subtraction.

mul32 %d, (%s|imm32)
     32-bit arithmetic multiplication.

div32 %d, (%s|imm32)
     32-bit arithmetic integer division.

mod32 %d, (%s|imm32)
     32-bit integer remainder.

and32 %d, (%s|imm32)
     32-bit bit-wise ``and'' operation.

or32 %d, (%s|imm32)
     32-bit bit-wise ``or'' operation.

xor32 %d, (%s|imm32)
     32-bit bit-wise exclusive-or operation.

lsh32 %d, (%s|imm32)
     32-bit left shift, by %s or imm32 bits.

rsh32 %d, (%s|imm32)
     32-bit right logical shift, by %s or imm32 bits.

arsh32 %d, (%s|imm32)
     32-bit right arithmetic shift, by %s or imm32 bits.

neg32 %d
     32-bit arithmetic negation.

mov32 %d, (%s|imm32)
     Move the 32-bit value of %s in %d, or load imm32 in %d.

Endianness conversion instructions
..................................

endle %d, (16|32|64)
     Convert the 16-bit, 32-bit or 64-bit value in %d to little-endian.

endbe %d, (16|32|64)
     Convert the 16-bit, 32-bit or 64-bit value in %d to big-endian.

64-bit load and pseudo maps
...........................

lddw %d, imm64
     Load the given signed 64-bit immediate, or pseudo map descriptor, to the destination register %d.

lddw %d, %map_fd(N)
     Load the address of the given pseudo map fd N to the destination register %d.

Load instructions for socket filters
....................................

The following instructions are intended to be used in socket filters, and are therefore not general-purpose: they make assumptions on the contents of several registers.  See the file Documentation/networking/filter.txt in the Linux kernel source tree for more information.

Absolute loads:

ldabsdw imm32
     Absolute 64-bit load.

ldabsw imm32
     Absolute 32-bit load.

ldabsh imm32
     Absolute 16-bit load.

ldabsb imm32
     Absolute 8-bit load.

Indirect loads:

ldinddw %s, imm32
     Indirect 64-bit load.

ldindw %s, imm32
     Indirect 32-bit load.

ldindh %s, imm32
     Indirect 16-bit load.

ldindb %s, imm32
     Indirect 8-bit load.

Generic load/store instructions
...............................

General-purpose load and store instructions are provided for several word sizes.

Load to register instructions:

ldxdw %d, [%s+offset16]
     Generic 64-bit load.

ldxw %d, [%s+offset16]
     Generic 32-bit load.

ldxh %d, [%s+offset16]
     Generic 16-bit load.

ldxb %d, [%s+offset16]
     Generic 8-bit load.

Store from register instructions:

stxdw [%d+offset16], %s
     Generic 64-bit store.

stxw [%d+offset16], %s
     Generic 32-bit store.

stxh [%d+offset16], %s
     Generic 16-bit store.

stxb [%d+offset16], %s
     Generic 8-bit store.

Store from immediates instructions:

stddw [%d+offset16], imm32
     Store immediate as 64-bit.

stdw [%d+offset16], imm32
     Store immediate as 32-bit.

stdh [%d+offset16], imm32
     Store immediate as 16-bit.

stdb [%d+offset16], imm32
     Store immediate as 8-bit.

Jump instructions
.................

eBPF provides the following compare-and-jump instructions, which compare the values of the two given registers, or the values of a register and an immediate, and perform a branch in case the comparison holds true.

ja %d,(%s|imm32),disp16
     Jump-always.

jeq %d,(%s|imm32),disp16
     Jump if equal, unsigned.

jgt %d,(%s|imm32),disp16
     Jump if greater, unsigned.

jge %d,(%s|imm32),disp16
     Jump if greater or equal.

jlt %d,(%s|imm32),disp16
     Jump if lesser.

jle %d,(%s|imm32),disp16
     Jump if lesser or equal.

jset %d,(%s|imm32),disp16
     Jump if signed equal.

jne %d,(%s|imm32),disp16
     Jump if not equal.

jsgt %d,(%s|imm32),disp16
     Jump if signed greater.

jsge %d,(%s|imm32),disp16
     Jump if signed greater or equal.

jslt %d,(%s|imm32),disp16
     Jump if signed lesser.

jsle %d,(%s|imm32),disp16
     Jump if signed lesser or equal.

A call instruction is provided in order to perform calls to other eBPF functions, or to external kernel helpers:

call (disp32|imm32)
     Jump and link to the offset disp32, or to the kernel helper function identified by imm32.

Finally:

exit
     Terminate the eBPF program.

Atomic instructions
...................

Atomic exchange-and-add instructions are provided in two flavors: one for swapping 64-bit quantities and another for 32-bit quantities.

xadddw [%d+offset16],%s
     Exchange-and-add a 64-bit value at the specified location.

xaddw [%d+offset16],%s
     Exchange-and-add a 32-bit value at the specified location.

BPF Pseudo-C Syntax
===================

This assembler supports another syntax to denote BPF instructions, which is an alternative to the normal looking syntax documented above. This alternatative syntax, which we call pseudo-C syntax, is supported by the LLVM/clang integrated assembler.

This syntax is very unconventional, but we need to support it in order to support inline assembly in existing BPF programs.

Note that the assembler is able to parse sources in which both syntaxes coexist: some instructions can use the usual assembly like syntax, whereas some other instructions in the same file can use the pseudo-C syntax.

Pseudo-C Register Names
.......................

All BPF registers are 64-bit long.  However, in the Pseudo-C syntax registers can be referred using different names, which actually reflect the kind of instruction they appear on:

r0..r9
     General-purpose register in an instruction that operates on its value as if it was a 64-bit value.

w0..w9
     General-purpose register in an instruction that operates on its value as if it was a 32-bit value.

Note that in the Pseudo-C syntax register names are not preceded by % characters.

Arithmetic instructions
.......................

In all the instructions below, the operations are 64-bit or 32-bit depending on the names used to refer to the registers.  For example r3 += r2 will perform 64-bit addition, whereas w3 += w2 will perform 32-bit addition.  Mixing register prefixes is an error, for example r3 += w2.

dst_reg += (imm32|src_reg)
     Arithmetic addition.

dst_reg -= (imm32|src_reg)
     Arithmetic subtraction.

dst_reg *= (imm32|src_reg)
     Arithmetic multiplication.

dst_reg /= (imm32|src_reg)
     Arithmetic integer unsigned division.

dst_reg %= (imm32|src_reg)
     Arithmetic integer unsigned remainder.

dst_reg &= (imm32|src_reg)
     Bit-wise ``and'' operation.

dst_reg |= (imm32|src_reg)
     Bit-wise ``or'' operation.

dst_reg ^= (imm32|src_reg)
     Bit-wise exclusive-or operation.

dst_reg <<= (imm32|src_reg)
     Left shift, by whatever specified number of bits.

dst_reg >>= (imm32|src_reg)
     Right logical shift, by whatever specified number of bits.

dst_reg s>>= (imm32|src_reg)
     Right arithmetic shift, by whatever specified number of bits.

dst_reg = (imm32|src_reg)
     Move the value in imm32 or src_reg in dst_reg.

dst_reg = -dst_reg
     Arithmetic negation.

Endianness conversion instructions
..................................

dst_reg = le16 src_reg
     Convert the 16-bit value in src_reg to little-endian.

dst_reg = le32 src_reg
     Convert the 32-bit value in src_reg to little-endian.

dst_reg = le64 src_reg
     Convert the 64-bit value in src_reg to little-endian.

dst_reg = be16 src_reg
     Convert the 16-bit value in src_reg to big-endian.

dst_reg = be32 src_reg
     Convert the 32-bit value in src_reg to big-endian.

dst_reg = be64 src_reg
     Convert the 64-bit value in src_reg to big-endian.

64-bit load and pseudo maps
...........................

dst_reg = imm64 ll
     Load the given signed 64-bit immediate, or pseudo map descriptor, to the destination register dst_reg.

Load instructions for socket filters
....................................

r0 = *(u8 *)skb[imm32]
     Absolute 8-bit load.

r0 = *(u16 *)skb[imm32]
     Absolute 16-bit load.

r0 = *(u32 *)skb[imm32]
     Absolute 32-bit load.

r0 = *(u64 *)skb[imm32]
     Absolute 64-bit load.

r0 = *(u8 *)skb[src_reg + imm32]
     Indirect 8-bit load.

r0 = *(u16 *)skb[src_reg + imm32]
     Indirect 16-bit load.

r0 = *(u32 *)skb[src_reg + imm32]
     Indirect 32-bit load.

r0 = *(u64 *)skb[src_reg + imm32]
     Indirect 64-bit load.

Generic load/store instructions
...............................

dst_reg = *(u8 *)(src_reg + offset16)
     Generic 8-bit load.

dst_reg = *(u16 *)(src_reg + offset16)
     Generic 16-bit load.

dst_reg = *(u32 *)(src_reg + offset16)
     Generic 32-bit load.

dst_reg = *(u64 *)(src_reg + offset16)
     Generic 64-bit load.

*(u8 *)(dst_reg + offset16) = src_reg
     Generic 8-bit store.

*(u16 *)(dst_reg + offset16) = src_reg
     Generic 16-bit store.

*(u32 *)(dst_reg + offset16) = src_reg
     Generic 32-bit store.

*(u64 *)(dst_reg + offset16) = src_reg
     Generic 64-bit store.

Jump instructions
.................

goto disp16
     Jump-always.

if dst_reg == (imm32|src_reg) goto disp16
     Jump if equal.

if dst_reg & (imm32|src_reg) goto disp16
     Jump if signed equal.

if dst_reg != (imm32|src_reg) goto disp16
     Jump if not equal.

if dst_reg > (imm32|src_reg) goto disp16
     Jump if bigger, unsigned.

if dst_reg < (imm32|src_reg) goto disp16
     Jump if smaller, unsigned.

if dst_reg >= (imm32|src_reg) goto disp16
     Jump if bigger or equal, unsigned.

if dst_reg <= (imm32|src_reg) goto disp16
     Jump if smaller or equal, unsigned.

if dst_reg s> (imm32|src_reg) goto disp16
     Jump if bigger, signed.

if dst_reg s< (imm32|src_reg) goto disp16
     Jump if smaller, signed.

if dst_reg s>= (imm32|src_reg) goto disp16
     Jump if bigger or equal, signed.

if dst_reg s<= (imm32|src_reg) goto disp16
     Jump if smaller or equal, signed.

call imm32
     Jump and link.

exit
     Terminate the eBPF program.

Atomic instructions
...................

lock *(u64 *)(dst_reg + offset16) += src_reg
     Exchange-and-add a 64-bit value at the specified location.

lock *(u32 *)(dst_reg + offset16) += src_reg
     Exchange-and-add a 32-bit value at the specified location.