]>
Commit | Line | Data |
---|---|---|
ea195bb0 JM |
1 | ;; Linux BPF CPU description -*- Scheme -*- |
2 | ;; Copyright (C) 2019 Free Software Foundation, Inc. | |
3 | ;; | |
4 | ;; Contributed by Oracle Inc. | |
5 | ;; | |
6 | ;; This file is part of the GNU Binutils and of GDB. | |
7 | ;; | |
8 | ;; This program is free software; you can redistribute it and/or | |
9 | ;; modify it under the terms of the GNU General Public License as | |
10 | ;; published by the Free Software Foundation; either version 3 of the | |
11 | ;; License, or (at your option) any later version. | |
12 | ;; | |
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. | |
17 | ;; | |
18 | ;; You should have received a copy of the GNU General Public License | |
19 | ;; along with this program; if not, write to the Free Software | |
20 | ;; Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA | |
21 | ;; 02110-1301, USA. | |
22 | ||
23 | ;; This file contains a CGEN CPU description for the Linux kernel eBPF | |
24 | ;; instruction set. eBPF is documented in the linux kernel source | |
25 | ;; tree. See linux/Documentation/networking/filter.txt, and also the | |
26 | ;; sources in the networking subsystem, notably | |
27 | ;; linux/net/core/filter.c. | |
28 | ||
29 | (include "simplify.inc") | |
30 | ||
31 | (define-arch | |
32 | (name bpf) | |
33 | (comment "Linux kernel BPF") | |
34 | (insn-lsb0? #t) | |
78c1c354 JM |
35 | ;; XXX explain the default-alignment setting is for the simulator. |
36 | ;; It is confusing that the simulator follows the emulated memory | |
37 | ;; access conventions for fetching instructions by pieces... | |
38 | (default-alignment unaligned) | |
4449c81a DF |
39 | (machs bpf xbpf) |
40 | (isas ebpfle ebpfbe xbpfle xbpfbe)) | |
ea195bb0 JM |
41 | |
42 | ;;;; The ISAs | |
43 | ||
44 | ;; Logically, eBPF comforms a single instruction set featuring two | |
45 | ;; kind of instructions: 64-bit instructions and 128-bit instructions. | |
46 | ;; | |
47 | ;; The 64-bit instructions have the form: | |
48 | ;; | |
49 | ;; code:8 regs:8 offset:16 imm:32 | |
50 | ;; | |
51 | ;; Whereas the 128-bit instructions (at the moment there is only one | |
52 | ;; of such instructions, lddw) have the form: | |
53 | ;; | |
e042e6c3 | 54 | ;; code:8 regs:8 offset:16 imm:32 unused:32 imm:32 |
ea195bb0 JM |
55 | ;; |
56 | ;; In both formats `regs' is itself composed by two fields: | |
57 | ;; | |
58 | ;; dst:4 src:4 | |
59 | ;; | |
60 | ;; The ISA is supposed to be orthogonal to endianness: the endianness | |
61 | ;; of the instruction fields follow the endianness of the host running | |
62 | ;; the eBPF program, and that's all. However, this is not entirely | |
63 | ;; true. The definition of an eBPF code in the Linux kernel is: | |
64 | ;; | |
65 | ;; struct bpf_insn { | |
66 | ;; __u8 code; /* opcode */ | |
67 | ;; __u8 dst_reg:4; /* dest register */ | |
68 | ;; __u8 src_reg:4; /* source register */ | |
69 | ;; __s16 off; /* signed offset */ | |
70 | ;; __s32 imm; /* signed immediate constant */ | |
71 | ;; }; | |
72 | ;; | |
73 | ;; Since the ordering of fields in C bitmaps is defined by the | |
74 | ;; implementation, the impact of endianness in the encoding of eBPF | |
75 | ;; instructions is effectively defined by GCC. In particular, GCC | |
76 | ;; places dst_reg before src_reg in little-endian code, and the other | |
77 | ;; way around in big-endian code. | |
78 | ;; | |
79 | ;; So, in reality, eBPF comprises two instruction sets: one for | |
80 | ;; little-endian with instructions like: | |
81 | ;; | |
82 | ;; code:8 src:4 dst:4 offset:16 imm:32 [unused:32 imm:32] | |
83 | ;; | |
84 | ;; and another for big-endian with instructions like: | |
85 | ;; | |
86 | ;; code:8 dst:4 src:4 offset:16 imm:32 [unused:32 imm:32] | |
87 | ;; | |
88 | ;; where `offset' and the immediate fields are encoded in | |
89 | ;; little-endian and big-endian byte-order, respectively. | |
90 | ||
91 | (define-pmacro (define-bpf-isa x-endian) | |
92 | (define-isa | |
93 | (name (.sym ebpf x-endian)) | |
94 | (comment "The eBPF instruction set") | |
95 | ;; Default length to record in ifields. This is used in | |
96 | ;; calculations involving bit numbers. | |
97 | (default-insn-word-bitsize 64) | |
98 | ;; Length of an unknown instruction. Used by disassembly and by the | |
99 | ;; simulator's invalid insn handler. | |
100 | (default-insn-bitsize 64) | |
d8740be1 JM |
101 | ;; Number of bits of insn that can be initially fetched. This is |
102 | ;; the size of the smallest insn. | |
103 | (base-insn-bitsize 64))) | |
ea195bb0 JM |
104 | |
105 | (define-bpf-isa le) | |
106 | (define-bpf-isa be) | |
107 | ||
4449c81a DF |
108 | (define-pmacro (define-xbpf-isa x-endian) |
109 | (define-isa | |
110 | (name (.sym xbpf x-endian)) | |
111 | (comment "The xBPF instruction set") | |
112 | (default-insn-word-bitsize 64) | |
113 | (default-insn-bitsize 64) | |
114 | (base-insn-bitsize 64))) | |
115 | ||
116 | (define-xbpf-isa le) | |
117 | (define-xbpf-isa be) | |
118 | ||
119 | (define-pmacro all-isas () (ISA ebpfle,ebpfbe,xbpfle,xbpfbe)) | |
120 | (define-pmacro xbpf-isas () (ISA xbpfle,xbpfbe)) | |
121 | ||
122 | (define-pmacro (endian-isas x-endian) | |
123 | ((ISA (.sym ebpf x-endian) (.sym xbpf x-endian)))) | |
ea195bb0 JM |
124 | |
125 | ;;;; Hardware Hierarchy | |
126 | ||
127 | ;; | |
4449c81a DF |
128 | ;; bpf architecture |
129 | ;; | | |
130 | ;; bpfbf cpu-family | |
131 | ;; / \ | |
132 | ;; bpf xbpf machine | |
133 | ;; | | | |
134 | ;; bpf-def xbpf-def model | |
ea195bb0 JM |
135 | |
136 | (define-cpu | |
137 | (name bpfbf) | |
138 | (comment "Linux kernel eBPF virtual CPU") | |
78c1c354 JM |
139 | (insn-endian big) |
140 | (word-bitsize 64)) | |
ea195bb0 JM |
141 | |
142 | (define-mach | |
143 | (name bpf) | |
144 | (comment "Linux eBPF") | |
145 | (cpu bpfbf) | |
146 | (isas ebpfle ebpfbe)) | |
147 | ||
148 | (define-model | |
149 | (name bpf-def) | |
150 | (comment "Linux eBPF default model") | |
151 | (mach bpf) | |
152 | (unit u-exec "execution unit" () | |
153 | 1 ; issue | |
154 | 1 ; done | |
155 | () ; state | |
156 | () ; inputs | |
157 | () ; outputs | |
158 | () ; profile action (default) | |
159 | )) | |
160 | ||
4449c81a DF |
161 | (define-mach |
162 | (name xbpf) | |
163 | (comment "Experimental BPF") | |
164 | (cpu bpfbf) | |
165 | (isas ebpfle ebpfbe xbpfle xbpfbe)) | |
166 | ||
167 | (define-model | |
168 | (name xbpf-def) | |
169 | (comment "xBPF default model") | |
170 | (mach xbpf) | |
171 | (unit u-exec "execution unit" () | |
172 | 1 ; issue | |
173 | 1 ; done | |
174 | () ; state | |
175 | () ; inputs | |
176 | () ; outputs | |
177 | () ; profile action (default) | |
178 | )) | |
179 | ||
ea195bb0 JM |
180 | ;;;; Hardware Elements |
181 | ||
182 | ;; eBPF programs can access 10 general-purpose registers which are | |
183 | ;; 64-bit. | |
184 | ||
185 | (define-hardware | |
186 | (name h-gpr) | |
187 | (comment "General Purpose Registers") | |
4449c81a | 188 | (attrs all-isas (MACH bpf xbpf)) |
ea195bb0 JM |
189 | (type register DI (16)) |
190 | (indices keyword "%" | |
191 | ;; XXX the frame pointer fp is read-only, so it should | |
192 | ;; go in a different hardware. | |
193 | (;; ABI names. Take priority when disassembling. | |
231097b0 | 194 | (r0 0) (r1 1) (r2 2) (r3 3) (r4 4) (r5 5) (r6 6) |
ea195bb0 JM |
195 | (r7 7) (r8 8) (r9 9) (fp 10) |
196 | ;; Additional names recognized when assembling. | |
78c1c354 | 197 | (r0 0) (r6 6) (r10 10)))) |
ea195bb0 JM |
198 | |
199 | ;; The program counter. CGEN requires it, even if it is not visible | |
200 | ;; to eBPF programs. | |
201 | ||
78c1c354 JM |
202 | (define-hardware |
203 | (name h-pc) | |
204 | (comment "program counter") | |
205 | (attrs PC PROFILE all-isas) | |
206 | (type pc UDI) | |
207 | (get () (raw-reg h-pc)) | |
208 | (set (newval) (set (raw-reg h-pc) newval))) | |
209 | ||
ea195bb0 JM |
210 | ;; A 64-bit h-sint to be used by the imm64 operand below. XXX this |
211 | ;; shouldn't be needed, as h-sint is supposed to be able to hold | |
212 | ;; 64-bit values. However, in practice CGEN limits h-sint to 32 bits | |
213 | ;; in 32-bit hosts. To be fixed in CGEN. | |
214 | ||
215 | (dnh h-sint64 "signed 64-bit integer" (all-isas) (immediate DI) | |
216 | () () ()) | |
217 | ||
218 | ;;;; The Instruction Sets | |
219 | ||
220 | ;;; Fields and Opcodes | |
221 | ||
222 | ;; Convenience macro to shorten the definition of the fields below. | |
223 | (define-pmacro (dwf x-name x-comment x-attrs | |
224 | x-word-offset x-word-length x-start x-length | |
225 | x-mode) | |
226 | "Define a field including its containing word." | |
227 | (define-ifield | |
228 | (name x-name) | |
229 | (comment x-comment) | |
230 | (.splice attrs (.unsplice x-attrs)) | |
231 | (word-offset x-word-offset) | |
232 | (word-length x-word-length) | |
233 | (start x-start) | |
234 | (length x-length) | |
235 | (mode x-mode))) | |
236 | ||
237 | ;; For arithmetic and jump instructions the 8-bit code field is | |
238 | ;; subdivided in: | |
239 | ;; | |
240 | ;; op-code:4 op-src:1 op-class:3 | |
241 | ||
242 | (dwf f-op-code "eBPF opcode code" (all-isas) 0 8 7 4 UINT) | |
243 | (dwf f-op-src "eBPF opcode source" (all-isas) 0 8 3 1 UINT) | |
244 | (dwf f-op-class "eBPF opcode instruction class" (all-isas) 0 8 2 3 UINT) | |
245 | ||
246 | (define-normal-insn-enum insn-op-code-alu "eBPF instruction codes" | |
247 | (all-isas) OP_CODE_ f-op-code | |
248 | (;; Codes for OP_CLASS_ALU and OP_CLASS_ALU64 | |
249 | (ADD #x0) (SUB #x1) (MUL #x2) (DIV #x3) (OR #x4) (AND #x5) | |
250 | (LSH #x6) (RSH #x7) (NEG #x8) (MOD #x9) (XOR #xa) (MOV #xb) | |
251 | (ARSH #xc) (END #xd) | |
6e25f888 DF |
252 | ;; xBPF-only: signed div, signed mod |
253 | (SDIV #xe) (SMOD #xf) | |
ea195bb0 JM |
254 | ;; Codes for OP_CLASS_JMP |
255 | (JA #x0) (JEQ #x1) (JGT #x2) (JGE #x3) (JSET #x4) | |
256 | (JNE #x5) (JSGT #x6) (JSGE #x7) (CALL #x8) (EXIT #x9) | |
257 | (JLT #xa) (JLE #xb) (JSLT #xc) (JSLE #xd))) | |
258 | ||
259 | (define-normal-insn-enum insn-op-src "eBPF instruction source" | |
260 | (all-isas) OP_SRC_ f-op-src | |
261 | ;; X => use `src' as source operand. | |
262 | ;; K => use `imm32' as source operand. | |
263 | ((K #b0) (X #b1))) | |
264 | ||
265 | (define-normal-insn-enum insn-op-class "eBPF instruction class" | |
266 | (all-isas) OP_CLASS_ f-op-class | |
267 | ((LD #b000) (LDX #b001) (ST #b010) (STX #b011) | |
c54a9b56 | 268 | (ALU #b100) (JMP #b101) (JMP32 #b110) (ALU64 #b111))) |
ea195bb0 JM |
269 | |
270 | ;; For load/store instructions, the 8-bit code field is subdivided in: | |
271 | ;; | |
272 | ;; op-mode:3 op-size:2 op-class:3 | |
273 | ||
274 | (dwf f-op-mode "eBPF opcode mode" (all-isas) 0 8 7 3 UINT) | |
275 | (dwf f-op-size "eBPF opcode size" (all-isas) 0 8 4 2 UINT) | |
276 | ||
277 | (define-normal-insn-enum insn-op-mode "eBPF load/store instruction modes" | |
278 | (all-isas) OP_MODE_ f-op-mode | |
279 | ((IMM #b000) (ABS #b001) (IND #b010) (MEM #b011) | |
280 | ;; #b100 and #b101 are used in classic BPF only, reserved in eBPF. | |
281 | (XADD #b110))) | |
282 | ||
283 | (define-normal-insn-enum insn-op-size "eBPF load/store instruction sizes" | |
284 | (all-isas) OP_SIZE_ f-op-size | |
285 | ((W #b00) ;; Word: 4 byte | |
286 | (H #b01) ;; Half-word: 2 byte | |
287 | (B #b10) ;; Byte: 1 byte | |
288 | (DW #b11))) ;; Double-word: 8 byte | |
289 | ||
290 | ;; The fields for the source and destination registers are a bit | |
291 | ;; tricky. Due to the bizarre nibble swap between little-endian and | |
292 | ;; big-endian ISAs we need to keep different variants of the fields. | |
293 | ;; | |
294 | ;; Note that f-regs is used in the format spec of instructions that do | |
295 | ;; NOT use registers, where endianness is irrelevant i.e. f-regs is a | |
296 | ;; constant 0 opcode. | |
297 | ||
4449c81a DF |
298 | (dwf f-dstle "eBPF dst register field" ((ISA ebpfle xbpfle)) 8 8 3 4 UINT) |
299 | (dwf f-srcle "eBPF source register field" ((ISA ebpfle xbpfle)) 8 8 7 4 UINT) | |
ea195bb0 | 300 | |
4449c81a DF |
301 | (dwf f-dstbe "eBPF dst register field" ((ISA ebpfbe xbpfbe)) 8 8 7 4 UINT) |
302 | (dwf f-srcbe "eBPF source register field" ((ISA ebpfbe xbpfbe)) 8 8 3 4 UINT) | |
ea195bb0 JM |
303 | |
304 | (dwf f-regs "eBPF registers field" (all-isas) 8 8 7 8 UINT) | |
305 | ||
306 | ;; Finally, the fields for the immediates. | |
307 | ;; | |
308 | ;; The 16-bit offsets and 32-bit immediates do not present any special | |
309 | ;; difficulty: we put them in their own instruction word so the | |
310 | ;; byte-endianness will be properly applied. | |
311 | ||
d73be611 | 312 | (dwf f-offset16 "eBPF offset field" (all-isas) 16 16 15 16 HI) |
ea195bb0 JM |
313 | (dwf f-imm32 "eBPF 32-bit immediate field" (all-isas) 32 32 31 32 INT) |
314 | ||
315 | ;; For the disjoint 64-bit signed immediate, however, we need to use a | |
316 | ;; multi-ifield. | |
317 | ||
318 | (dwf f-imm64-a "eBPF 64-bit immediate a" (all-isas) 32 32 31 32 UINT) | |
319 | (dwf f-imm64-b "eBPF 64-bit immediate b" (all-isas) 64 32 31 32 UINT) | |
320 | (dwf f-imm64-c "eBPF 64-bit immediate c" (all-isas) 96 32 31 32 UINT) | |
321 | ||
322 | (define-multi-ifield | |
323 | (name f-imm64) | |
324 | (comment "eBPF 64-bit immediate field") | |
325 | (attrs all-isas) | |
326 | (mode DI) | |
327 | (subfields f-imm64-a f-imm64-b f-imm64-c) | |
328 | (insert (sequence () | |
329 | (set (ifield f-imm64-b) (const 0)) | |
330 | (set (ifield f-imm64-c) (srl (ifield f-imm64) (const 32))) | |
331 | (set (ifield f-imm64-a) (and (ifield f-imm64) (const #xffffffff))))) | |
332 | (extract (sequence () | |
333 | (set (ifield f-imm64) | |
62e65990 AM |
334 | (or (sll UDI (zext UDI (ifield f-imm64-c)) (const 32)) |
335 | (zext UDI (ifield f-imm64-a))))))) | |
ea195bb0 JM |
336 | |
337 | ;;; Operands | |
338 | ||
339 | ;; A couple of source and destination register operands are defined | |
340 | ;; for each ISA: ebpfle and ebpfbe. | |
341 | ||
4449c81a DF |
342 | (dno dstle "destination register" ((ISA ebpfle xbpfle)) h-gpr f-dstle) |
343 | (dno srcle "source register" ((ISA ebpfle xbpfle)) h-gpr f-srcle) | |
ea195bb0 | 344 | |
4449c81a DF |
345 | (dno dstbe "destination register" ((ISA ebpfbe xbpfbe)) h-gpr f-dstbe) |
346 | (dno srcbe "source register" ((ISA ebpfbe xbpfbe)) h-gpr f-srcbe) | |
ea195bb0 JM |
347 | |
348 | ;; Jump instructions have a 16-bit PC-relative address. | |
349 | ;; CALL instructions have a 32-bit PC-relative address. | |
350 | ||
351 | (dno disp16 "16-bit PC-relative address" (all-isas PCREL-ADDR) h-sint | |
352 | f-offset16) | |
353 | (dno disp32 "32-bit PC-relative address" (all-isas PCREL-ADDR) h-sint | |
354 | f-imm32) | |
355 | ||
356 | ;; Immediate operands in eBPF are signed, and we want the disassembler | |
357 | ;; to print negative values in a sane way. Therefore we use the macro | |
358 | ;; below to register a printer, which is itself defined as a C | |
359 | ;; function in bpf.opc. | |
360 | ||
361 | ;; define-normal-signed-immediate-operand | |
362 | (define-pmacro (dnsio x-name x-comment x-attrs x-type x-index) | |
363 | (define-operand | |
364 | (name x-name) | |
365 | (comment x-comment) | |
366 | (.splice attrs (.unsplice x-attrs)) | |
367 | (type x-type) | |
368 | (index x-index) | |
369 | (handlers (print "immediate")))) | |
370 | ||
371 | (dnsio imm32 "32-bit immediate" (all-isas) h-sint f-imm32) | |
372 | (dnsio offset16 "16-bit offset" (all-isas) h-sint f-offset16) | |
373 | ||
374 | ;; The 64-bit immediate cannot use the default | |
375 | ;; cgen_parse_signed_integer, because it assumes operands are at much | |
376 | ;; 32-bit wide. Use our own. | |
377 | ||
378 | (define-operand | |
379 | (name imm64) | |
380 | (comment "64-bit immediate") | |
381 | (attrs all-isas) | |
382 | (type h-sint64) | |
383 | (index f-imm64) | |
384 | (handlers (parse "imm64") (print "immediate"))) | |
385 | ||
386 | ;; The endle/endbe instructions take an operand to specify the word | |
387 | ;; width in endianness conversions. We use both a parser and printer, | |
388 | ;; which are defined as C functions in bpf.opc. | |
389 | ||
390 | (define-operand | |
391 | (name endsize) | |
392 | (comment "endianness size immediate: 16, 32 or 64") | |
393 | (attrs all-isas) | |
394 | (type h-uint) | |
395 | (index f-imm32) | |
396 | (handlers (parse "endsize") (print "endsize"))) | |
397 | ||
398 | ;;; ALU instructions | |
399 | ||
400 | ;; For each opcode in insn-op-code-alu representing and integer | |
401 | ;; arithmetic instruction (ADD, SUB, etc) we define a bunch of | |
402 | ;; instruction variants: | |
403 | ;; | |
404 | ;; ADD[32]{i,r}le for the little-endian ISA | |
405 | ;; ADD[32]{i,r}be for the big-endian ISA | |
406 | ;; | |
78c1c354 JM |
407 | ;; The `i' variants perform `dst OP imm32 -> dst' operations. |
408 | ;; The `r' variants perform `dst OP src -> dst' operations. | |
ea195bb0 JM |
409 | ;; |
410 | ;; The variants with 32 in their name are of ALU class. Otherwise | |
411 | ;; they are ALU64 class. | |
412 | ||
78c1c354 JM |
413 | (define-pmacro (define-alu-insn-un x-basename x-suffix x-op-class x-op-code |
414 | x-endian x-mode x-semop) | |
ea195bb0 JM |
415 | (dni (.sym x-basename x-suffix x-endian) |
416 | (.str x-basename x-suffix) | |
4449c81a | 417 | (endian-isas x-endian) |
ea195bb0 JM |
418 | (.str x-basename x-suffix " $dst" x-endian) |
419 | (+ (f-imm32 0) (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian) | |
78c1c354 JM |
420 | x-op-class OP_SRC_K x-op-code) |
421 | (set x-mode (.sym dst x-endian) (x-semop x-mode (.sym dst x-endian))) | |
422 | ())) | |
ea195bb0 | 423 | |
78c1c354 | 424 | (define-pmacro (define-alu-insn-bin x-basename x-suffix x-op-class x-op-code |
6e25f888 | 425 | x-endian x-mode x-semop x-isas) |
ea195bb0 | 426 | (begin |
78c1c354 | 427 | ;; dst = dst OP immediate |
ea195bb0 JM |
428 | (dni (.sym x-basename x-suffix "i" x-endian) |
429 | (.str x-basename x-suffix " immediate") | |
6e25f888 | 430 | (.splice (.unsplice x-isas)) |
ea195bb0 JM |
431 | (.str x-basename x-suffix " $dst" x-endian ",$imm32") |
432 | (+ imm32 (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian) | |
78c1c354 JM |
433 | x-op-class OP_SRC_K x-op-code) |
434 | (set x-mode (.sym dst x-endian) (x-semop x-mode (.sym dst x-endian) imm32)) | |
435 | ()) | |
436 | ;; dst = dst OP src | |
ea195bb0 JM |
437 | (dni (.sym x-basename x-suffix "r" x-endian) |
438 | (.str x-basename x-suffix " register") | |
6e25f888 | 439 | (.splice (.unsplice x-isas)) |
ea195bb0 JM |
440 | (.str x-basename x-suffix " $dst" x-endian ",$src" x-endian) |
441 | (+ (f-imm32 0) (f-offset16 0) (.sym src x-endian) (.sym dst x-endian) | |
78c1c354 JM |
442 | x-op-class OP_SRC_X x-op-code) |
443 | (set x-mode (.sym dst x-endian) | |
444 | (x-semop x-mode (.sym dst x-endian) (.sym src x-endian))) | |
445 | ()))) | |
446 | ||
447 | (define-pmacro (define-alu-insn-mov x-basename x-suffix x-op-class x-op-code | |
448 | x-endian x-mode) | |
449 | (begin | |
450 | (dni (.sym mov x-suffix "i" x-endian) | |
451 | (.str mov x-suffix " immediate") | |
4449c81a | 452 | (endian-isas x-endian) |
78c1c354 JM |
453 | (.str x-basename x-suffix " $dst" x-endian ",$imm32") |
454 | (+ imm32 (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian) | |
455 | x-op-class OP_SRC_K x-op-code) | |
456 | (set x-mode (.sym dst x-endian) imm32) | |
457 | ()) | |
458 | (dni (.sym mov x-suffix "r" x-endian) | |
459 | (.str mov x-suffix " register") | |
4449c81a | 460 | (endian-isas x-endian) |
78c1c354 JM |
461 | (.str x-basename x-suffix " $dst" x-endian ",$src" x-endian) |
462 | (+ (f-imm32 0) (f-offset16 0) (.sym src x-endian) (.sym dst x-endian) | |
463 | x-op-class OP_SRC_X x-op-code) | |
464 | (set x-mode (.sym dst x-endian) (.sym src x-endian)) | |
465 | ()))) | |
466 | ||
ea195bb0 | 467 | |
78c1c354 JM |
468 | ;; Unary ALU instructions (neg) |
469 | (define-pmacro (daiu x-basename x-op-code x-endian x-semop) | |
ea195bb0 | 470 | (begin |
78c1c354 JM |
471 | (define-alu-insn-un x-basename "" OP_CLASS_ALU64 x-op-code x-endian DI x-semop) |
472 | (define-alu-insn-un x-basename "32" OP_CLASS_ALU x-op-code x-endian USI x-semop))) | |
ea195bb0 | 473 | |
78c1c354 JM |
474 | ;; Binary ALU instructions (all the others) |
475 | ;; For ALU32: DST = (u32) DST OP (u32) SRC is correct semantics | |
6e25f888 | 476 | (define-pmacro (daib x-basename x-op-code x-endian x-semop x-isas) |
ea195bb0 | 477 | (begin |
6e25f888 DF |
478 | (define-alu-insn-bin x-basename "" OP_CLASS_ALU64 x-op-code x-endian DI x-semop x-isas) |
479 | (define-alu-insn-bin x-basename "32" OP_CLASS_ALU x-op-code x-endian USI x-semop x-isas))) | |
78c1c354 JM |
480 | |
481 | ;; Move ALU instructions (mov) | |
482 | (define-pmacro (daim x-basename x-op-code x-endian) | |
483 | (begin | |
484 | (define-alu-insn-mov x-basename "" OP_CLASS_ALU64 x-op-code x-endian DI) | |
485 | (define-alu-insn-mov x-basename "32" OP_CLASS_ALU x-op-code x-endian USI))) | |
ea195bb0 JM |
486 | |
487 | (define-pmacro (define-alu-instructions x-endian) | |
488 | (begin | |
6e25f888 DF |
489 | (daib add OP_CODE_ADD x-endian add (endian-isas x-endian)) |
490 | (daib sub OP_CODE_SUB x-endian sub (endian-isas x-endian)) | |
491 | (daib mul OP_CODE_MUL x-endian mul (endian-isas x-endian)) | |
492 | (daib div OP_CODE_DIV x-endian udiv (endian-isas x-endian)) | |
493 | (daib or OP_CODE_OR x-endian or (endian-isas x-endian)) | |
494 | (daib and OP_CODE_AND x-endian and (endian-isas x-endian)) | |
495 | (daib lsh OP_CODE_LSH x-endian sll (endian-isas x-endian)) | |
496 | (daib rsh OP_CODE_RSH x-endian srl (endian-isas x-endian)) | |
497 | (daib mod OP_CODE_MOD x-endian umod (endian-isas x-endian)) | |
498 | (daib xor OP_CODE_XOR x-endian xor (endian-isas x-endian)) | |
499 | (daib arsh OP_CODE_ARSH x-endian sra (endian-isas x-endian)) | |
500 | (daib sdiv OP_CODE_SDIV x-endian div ((ISA (.sym xbpf x-endian)))) | |
501 | (daib smod OP_CODE_SMOD x-endian mod ((ISA (.sym xbpf x-endian)))) | |
78c1c354 JM |
502 | (daiu neg OP_CODE_NEG x-endian neg) |
503 | (daim mov OP_CODE_MOV x-endian))) | |
ea195bb0 JM |
504 | |
505 | (define-alu-instructions le) | |
506 | (define-alu-instructions be) | |
507 | ||
508 | ;;; Endianness conversion instructions | |
509 | ||
510 | ;; The endianness conversion instructions come in several variants: | |
511 | ;; | |
512 | ;; END{le,be}le for the little-endian ISA | |
513 | ;; END{le,be}be for the big-endian ISA | |
514 | ;; | |
515 | ;; Please do not be confused by the repeated `be' and `le' here. Each | |
516 | ;; ISA has both endle and endbe instructions. It is the disposition | |
517 | ;; of the source and destination register fields that change between | |
518 | ;; ISAs, not the semantics of the instructions themselves (see section | |
519 | ;; "The ISAs" above in this very file.) | |
520 | ||
521 | (define-pmacro (define-endian-insn x-suffix x-op-src x-endian) | |
522 | (dni (.sym "end" x-suffix x-endian) | |
523 | (.str "end" x-suffix " register") | |
4449c81a | 524 | (endian-isas x-endian) |
ea195bb0 JM |
525 | (.str "end" x-suffix " $dst" x-endian ",$endsize") |
526 | (+ (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian) endsize | |
78c1c354 JM |
527 | OP_CLASS_ALU x-op-src OP_CODE_END) |
528 | (set (.sym dst x-endian) | |
d73be611 | 529 | (c-call DI (.str "bpfbf_end" x-suffix) (.sym dst x-endian) endsize)) |
78c1c354 | 530 | ())) |
ea195bb0 JM |
531 | |
532 | (define-endian-insn "le" OP_SRC_K le) | |
533 | (define-endian-insn "be" OP_SRC_X le) | |
534 | (define-endian-insn "le" OP_SRC_K be) | |
535 | (define-endian-insn "be" OP_SRC_X be) | |
536 | ||
537 | ;;; Load/Store instructions | |
538 | ||
539 | ;; The lddw instruction takes a 64-bit immediate as an operand. Since | |
540 | ;; this instruction also takes a `dst' operand, we need to define a | |
541 | ;; variant for each ISA: | |
542 | ;; | |
543 | ;; LDDWle for the little-endian ISA | |
544 | ;; LDDWbe for the big-endian ISA | |
545 | ||
546 | (define-pmacro (define-lddw x-endian) | |
547 | (dni (.sym lddw x-endian) | |
548 | (.str "lddw" x-endian) | |
4449c81a | 549 | (endian-isas x-endian) |
ea195bb0 JM |
550 | (.str "lddw $dst" x-endian ",$imm64") |
551 | (+ imm64 (f-offset16 0) ((.sym f-src x-endian) 0) | |
552 | (.sym dst x-endian) | |
78c1c354 JM |
553 | OP_CLASS_LD OP_SIZE_DW OP_MODE_IMM) |
554 | (set DI (.sym dst x-endian) imm64) | |
555 | ())) | |
ea195bb0 JM |
556 | |
557 | (define-lddw le) | |
558 | (define-lddw be) | |
559 | ||
3719fd55 JM |
560 | ;; The absolute load instructions are non-generic loads designed to be |
561 | ;; used in socket filters. They come in several variants: | |
ea195bb0 | 562 | ;; |
3719fd55 JM |
563 | ;; LDABS{w,h,b,dw} |
564 | ||
78c1c354 | 565 | (define-pmacro (dlabs x-suffix x-size x-smode) |
3719fd55 JM |
566 | (dni (.sym "ldabs" x-suffix) |
567 | (.str "ldabs" x-suffix) | |
568 | (all-isas) | |
569 | (.str "ldabs" x-suffix " $imm32") | |
570 | (+ imm32 (f-offset16 0) (f-regs 0) | |
571 | OP_CLASS_LD OP_MODE_ABS (.sym OP_SIZE_ x-size)) | |
78c1c354 JM |
572 | (set x-smode |
573 | (reg x-smode h-gpr 0) | |
574 | (mem x-smode | |
575 | (add DI | |
576 | (mem DI | |
577 | (add DI | |
578 | (reg DI h-gpr 6) ;; Pointer to struct sk_buff | |
d73be611 | 579 | (c-call "bpfbf_skb_data_offset"))) |
78c1c354 JM |
580 | imm32))) |
581 | ;; XXX this clobbers R1-R5 | |
582 | ())) | |
583 | ||
584 | (dlabs "w" W SI) | |
585 | (dlabs "h" H HI) | |
586 | (dlabs "b" B QI) | |
587 | (dlabs "dw" DW DI) | |
3719fd55 JM |
588 | |
589 | ;; The indirect load instructions are non-generic loads designed to be | |
590 | ;; used in socket filters. They come in several variants: | |
591 | ;; | |
592 | ;; LDIND{w,h,b,dw}le for the little-endian ISA | |
593 | ;; LDIND[w,h,b,dw}be for the big-endian ISA | |
ea195bb0 | 594 | |
78c1c354 | 595 | (define-pmacro (dlind x-suffix x-size x-endian x-smode) |
3719fd55 JM |
596 | (dni (.sym "ldind" x-suffix x-endian) |
597 | (.str "ldind" x-suffix) | |
4449c81a | 598 | (endian-isas x-endian) |
3719fd55 | 599 | (.str "ldind" x-suffix " $src" x-endian ",$imm32") |
92434a14 | 600 | (+ imm32 (f-offset16 0) ((.sym f-dst x-endian) 0) (.sym src x-endian) |
3719fd55 | 601 | OP_CLASS_LD OP_MODE_IND (.sym OP_SIZE_ x-size)) |
78c1c354 JM |
602 | (set x-smode |
603 | (reg x-smode h-gpr 0) | |
604 | (mem x-smode | |
605 | (add DI | |
606 | (mem DI | |
607 | (add DI | |
608 | (reg DI h-gpr 6) ;; Pointer to struct sk_buff | |
d73be611 | 609 | (c-call "bpfbf_skb_data_offset"))) |
78c1c354 JM |
610 | (add DI |
611 | (.sym src x-endian) | |
612 | imm32)))) | |
613 | ;; XXX this clobbers R1-R5 | |
614 | ())) | |
3719fd55 JM |
615 | |
616 | (define-pmacro (define-ldind x-endian) | |
617 | (begin | |
78c1c354 JM |
618 | (dlind "w" W x-endian SI) |
619 | (dlind "h" H x-endian HI) | |
620 | (dlind "b" B x-endian QI) | |
621 | (dlind "dw" DW x-endian DI))) | |
3719fd55 JM |
622 | |
623 | (define-ldind le) | |
624 | (define-ldind be) | |
ea195bb0 JM |
625 | |
626 | ;; Generic load and store instructions are provided for several word | |
627 | ;; sizes. They come in several variants: | |
628 | ;; | |
629 | ;; LDX{b,h,w,dw}le, STX{b,h,w,dw}le for the little-endian ISA | |
630 | ;; | |
631 | ;; LDX{b,h,w,dw}be, STX{b,h,w,dw}be for the big-endian ISA | |
632 | ;; | |
633 | ;; Loads operate on [$SRC+-OFFSET] -> $DST | |
634 | ;; Stores operate on $SRC -> [$DST+-OFFSET] | |
635 | ||
78c1c354 | 636 | (define-pmacro (dxli x-basename x-suffix x-size x-endian x-mode) |
ea195bb0 JM |
637 | (dni (.sym x-basename x-suffix x-endian) |
638 | (.str x-basename x-suffix) | |
4449c81a | 639 | (endian-isas x-endian) |
ea195bb0 JM |
640 | (.str x-basename x-suffix " $dst" x-endian ",[$src" x-endian "+$offset16]") |
641 | (+ (f-imm32 0) offset16 (.sym src x-endian) (.sym dst x-endian) | |
642 | OP_CLASS_LDX (.sym OP_SIZE_ x-size) OP_MODE_MEM) | |
78c1c354 JM |
643 | (set x-mode |
644 | (.sym dst x-endian) | |
d73be611 | 645 | (mem x-mode (add DI (.sym src x-endian) offset16))) |
78c1c354 | 646 | ())) |
ea195bb0 | 647 | |
78c1c354 | 648 | (define-pmacro (dxsi x-basename x-suffix x-size x-endian x-mode) |
ea195bb0 JM |
649 | (dni (.sym x-basename x-suffix x-endian) |
650 | (.str x-basename x-suffix) | |
4449c81a | 651 | (endian-isas x-endian) |
ea195bb0 JM |
652 | (.str x-basename x-suffix " [$dst" x-endian "+$offset16],$src" x-endian) |
653 | (+ (f-imm32 0) offset16 (.sym src x-endian) (.sym dst x-endian) | |
654 | OP_CLASS_STX (.sym OP_SIZE_ x-size) OP_MODE_MEM) | |
78c1c354 | 655 | (set x-mode |
d73be611 | 656 | (mem x-mode (add DI (.sym dst x-endian) offset16)) |
78c1c354 JM |
657 | (.sym src x-endian)) ;; XXX address is section-relative |
658 | ())) | |
ea195bb0 JM |
659 | |
660 | (define-pmacro (define-ldstx-insns x-endian) | |
661 | (begin | |
78c1c354 JM |
662 | (dxli "ldx" "w" W x-endian SI) |
663 | (dxli "ldx" "h" H x-endian HI) | |
664 | (dxli "ldx" "b" B x-endian QI) | |
665 | (dxli "ldx" "dw" DW x-endian DI) | |
ea195bb0 | 666 | |
78c1c354 JM |
667 | (dxsi "stx" "w" W x-endian SI) |
668 | (dxsi "stx" "h" H x-endian HI) | |
669 | (dxsi "stx" "b" B x-endian QI) | |
670 | (dxsi "stx" "dw" DW x-endian DI))) | |
ea195bb0 JM |
671 | |
672 | (define-ldstx-insns le) | |
673 | (define-ldstx-insns be) | |
674 | ||
675 | ;; Generic store instructions of the form IMM32 -> [$DST+OFFSET] are | |
676 | ;; provided in several variants: | |
677 | ;; | |
678 | ;; ST{b,h,w,dw}le for the little-endian ISA | |
679 | ;; ST{b,h,w,dw}be for the big-endian ISA | |
680 | ||
78c1c354 | 681 | (define-pmacro (dsti x-suffix x-size x-endian x-mode) |
ea195bb0 JM |
682 | (dni (.sym "st" x-suffix x-endian) |
683 | (.str "st" x-suffix) | |
4449c81a | 684 | (endian-isas x-endian) |
ea195bb0 JM |
685 | (.str "st" x-suffix " [$dst" x-endian "+$offset16],$imm32") |
686 | (+ imm32 offset16 ((.sym f-src x-endian) 0) (.sym dst x-endian) | |
78c1c354 JM |
687 | OP_CLASS_ST (.sym OP_SIZE_ x-size) OP_MODE_MEM) |
688 | (set x-mode | |
689 | (mem x-mode (add DI (.sym dst x-endian) offset16)) | |
690 | imm32) ;; XXX address is section-relative | |
691 | ())) | |
ea195bb0 JM |
692 | |
693 | (define-pmacro (define-st-insns x-endian) | |
694 | (begin | |
78c1c354 JM |
695 | (dsti "b" B x-endian QI) |
696 | (dsti "h" H x-endian HI) | |
697 | (dsti "w" W x-endian SI) | |
698 | (dsti "dw" DW x-endian DI))) | |
ea195bb0 JM |
699 | |
700 | (define-st-insns le) | |
701 | (define-st-insns be) | |
702 | ||
703 | ;;; Jump instructions | |
704 | ||
705 | ;; Compare-and-jump instructions, on the other hand, make use of | |
706 | ;; registers. Therefore, we need to define several variants in both | |
707 | ;; ISAs: | |
708 | ;; | |
c54a9b56 | 709 | ;; J{eq,gt,ge,lt,le,set,ne,sgt,sge,slt,sle}[32]{i,r}le for the |
ea195bb0 | 710 | ;; little-endian ISA. |
c54a9b56 | 711 | ;; J{eq,gt,ge,lt,le,set,ne.sgt,sge,slt,sle}[32]{i,r}be for the |
ea195bb0 JM |
712 | ;; big-endian ISA. |
713 | ||
78c1c354 | 714 | (define-pmacro (define-cond-jump-insn x-cond x-suffix x-op-class x-op-code x-endian x-mode x-semop) |
ea195bb0 | 715 | (begin |
c54a9b56 DF |
716 | (dni (.sym j x-cond x-suffix i x-endian) |
717 | (.str j x-cond x-suffix " i") | |
4449c81a | 718 | (endian-isas x-endian) |
c54a9b56 | 719 | (.str "j" x-cond x-suffix " $dst" x-endian ",$imm32,$disp16") |
ea195bb0 | 720 | (+ imm32 disp16 ((.sym f-src x-endian) 0) (.sym dst x-endian) |
78c1c354 JM |
721 | x-op-class OP_SRC_K (.sym OP_CODE_ x-op-code)) |
722 | (if VOID (x-semop x-mode (.sym dst x-endian) imm32) | |
723 | (set DI | |
724 | (reg DI h-pc) (add DI (reg DI h-pc) | |
725 | (mul DI (add HI disp16 1) 8)))) | |
726 | ()) | |
c54a9b56 DF |
727 | (dni (.sym j x-cond x-suffix r x-endian) |
728 | (.str j x-cond x-suffix " r") | |
4449c81a | 729 | (endian-isas x-endian) |
c54a9b56 | 730 | (.str "j" x-cond x-suffix " $dst" x-endian ",$src" x-endian ",$disp16") |
ea195bb0 | 731 | (+ (f-imm32 0) disp16 (.sym src x-endian) (.sym dst x-endian) |
78c1c354 JM |
732 | x-op-class OP_SRC_X (.sym OP_CODE_ x-op-code)) |
733 | (if VOID (x-semop x-mode (.sym dst x-endian) (.sym src x-endian)) | |
734 | (set DI | |
735 | (reg DI h-pc) (add DI (reg DI h-pc) | |
736 | (mul DI (add HI disp16 1) 8)))) | |
737 | ()))) | |
738 | ||
739 | (define-pmacro (dcji x-cond x-op-code x-endian x-semop) | |
c54a9b56 | 740 | (begin |
78c1c354 JM |
741 | (define-cond-jump-insn x-cond "" OP_CLASS_JMP x-op-code x-endian DI x-semop) |
742 | (define-cond-jump-insn x-cond "32" OP_CLASS_JMP32 x-op-code x-endian SI x-semop ))) | |
ea195bb0 JM |
743 | |
744 | (define-pmacro (define-condjump-insns x-endian) | |
745 | (begin | |
78c1c354 JM |
746 | (dcji "eq" JEQ x-endian eq) |
747 | (dcji "gt" JGT x-endian gtu) | |
748 | (dcji "ge" JGE x-endian geu) | |
749 | (dcji "lt" JLT x-endian ltu) | |
750 | (dcji "le" JLE x-endian leu) | |
751 | (dcji "set" JSET x-endian and) | |
752 | (dcji "ne" JNE x-endian ne) | |
753 | (dcji "sgt" JSGT x-endian gt) | |
754 | (dcji "sge" JSGE x-endian ge) | |
755 | (dcji "slt" JSLT x-endian lt) | |
756 | (dcji "sle" JSLE x-endian le))) | |
ea195bb0 JM |
757 | |
758 | (define-condjump-insns le) | |
759 | (define-condjump-insns be) | |
760 | ||
78c1c354 JM |
761 | ;; The `call' instruction doesn't make use of registers, but the |
762 | ;; semantic routine should have access to the src register in order to | |
763 | ;; properly interpret the meaning of disp32. Therefore we need one | |
764 | ;; version per ISA. | |
765 | ||
766 | (define-pmacro (define-call-insn x-endian) | |
767 | (dni (.sym call x-endian) | |
768 | "call" | |
4449c81a | 769 | (endian-isas x-endian) |
78c1c354 JM |
770 | "call $disp32" |
771 | (+ disp32 (f-offset16 0) (f-regs 0) | |
772 | OP_CLASS_JMP OP_SRC_K OP_CODE_CALL) | |
773 | (c-call VOID | |
774 | "bpfbf_call" disp32 (ifield (.sym f-src x-endian))) | |
775 | ())) | |
776 | ||
777 | (define-call-insn le) | |
778 | (define-call-insn be) | |
779 | ||
4449c81a DF |
780 | (define-pmacro (define-callr-insn x-endian) |
781 | (dni (.sym callr x-endian) | |
782 | "callr" | |
783 | ((ISA (.sym xbpf x-endian))) | |
784 | (.str "call $dst" x-endian) | |
785 | (+ (f-imm32 0) (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian) | |
786 | OP_CLASS_JMP OP_SRC_X OP_CODE_CALL) | |
787 | (c-call VOID | |
788 | "bpfbf_callr" (ifield (.sym f-dst x-endian))) | |
789 | ())) | |
790 | ||
791 | (define-callr-insn le) | |
792 | (define-callr-insn be) | |
793 | ||
78c1c354 JM |
794 | ;; The jump-always and `exit' instructions dont make use of either |
795 | ;; source nor destination registers, so only one variant per | |
ea195bb0 JM |
796 | ;; instruction is defined. |
797 | ||
798 | (dni ja "ja" (all-isas) "ja $disp16" | |
799 | (+ (f-imm32 0) disp16 (f-regs 0) | |
78c1c354 JM |
800 | OP_CLASS_JMP OP_SRC_K OP_CODE_JA) |
801 | (set DI (reg DI h-pc) (add DI (reg DI h-pc) | |
802 | (mul DI (add HI disp16 1) 8))) | |
803 | ()) | |
ea195bb0 JM |
804 | |
805 | (dni "exit" "exit" (all-isas) "exit" | |
806 | (+ (f-imm32 0) (f-offset16 0) (f-regs 0) | |
78c1c354 JM |
807 | OP_CLASS_JMP (f-op-src 0) OP_CODE_EXIT) |
808 | (c-call VOID "bpfbf_exit") | |
809 | ()) | |
ea195bb0 JM |
810 | |
811 | ;;; Atomic instructions | |
812 | ||
813 | ;; The atomic exchange-and-add instructions come in two flavors: one | |
814 | ;; for swapping 64-bit quantities and another for 32-bit quantities. | |
815 | ||
78c1c354 JM |
816 | (define-pmacro (sem-exchange-and-add x-endian x-mode) |
817 | (sequence VOID ((x-mode tmp)) | |
818 | ;; XXX acquire lock in simulator... as a hardware element? | |
819 | (set x-mode tmp (mem x-mode (add DI (.sym dst x-endian) offset16))) | |
820 | (set x-mode | |
821 | (mem x-mode (add DI (.sym dst x-endian) offset16)) | |
822 | (add x-mode tmp (.sym src x-endian))))) | |
823 | ||
ea195bb0 JM |
824 | (define-pmacro (define-atomic-insns x-endian) |
825 | (begin | |
826 | (dni (.str "xadddw" x-endian) | |
827 | "xadddw" | |
4449c81a | 828 | (endian-isas x-endian) |
ea195bb0 JM |
829 | (.str "xadddw [$dst" x-endian "+$offset16],$src" x-endian) |
830 | (+ (f-imm32 0) (.sym src x-endian) (.sym dst x-endian) | |
78c1c354 JM |
831 | offset16 OP_MODE_XADD OP_SIZE_DW OP_CLASS_STX) |
832 | (sem-exchange-and-add x-endian DI) | |
833 | ()) | |
ea195bb0 JM |
834 | (dni (.str "xaddw" x-endian) |
835 | "xaddw" | |
4449c81a | 836 | (endian-isas x-endian) |
ea195bb0 JM |
837 | (.str "xaddw [$dst" x-endian "+$offset16],$src" x-endian) |
838 | (+ (f-imm32 0) (.sym src x-endian) (.sym dst x-endian) | |
78c1c354 JM |
839 | offset16 OP_MODE_XADD OP_SIZE_W OP_CLASS_STX) |
840 | (sem-exchange-and-add x-endian SI) | |
841 | ()))) | |
ea195bb0 JM |
842 | |
843 | (define-atomic-insns le) | |
844 | (define-atomic-insns be) | |
78c1c354 JM |
845 | |
846 | ;;; Breakpoint instruction | |
847 | ||
848 | ;; The brkpt instruction is used by the BPF simulator and it doesn't | |
849 | ;; really belong to the eBPF instruction set. | |
850 | ||
851 | (dni "brkpt" "brkpt" (all-isas) "brkpt" | |
852 | (+ (f-imm32 0) (f-offset16 0) (f-regs 0) | |
853 | OP_CLASS_ALU OP_SRC_X OP_CODE_NEG) | |
854 | (c-call VOID "bpfbf_breakpoint") | |
855 | ()) |