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