]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/bpf-opc.c
DesCGENization of the BPF binutils port
[thirdparty/binutils-gdb.git] / opcodes / bpf-opc.c
CommitLineData
d218e7fe
JM
1/* bpf-opc.c - BPF opcodes.
2 Copyright (C) 2023 Free Software Foundation, Inc.
79472b45 3
d218e7fe 4 Contributed by Oracle Inc.
79472b45 5
d218e7fe 6 This file is part of the GNU binutils.
79472b45 7
d218e7fe
JM
8 This is free software; you can redistribute them and/or modify them
9 under the terms of the GNU General Public License as published by
79472b45
JM
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
d218e7fe
JM
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
79472b45 17
d218e7fe
JM
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING3. If not,
20 see <http://www.gnu.org/licenses/>. */
79472b45 21
d218e7fe
JM
22#include "config.h"
23#include <stdlib.h>
24#include "opcode/bpf.h"
79472b45 25
d218e7fe
JM
26/* Note that the entries in the opcodes table below are accessed
27 sequentially when matching instructions per opcode, and also when
28 parsing. Please take care to keep the entries sorted
29 accordingly! */
79472b45 30
d218e7fe 31const struct bpf_opcode bpf_opcodes[] =
79472b45 32{
d218e7fe
JM
33 /* id, normal, pseudoc, version, mask, opcodes */
34
35 /* ALU instructions. */
36 {BPF_INSN_ADDR, "add%W%dr , %sr", "%dr += %sr",
37 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_ADD|BPF_SRC_X},
38 {BPF_INSN_ADDI, "add%W%dr , %i32", "%dr += %i32",
39 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_ADD|BPF_SRC_K},
40 {BPF_INSN_SUBR, "sub%W%dr , %sr", "%dr -= %sr",
41 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_SUB|BPF_SRC_X},
42 {BPF_INSN_SUBI, "sub%W%dr , %i32", "%dr -= %i32",
43 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_SUB|BPF_SRC_K},
44 {BPF_INSN_MULR, "mul%W%dr , %sr", "%dr *= %sr",
45 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MUL|BPF_SRC_X},
46 {BPF_INSN_MULI, "mul%W%dr , %i32", "%dr *= %i32",
47 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MUL|BPF_SRC_K},
48 {BPF_INSN_SDIVR, "sdiv%W%dr, %sr", "%dr s/= %sr",
49 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU64|BPF_CODE_DIV|BPF_SRC_X|BPF_OFFSET16_SDIVMOD},
50 {BPF_INSN_SDIVI, "sdiv%W%dr , %i32","%dr s/= %i32",
51 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU64|BPF_CODE_DIV|BPF_SRC_K|BPF_OFFSET16_SDIVMOD},
52 {BPF_INSN_SMODR, "smod%W%dr , %sr", "%dr s%%= %sr",
53 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU64|BPF_CODE_MOD|BPF_SRC_X|BPF_OFFSET16_SDIVMOD},
54 {BPF_INSN_SMODI, "smod%W%dr , %i32", "%dr s%%= %i32",
55 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU64|BPF_CODE_MOD|BPF_SRC_K|BPF_OFFSET16_SDIVMOD},
56 {BPF_INSN_DIVR, "div%W%dr , %sr", "%dr /= %sr",
57 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_DIV|BPF_SRC_X},
58 {BPF_INSN_DIVI, "div%W%dr , %i32", "%dr /= %i32",
59 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_DIV|BPF_SRC_K},
60 {BPF_INSN_MODR, "mod%W%dr , %sr", "%dr %%= %sr",
61 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MOD|BPF_SRC_X},
62 {BPF_INSN_MODI, "mod%W%dr , %i32", "%dr %%= %i32",
63 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MOD|BPF_SRC_K},
64 {BPF_INSN_ORR, "or%W%dr , %sr", "%dr |= %sr",
65 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_OR|BPF_SRC_X},
66 {BPF_INSN_ORI, "or%W%dr , %i32", "%dr |= %i32",
67 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_OR|BPF_SRC_K},
68 {BPF_INSN_ANDR, "and%W%dr , %sr", "%dr &= %sr",
69 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_AND|BPF_SRC_X},
70 {BPF_INSN_ANDI, "and%W%dr , %i32", "%dr &= %i32",
71 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_AND|BPF_SRC_K},
72 {BPF_INSN_XORR, "xor%W%dr , %sr", "%dr ^= %sr",
73 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_XOR|BPF_SRC_X},
74 {BPF_INSN_XORI, "xor%W%dr , %i32", "%dr ^= %i32",
75 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_XOR|BPF_SRC_K},
76 {BPF_INSN_NEGR, "neg%W%dr, %sr", "%dr = - %sr",
77 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_NEG|BPF_SRC_X},
78 {BPF_INSN_NEGI, "neg%W%dr , %i32", "%dr = -%W%i32",
79 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_NEG|BPF_SRC_K},
80 {BPF_INSN_LSHR, "lsh%W%dr , %sr", "%dr <<= %sr",
81 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_LSH|BPF_SRC_X},
82 {BPF_INSN_LSHI, "lsh%W%dr , %i32", "%dr <<= %i32",
83 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_LSH|BPF_SRC_K},
84 {BPF_INSN_RSHR, "rsh%W%dr , %sr", "%dr >>= %sr",
85 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_RSH|BPF_SRC_X},
86 {BPF_INSN_RSHI, "rsh%W%dr , %i32", "%dr >>= %i32",
87 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_RSH|BPF_SRC_K},
88 {BPF_INSN_ARSHR, "arsh%W%dr , %sr", "%dr%ws>>= %sr",
89 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_ARSH|BPF_SRC_X},
90 {BPF_INSN_ARSHI, "arsh%W%dr , %i32", "%dr%ws>>= %i32",
91 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_ARSH|BPF_SRC_K},
92 {BPF_INSN_MOVR, "mov%W%dr , %sr", "%dr = %sr",
93 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_X},
94 {BPF_INSN_MOVI, "mov%W%dr , %i32", "%dr = %i32",
95 BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_K},
96
97 /* ALU32 instructions. */
98 {BPF_INSN_ADD32R, "add32%W%dr , %sr", "%dw += %sw",
99 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_ADD|BPF_SRC_X},
100 {BPF_INSN_ADD32I, "add32%W%dr , %i32", "%dw += %i32",
101 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_ADD|BPF_SRC_K},
102 {BPF_INSN_SUB32R, "sub32%W%dr , %sr", "%dw -= %sw",
103 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_SUB|BPF_SRC_X},
104 {BPF_INSN_SUB32I, "sub32%W%dr , %i32", "%dw -= %i32",
105 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_SUB|BPF_SRC_K},
106 {BPF_INSN_MUL32R, "mul32%W%dr , %sr", "%dw *= %sw",
107 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_MUL|BPF_SRC_X},
108 {BPF_INSN_MUL32I, "mul32%W%dr , %i32", "%dw *= %i32",
109 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_MUL|BPF_SRC_K},
110 {BPF_INSN_SDIV32R, "sdiv32%W%dr , %sr", "%dw s/= %sw",
111 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU|BPF_CODE_DIV|BPF_SRC_X|BPF_OFFSET16_SDIVMOD},
112 {BPF_INSN_SDIV32I, "sdiv32%W%dr , %i32", "%dw s/= %i32",
113 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU|BPF_CODE_DIV|BPF_SRC_K|BPF_OFFSET16_SDIVMOD},
114 {BPF_INSN_SMOD32R, "smod32%W%dr , %sr", "%dw s%%= %sw",
115 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU|BPF_CODE_MOD|BPF_SRC_X|BPF_OFFSET16_SDIVMOD},
116 {BPF_INSN_SMOD32I, "smod32%W%dr , %i32", "%dw s%%= %i32",
117 BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU|BPF_CODE_MOD|BPF_SRC_K|BPF_OFFSET16_SDIVMOD},
118 {BPF_INSN_DIV32R, "div32%W%dr , %sr", "%dw /= %sw",
119 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_DIV|BPF_SRC_X},
120 {BPF_INSN_DIV32I, "div32%W%dr , %i32", "%dw /= %i32",
121 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_DIV|BPF_SRC_K},
122 {BPF_INSN_MOD32R, "mod32%W%dr , %sr", "%dw %%= %sw",
123 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_MOD|BPF_SRC_X},
124 {BPF_INSN_MOD32I, "mod32%W%dr , %i32", "%dw %%= %i32",
125 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_MOD|BPF_SRC_K},
126 {BPF_INSN_OR32R, "or32%W%dr , %sr", "%dw |= %sw",
127 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_OR|BPF_SRC_X},
128 {BPF_INSN_OR32I, "or32%W%dr , %i32", "%dw |= %i32",
129 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_OR|BPF_SRC_K},
130 {BPF_INSN_AND32R, "and32%W%dr , %sr", "%dw &= %sw",
131 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_AND|BPF_SRC_X},
132 {BPF_INSN_AND32I, "and32%W%dr , %i32", "%dw &= %i32",
133 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_AND|BPF_SRC_K},
134 {BPF_INSN_XOR32R, "xor32%W%dr , %sr", "%dw ^= %sw",
135 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_XOR|BPF_SRC_X},
136 {BPF_INSN_XOR32I, "xor32%W%dr , %i32", "%dw ^= %i32",
137 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_XOR|BPF_SRC_K},
138 {BPF_INSN_NEG32R, "neg32%W%dr , %sr", "%dw = - %sw",
139 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_NEG|BPF_SRC_X},
140 {BPF_INSN_NEG32I, "neg32%W%dr , %i32", "%dw = -%W%i32",
141 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_NEG|BPF_SRC_K},
142 {BPF_INSN_LSH32R, "lsh32%W%dr , %sr", "%dw <<= %sw",
143 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_LSH|BPF_SRC_X},
144 {BPF_INSN_LSH32I, "lsh32%W%dr , %i32", "%dw <<= %i32",
145 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_LSH|BPF_SRC_K},
146 {BPF_INSN_RSH32R, "rsh32%W%dr , %sr", "%dw >>= %sw",
147 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_RSH|BPF_SRC_X},
148 {BPF_INSN_RSH32I, "rsh32%W%dr , %i32", "%dw >>= %i32",
149 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_RSH|BPF_SRC_K},
150 {BPF_INSN_ARSH32R, "arsh32%W%dr , %sr", "%dw%ws>>= %sw",
151 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_ARSH|BPF_SRC_X},
152 {BPF_INSN_ARSH32I, "arsh32%W%dr , %i32", "%dw%Ws>>= %i32",
153 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_ARSH|BPF_SRC_K},
154 {BPF_INSN_MOV32R, "mov32%W%dr , %sr", "%dw = %sw",
155 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_MOV|BPF_SRC_X},
156 {BPF_INSN_MOV32I, "mov32%W%dr , %i32", "%dw = %i32",
157 BPF_V1, BPF_CODE, BPF_CLASS_ALU|BPF_CODE_MOV|BPF_SRC_K},
158
159 /* Endianness conversion instructions. */
160 {BPF_INSN_ENDLE16, "endle%W%dr , 16", "%dr = le16%w%dr",
161 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_ALU|BPF_CODE_END|BPF_SRC_K|BPF_IMM32_END16},
162 {BPF_INSN_ENDLE32, "endle%W%dr , 32", "%dr = le32%w%dr",
163 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_ALU|BPF_CODE_END|BPF_SRC_K|BPF_IMM32_END32},
164 {BPF_INSN_ENDLE64, "endle%W%dr , 64", "%dr = le64%w%dr",
165 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_ALU|BPF_CODE_END|BPF_SRC_K|BPF_IMM32_END64},
166 {BPF_INSN_ENDBE16, "endbe%W%dr , 16", "%dr = be16%w%dr",
167 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_ALU|BPF_CODE_END|BPF_SRC_X|BPF_IMM32_END16},
168 {BPF_INSN_ENDBE32, "endbe%W%dr , 32", "%dr = be32%w%dr",
169 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_ALU|BPF_CODE_END|BPF_SRC_X|BPF_IMM32_END32},
170 {BPF_INSN_ENDBE64, "endbe%W%dr , 64", "%dr = be64%w%dr",
171 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_ALU|BPF_CODE_END|BPF_SRC_X|BPF_IMM32_END64},
172
173 /* 64-bit load instruction. */
174 {BPF_INSN_LDDW, "lddw%W%dr , %i64", "%dr = %i64%wll",
175 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_DW|BPF_MODE_IMM},
176
177 /* Indirect load instructions, designed to be used in socket
178 filters. */
179 {BPF_INSN_LDINDB, "ldindb%W%sr , %i32", "r0 = * ( u8 * ) skb [ %sr %I32 ]",
180 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_B|BPF_MODE_IND},
181 {BPF_INSN_LDINDH, "ldindh%W%sr , %i32", "r0 = * ( u16 * ) skb [ %sr %I32 ]",
182 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_H|BPF_MODE_IND},
183 {BPF_INSN_LDINDW, "ldindw%W%sr , %i32", "r0 = * ( u32 * ) skb [ %sr %I32 ]",
184 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_W|BPF_MODE_IND},
185 {BPF_INSN_LDINDDW, "ldinddw%W%sr , %i32", "r0 = * ( u64 * ) skb [ %sr %I32 ]",
186 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_DW|BPF_MODE_IND},
187
188 /* Absolute load instructions, designed to be used in socket filters. */
189 {BPF_INSN_LDABSB, "ldabsb%W%i32", "r0 = * ( u8 * ) skb [ %i32 ]",
190 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_B|BPF_MODE_ABS},
191 {BPF_INSN_LDABSH, "ldabsh%W%i32", "r0 = * ( u16 * ) skb [ %i32 ]",
192 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_H|BPF_MODE_ABS},
193 {BPF_INSN_LDABSW, "ldabsw%W%i32", "r0 = * ( u32 * ) skb [ %i32 ]",
194 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_W|BPF_MODE_ABS},
195 {BPF_INSN_LDABSDW, "ldabsdw%W%i32", "r0 = * ( u64 * ) skb [ %i32 ]",
196 BPF_V1, BPF_CODE, BPF_CLASS_LD|BPF_SIZE_DW|BPF_MODE_ABS},
197
198 /* Generic load instructions (to register.) */
199 {BPF_INSN_LDXB, "ldxb%W%dr , [ %sr %o16 ]", "%dr = * ( u8 * ) ( %sr %o16 )",
200 BPF_V1, BPF_CODE, BPF_CLASS_LDX|BPF_SIZE_B|BPF_MODE_MEM},
201 {BPF_INSN_LDXH, "ldxh%W%dr , [ %sr %o16 ]", "%dr = * ( u16 * ) ( %sr %o16 )",
202 BPF_V1, BPF_CODE, BPF_CLASS_LDX|BPF_SIZE_H|BPF_MODE_MEM},
203 {BPF_INSN_LDXW, "ldxw%W%dr , [ %sr %o16 ]", "%dr = * ( u32 * ) ( %sr %o16 )",
204 BPF_V1, BPF_CODE, BPF_CLASS_LDX|BPF_SIZE_W|BPF_MODE_MEM},
205 {BPF_INSN_LDXDW, "ldxdw%W%dr , [ %sr %o16 ]","%dr = * ( u64 * ) ( %sr %o16 )",
206 BPF_V1, BPF_CODE, BPF_CLASS_LDX|BPF_SIZE_DW|BPF_MODE_MEM},
207
208 /* Generic store instructions (from register.) */
209 {BPF_INSN_STXBR, "stxb%W[ %dr %o16 ] , %sr", "* ( u8 * ) ( %dr %o16 ) = %sr",
210 BPF_V1, BPF_CODE, BPF_CLASS_STX|BPF_SIZE_B|BPF_MODE_MEM},
211 {BPF_INSN_STXHR, "stxh%W[ %dr %o16 ] , %sr", "* ( u16 * ) ( %dr %o16 ) = %sr",
212 BPF_V1, BPF_CODE, BPF_CLASS_STX|BPF_SIZE_H|BPF_MODE_MEM},
213 {BPF_INSN_STXWR, "stxw%W[ %dr %o16 ], %sr", "* ( u32 * ) ( %dr %o16 ) = %sr",
214 BPF_V1, BPF_CODE, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_MEM},
215 {BPF_INSN_STXDWR, "stxdw%W[ %dr %o16 ] , %sr", "* ( u64 * ) ( %dr %o16 ) = %sr",
216 BPF_V1, BPF_CODE, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_MEM},
217
218 /* Generic store instructions (from 32-bit immediate.) */
219 {BPF_INSN_STXBI, "stb%W[ %dr %o16 ] , %i32", "* ( u8 * ) ( %dr %o16 ) = %i32",
220 BPF_V1, BPF_CODE, BPF_CLASS_ST|BPF_SIZE_B|BPF_MODE_MEM},
221 {BPF_INSN_STXHI, "sth%W[ %dr %o16 ] , %i32", "* ( u16 * ) ( %dr %o16 ) = %i32",
222 BPF_V1, BPF_CODE, BPF_CLASS_ST|BPF_SIZE_H|BPF_MODE_MEM},
223 {BPF_INSN_STXWI, "stw%W[ %dr %o16 ] , %i32", "* ( u32 * ) ( %dr %o16 ) = %i32",
224 BPF_V1, BPF_CODE, BPF_CLASS_ST|BPF_SIZE_W|BPF_MODE_MEM},
225 {BPF_INSN_STXDWI, "stdw%W[ %dr %o16 ] , %i32", "* ( u64 * ) ( %dr %o16 ) = %i32",
226 BPF_V1, BPF_CODE, BPF_CLASS_ST|BPF_SIZE_DW|BPF_MODE_MEM},
227
228 /* Compare-and-jump instructions (reg OP reg). */
229 {BPF_INSN_JAR, "ja%W%d16", "goto%w%d16",
230 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JA|BPF_SRC_K},
231 {BPF_INSN_JEQR, "jeq%W%dr , %sr , %d16", "if%w%dr == %sr%wgoto%w%d16",
232 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JEQ|BPF_SRC_X},
233 {BPF_INSN_JGTR, "jgt%W%dr , %sr , %d16", "if%w%dr > %sr%wgoto%w%d16",
234 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JGT|BPF_SRC_X},
235 {BPF_INSN_JSGTR, "jsgt%W%dr, %sr , %d16", "if%w%dr s> %sr%wgoto%w%d16",
236 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSGT|BPF_SRC_X},
237 {BPF_INSN_JGER, "jge%W%dr , %sr , %d16", "if%w%dr >= %sr%wgoto%w%d16",
238 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JGE|BPF_SRC_X},
239 {BPF_INSN_JSGER, "jsge%W%dr , %sr , %d16", "if%w%dr s>= %sr%wgoto%w%d16",
240 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSGE|BPF_SRC_X},
241 {BPF_INSN_JLTR, "jlt%W%dr , %sr , %d16", "if%w%dr < %sr%wgoto%w%d16",
242 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JLT|BPF_SRC_X},
243 {BPF_INSN_JSLTR, "jslt%W%dr , %sr , %d16", "if%w%dr s< %sr%wgoto%w%d16",
244 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSLT|BPF_SRC_X},
245 {BPF_INSN_JLER, "jle%W%dr , %sr , %d16", "if%w%dr <= %sr%wgoto%w%d16",
246 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JLE|BPF_SRC_X},
247 {BPF_INSN_JSLER, "jsle%W%dr , %sr , %d16", "if%w%dr s<= %sr%wgoto%w%d16",
248 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSLE|BPF_SRC_X},
249 {BPF_INSN_JSETR, "jset%W%dr , %sr , %d16", "if%w%dr & %sr%wgoto%w%d16",
250 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSET|BPF_SRC_X},
251 {BPF_INSN_JNER, "jne%W%dr , %sr , %d16", "if%w%dr != %sr%wgoto%w%d16",
252 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JNE|BPF_SRC_X},
253 {BPF_INSN_CALLR, "call%W%dr", "callx%w%dr",
254 BPF_XBPF, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_CALL|BPF_SRC_X},
255 {BPF_INSN_CALL, "call%W%d32", "call%w%d32",
256 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_CALL|BPF_SRC_K},
257 {BPF_INSN_EXIT, "exit", "exit",
258 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_EXIT|BPF_SRC_K},
259
260 /* Compare-and-jump instructions (reg OP imm). */
261 {BPF_INSN_JEQI, "jeq%W%dr , %i32 , %d16", "if%w%dr == %i32%wgoto%w%d16",
262 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JEQ|BPF_SRC_K},
263 {BPF_INSN_JGTI, "jgt%W%dr , %i32 , %d16", "if%w%dr > %i32%wgoto%w%d16",
264 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JGT|BPF_SRC_K},
265 {BPF_INSN_JSGTI, "jsgt%W%dr, %i32 , %d16", "if%w%dr s> %i32%wgoto%w%d16",
266 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSGT|BPF_SRC_K},
267 {BPF_INSN_JGEI, "jge%W%dr , %i32 , %d16", "if%w%dr >= %i32%wgoto%w%d16",
268 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JGE|BPF_SRC_K},
269 {BPF_INSN_JSGEI, "jsge%W%dr , %i32 , %d16", "if%w%dr s>= %i32%wgoto%w%d16",
270 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSGE|BPF_SRC_K},
271 {BPF_INSN_JLTI, "jlt%W%dr , %i32 , %d16", "if%w%dr < %i32%wgoto%w%d16",
272 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JLT|BPF_SRC_K},
273 {BPF_INSN_JSLTI, "jslt%W%dr , %i32, %d16", "if%w%dr s< %i32%wgoto%w%d16",
274 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSLT|BPF_SRC_K},
275 {BPF_INSN_JLEI, "jle%W%dr , %i32 , %d16", "if%w%dr <= %i32%wgoto%w%d16",
276 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JLE|BPF_SRC_K},
277 {BPF_INSN_JSLEI, "jsle%W%dr , %i32 , %d16", "if%w%dr s<= %i32%wgoto%w%d16",
278 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSLE|BPF_SRC_K},
279 {BPF_INSN_JSETI, "jset%W%dr , %i32 , %d16", "if%w%dr & %i32%wgoto%w%d16",
280 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JSET|BPF_SRC_K},
281 {BPF_INSN_JNEI, "jne%W%dr , %i32 , %d16", "if%w%dr != %i32%wgoto%w%d16",
282 BPF_V1, BPF_CODE, BPF_CLASS_JMP|BPF_CODE_JNE|BPF_SRC_K},
283
284 /* 32-bit compare-and-jump instructions (reg OP reg). */
285 {BPF_INSN_JEQ32R, "jeq32%W%dr , %sr , %d16", "if%w%dw == %sw%wgoto%w%d16",
286 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JEQ|BPF_SRC_X},
287 {BPF_INSN_JGT32R, "jgt32%W%dr , %sr , %d16", "if%w%dw > %sw%wgoto%w%d16",
288 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JGT|BPF_SRC_X},
289 {BPF_INSN_JSGT32R, "jsgt32%W%dr, %sr , %d16", "if%w%dw s> %sw%wgoto%w%d16",
290 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSGT|BPF_SRC_X},
291 {BPF_INSN_JGE32R, "jge32%W%dr , %sr , %d16", "if%w%dw >= %sw%wgoto%w%d16",
292 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JGE|BPF_SRC_X},
293 {BPF_INSN_JSGE32R, "jsge32%W%dr , %sr , %d16", "if%w%dw s>= %sw%wgoto%w%d16",
294 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSGE|BPF_SRC_X},
295 {BPF_INSN_JLT32R, "jlt32%W%dr , %sr , %d16", "if%w%dw < %sw%wgoto%w%d16",
296 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JLT|BPF_SRC_X},
297 {BPF_INSN_JSLT32R, "jslt32%W%dr , %sr , %d16", "if%w%dw s< %sw%wgoto%w%d16",
298 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSLT|BPF_SRC_X},
299 {BPF_INSN_JLE32R, "jle32%W%dr , %sr , %d16", "if%w%dw <= %sw%wgoto%w%d16",
300 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JLE|BPF_SRC_X},
301 {BPF_INSN_JSLE32R, "jsle32%W%dr , %sr , %d16", "if%w%dw s<= %sw%wgoto%w%d16",
302 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSLE|BPF_SRC_X},
303 {BPF_INSN_JSET32R, "jset32%W%dr , %sr , %d16", "if%w%dw & %sw%wgoto%w%d16",
304 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSET|BPF_SRC_X},
305 {BPF_INSN_JNE32R, "jne32%W%dr , %sr , %d16", "if%w%dw != %sw%wgoto%w%d16",
306 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JNE|BPF_SRC_X},
307
308 /* 32-bit compare-and-jump instructions (reg OP imm). */
309 {BPF_INSN_JEQ32I, "jeq32%W%dr , %i32 , %d16", "if%w%dw == %i32%wgoto%w%d16",
310 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JEQ|BPF_SRC_K},
311 {BPF_INSN_JGT32I, "jgt32%W%dr , %i32 , %d16", "if%w%dw > %i32%wgoto%w%d16",
312 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JGT|BPF_SRC_K},
313 {BPF_INSN_JSGT32I, "jsgt32%W%dr, %i32 , %d16", "if%w%dw s> %i32%wgoto%w%d16",
314 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSGT|BPF_SRC_K},
315 {BPF_INSN_JGE32I, "jge32%W%dr , %i32 , %d16", "if%w%dw >= %i32%wgoto%w%d16",
316 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JGE|BPF_SRC_K},
317 {BPF_INSN_JSGE32I, "jsge32%W%dr , %i32 , %d16", "if%w%dw s>= %i32%wgoto%w%d16",
318 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSGE|BPF_SRC_K},
319 {BPF_INSN_JLT32I, "jlt32%W%dr , %i32 , %d16", "if%w%dw < %i32%wgoto%w%d16",
320 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JLT|BPF_SRC_K},
321 {BPF_INSN_JSLT32I, "jslt32%W%dr , %i32, %d16", "if%w%dw s< %i32%wgoto%w%d16",
322 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSLT|BPF_SRC_K},
323 {BPF_INSN_JLE32I, "jle32%W%dr , %i32 , %d16", "if%w%dw <= %i32%wgoto%w%d16",
324 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JLE|BPF_SRC_K},
325 {BPF_INSN_JSLE32I, "jsle32%W%dr , %i32 , %d16", "if%w%dw s<= %i32%wgoto%w%d16",
326 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSLE|BPF_SRC_K},
327 {BPF_INSN_JSET32I, "jset32%W%dr , %i32 , %d16", "if%w%dw & %i32%wgoto%w%d16",
328 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JSET|BPF_SRC_K},
329 {BPF_INSN_JNE32I, "jne32%W%dr , %i32 , %d16", "if%w%dw != %i32%wgoto%w%d16",
330 BPF_V3, BPF_CODE, BPF_CLASS_JMP32|BPF_CODE_JNE|BPF_SRC_K},
331
332 /* Atomic instructions. */
333 {BPF_INSN_AADD, "aadd%W[ %dr %o16 ] , %sr", "* ( u64 * ) ( %dr %o16 ) += %sr",
334 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AADD},
335 {BPF_INSN_AOR, "aor%W[ %dr %o16 ] , %sr", "* ( u64 * ) ( %dr %o16 ) |= %sr",
336 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AOR},
337 {BPF_INSN_AAND, "aand%W[ %dr %o16 ] , %sr", "* ( u64 * ) ( %dr %o16 ) &= %sr",
338 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AAND},
339 {BPF_INSN_AXOR, "axor%W[ %dr %o16 ] , %sr", "* ( u64 * ) ( %dr %o16 ) ^= %sr",
340 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AXOR},
341
342 /* Atomic instructions with fetching. */
343 {BPF_INSN_AFADD, "afadd%W[ %dr %o16 ] , %sr", "???",
344 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AFADD},
345 {BPF_INSN_AFOR, "afor%W[ %dr %o16 ] , %sr", "???",
346 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AFOR},
347 {BPF_INSN_AFAND, "afand%W[ %dr %o16 ] , %sr", "???",
348 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AFAND},
349 {BPF_INSN_AFXOR, "afxor%W[ %dr %o16 ] , %sr", "???",
350 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AFXOR},
351
352 /* Atomic instructions (32-bit.) */
353 {BPF_INSN_AADD32, "aadd32%W[ %dr %o16 ] , %sr", "* ( u32 * ) ( %dr %o16 ) += %sr",
354 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AADD},
355 {BPF_INSN_AOR32, "aor32%W[ %dr %o16 ] , %sr", "* ( u32 * ) ( %dr %o16 ) |= %sr",
356 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AOR},
357 {BPF_INSN_AAND32, "aand32%W[ %dr %o16 ] , %sr", "* ( u32 * ) ( %dr %o16 ) &= %sr",
358 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AAND},
359 {BPF_INSN_AXOR32, "axor32%W[ %dr %o16 ] , %sr", "* ( u32 * ) ( %dr %o16 ) ^= %sr",
360 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AXOR},
361
362 /* Atomic instructions with fetching (32-bit.) */
363 {BPF_INSN_AFADD32, "afadd32 %W[ %dr %o16 ] , %sr", "???",
364 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AFADD},
365 {BPF_INSN_AFOR32, "afor32%W[ %dr %o16 ] , %sr", "???",
366 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AFOR},
367 {BPF_INSN_AFAND32, "afand32%W[ %dr %o16 ] , %sr", "???",
368 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AFAND},
369 {BPF_INSN_AFXOR32, "afxor32%W[ %dr %o16 ] , %sr", "???",
370 BPF_V3, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AFXOR},
371
372 /* Old versions of aadd and aadd32. */
373 {BPF_INSN_AADD, "xadddw%W[ %dr %o16 ] , %sr", "* ( u64 * ) ( %dr %o16 ) += %sr",
374 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_DW|BPF_MODE_ATOMIC|BPF_IMM32_AADD},
375 {BPF_INSN_AADD32, "xaddw%W[ %dr %o16 ] , %sr", "* ( u32 * ) ( %dr %o16 ) += %sr",
376 BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AADD},
377
378 /* the brkpt instruction is used by the BPF simulator and it doesn't
379 really belong to the BPF instruction set. */
380 {BPF_INSN_BRKPT, "brkpt", "brkpt",
381 BPF_XBPF, BPF_CODE, BPF_CLASS_ALU|BPF_SRC_X|BPF_CODE_NEG},
382
383 /* Sentinel. */
384 {BPF_NOINSN, NULL, NULL, 0, 0UL, 0UL},
79472b45
JM
385};
386
d218e7fe
JM
387static bpf_insn_word
388bpf_handle_endianness (bpf_insn_word word, enum bpf_endian endian)
79472b45 389{
d218e7fe
JM
390 if (endian == BPF_ENDIAN_LITTLE)
391 {
392 /* Endianness groups: 8 | 4 | 4 | 16 | 32 */
393
394 bpf_insn_word code = (word >> 56) & 0xff;
395 bpf_insn_word dst = (word >> 48) & 0xf;
396 bpf_insn_word src = (word >> 52) & 0xf;
397 bpf_insn_word offset16 = (word >> 32) & 0xffff;
398 bpf_insn_word imm32 = word & 0xffffffff;
399
400 return ((code << 56)
401 | dst << 52
402 | src << 48
403 | (offset16 & 0xff) << 40
404 | ((offset16 >> 8) & 0xff) << 32
405 | (imm32 & 0xff) << 24
406 | ((imm32 >> 8) & 0xff) << 16
407 | ((imm32 >> 16) & 0xff) << 8
408 | ((imm32 >> 24) & 0xff));
409 }
79472b45 410
d218e7fe
JM
411 return word;
412}
79472b45 413
d218e7fe
JM
414const struct bpf_opcode *
415bpf_match_insn (bpf_insn_word word,
416 enum bpf_endian endian,
417 int version)
79472b45 418{
d218e7fe 419 unsigned int i = 0;
79472b45 420
d218e7fe
JM
421 while (bpf_opcodes[i].normal != NULL)
422 {
423 bpf_insn_word cword
424 = bpf_handle_endianness (word, endian);
425
426 /* Attempt match using mask and opcodes. */
427 if (bpf_opcodes[i].version <= version
428 && (cword & bpf_opcodes[i].mask) == bpf_opcodes[i].opcode)
429 return &bpf_opcodes[i];
430 i++;
431 }
79472b45 432
d218e7fe
JM
433 /* No maching instruction found. */
434 return NULL;
435}
79472b45 436
d218e7fe
JM
437uint8_t
438bpf_extract_src (bpf_insn_word word, enum bpf_endian endian)
79472b45 439{
d218e7fe
JM
440 word = bpf_handle_endianness (word, endian);
441 return (uint8_t) ((word >> 48) & 0xf);
79472b45
JM
442}
443
d218e7fe
JM
444uint8_t
445bpf_extract_dst (bpf_insn_word word, enum bpf_endian endian)
79472b45 446{
d218e7fe
JM
447 word = bpf_handle_endianness (word, endian);
448 return (uint8_t) ((word >> 52) & 0xf);
79472b45
JM
449}
450
d218e7fe
JM
451int16_t
452bpf_extract_offset16 (bpf_insn_word word, enum bpf_endian endian)
79472b45 453{
d218e7fe
JM
454 word = bpf_handle_endianness (word, endian);
455 return (int16_t) ((word >> 32) & 0xffff);
79472b45
JM
456}
457
d218e7fe
JM
458int32_t
459bpf_extract_imm32 (bpf_insn_word word, enum bpf_endian endian)
79472b45 460{
d218e7fe
JM
461 word = bpf_handle_endianness (word, endian);
462 return (int32_t) (word & 0xffffffff);
79472b45
JM
463}
464
d218e7fe
JM
465int64_t
466bpf_extract_imm64 (bpf_insn_word word1, bpf_insn_word word2,
467 enum bpf_endian endian)
79472b45 468{
d218e7fe
JM
469 word1 = bpf_handle_endianness (word1, endian);
470 word2 = bpf_handle_endianness (word2, endian);
471 return (int64_t) (((word2 & 0xffffffff) << 32) | (word1 & 0xffffffff));
79472b45
JM
472}
473
d218e7fe
JM
474const struct bpf_opcode *
475bpf_get_opcode (unsigned int index)
79472b45 476{
d218e7fe 477 unsigned int i = 0;
79472b45 478
d218e7fe
JM
479 while (bpf_opcodes[i].normal != NULL && i < index)
480 ++i;
481 return (bpf_opcodes[i].normal == NULL
482 ? NULL
483 : &bpf_opcodes[i]);
79472b45 484}