;; It is confusing that the simulator follows the emulated memory
;; access conventions for fetching instructions by pieces...
(default-alignment unaligned)
- (machs bpf)
- (isas ebpfle ebpfbe))
+ (machs bpf xbpf)
+ (isas ebpfle ebpfbe xbpfle xbpfbe))
;;;; The ISAs
(define-bpf-isa le)
(define-bpf-isa be)
-(define-pmacro all-isas () (ISA ebpfle,ebpfbe))
+(define-pmacro (define-xbpf-isa x-endian)
+ (define-isa
+ (name (.sym xbpf x-endian))
+ (comment "The xBPF instruction set")
+ (default-insn-word-bitsize 64)
+ (default-insn-bitsize 64)
+ (base-insn-bitsize 64)))
+
+(define-xbpf-isa le)
+(define-xbpf-isa be)
+
+(define-pmacro all-isas () (ISA ebpfle,ebpfbe,xbpfle,xbpfbe))
+(define-pmacro xbpf-isas () (ISA xbpfle,xbpfbe))
+
+(define-pmacro (endian-isas x-endian)
+ ((ISA (.sym ebpf x-endian) (.sym xbpf x-endian))))
;;;; Hardware Hierarchy
;;
-;; bpf architecture
-;; |
-;; bpfbf cpu-family
-;; |
-;; bpf machine
-;; |
-;; bpf-def model
+;; bpf architecture
+;; |
+;; bpfbf cpu-family
+;; / \
+;; bpf xbpf machine
+;; | |
+;; bpf-def xbpf-def model
(define-cpu
(name bpfbf)
() ; profile action (default)
))
+(define-mach
+ (name xbpf)
+ (comment "Experimental BPF")
+ (cpu bpfbf)
+ (isas ebpfle ebpfbe xbpfle xbpfbe))
+
+(define-model
+ (name xbpf-def)
+ (comment "xBPF default model")
+ (mach xbpf)
+ (unit u-exec "execution unit" ()
+ 1 ; issue
+ 1 ; done
+ () ; state
+ () ; inputs
+ () ; outputs
+ () ; profile action (default)
+ ))
+
;;;; Hardware Elements
;; eBPF programs can access 10 general-purpose registers which are
(define-hardware
(name h-gpr)
(comment "General Purpose Registers")
- (attrs all-isas (MACH bpf))
+ (attrs all-isas (MACH bpf xbpf))
(type register DI (16))
(indices keyword "%"
;; XXX the frame pointer fp is read-only, so it should
(ADD #x0) (SUB #x1) (MUL #x2) (DIV #x3) (OR #x4) (AND #x5)
(LSH #x6) (RSH #x7) (NEG #x8) (MOD #x9) (XOR #xa) (MOV #xb)
(ARSH #xc) (END #xd)
+ ;; xBPF-only: signed div, signed mod
+ (SDIV #xe) (SMOD #xf)
;; Codes for OP_CLASS_JMP
(JA #x0) (JEQ #x1) (JGT #x2) (JGE #x3) (JSET #x4)
(JNE #x5) (JSGT #x6) (JSGE #x7) (CALL #x8) (EXIT #x9)
;; NOT use registers, where endianness is irrelevant i.e. f-regs is a
;; constant 0 opcode.
-(dwf f-dstle "eBPF dst register field" ((ISA ebpfle)) 8 8 3 4 UINT)
-(dwf f-srcle "eBPF source register field" ((ISA ebpfle)) 8 8 7 4 UINT)
+(dwf f-dstle "eBPF dst register field" ((ISA ebpfle xbpfle)) 8 8 3 4 UINT)
+(dwf f-srcle "eBPF source register field" ((ISA ebpfle xbpfle)) 8 8 7 4 UINT)
-(dwf f-dstbe "eBPF dst register field" ((ISA ebpfbe)) 8 8 7 4 UINT)
-(dwf f-srcbe "eBPF source register field" ((ISA ebpfbe)) 8 8 3 4 UINT)
+(dwf f-dstbe "eBPF dst register field" ((ISA ebpfbe xbpfbe)) 8 8 7 4 UINT)
+(dwf f-srcbe "eBPF source register field" ((ISA ebpfbe xbpfbe)) 8 8 3 4 UINT)
(dwf f-regs "eBPF registers field" (all-isas) 8 8 7 8 UINT)
;; difficulty: we put them in their own instruction word so the
;; byte-endianness will be properly applied.
-(dwf f-offset16 "eBPF offset field" (all-isas) 16 16 15 16 INT)
+(dwf f-offset16 "eBPF offset field" (all-isas) 16 16 15 16 HI)
(dwf f-imm32 "eBPF 32-bit immediate field" (all-isas) 32 32 31 32 INT)
;; For the disjoint 64-bit signed immediate, however, we need to use a
;; A couple of source and destination register operands are defined
;; for each ISA: ebpfle and ebpfbe.
-(dno dstle "destination register" ((ISA ebpfle)) h-gpr f-dstle)
-(dno srcle "source register" ((ISA ebpfle)) h-gpr f-srcle)
+(dno dstle "destination register" ((ISA ebpfle xbpfle)) h-gpr f-dstle)
+(dno srcle "source register" ((ISA ebpfle xbpfle)) h-gpr f-srcle)
-(dno dstbe "destination register" ((ISA ebpfbe)) h-gpr f-dstbe)
-(dno srcbe "source register" ((ISA ebpfbe)) h-gpr f-srcbe)
+(dno dstbe "destination register" ((ISA ebpfbe xbpfbe)) h-gpr f-dstbe)
+(dno srcbe "source register" ((ISA ebpfbe xbpfbe)) h-gpr f-srcbe)
;; Jump instructions have a 16-bit PC-relative address.
;; CALL instructions have a 32-bit PC-relative address.
x-endian x-mode x-semop)
(dni (.sym x-basename x-suffix x-endian)
(.str x-basename x-suffix)
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str x-basename x-suffix " $dst" x-endian)
(+ (f-imm32 0) (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian)
x-op-class OP_SRC_K x-op-code)
()))
(define-pmacro (define-alu-insn-bin x-basename x-suffix x-op-class x-op-code
- x-endian x-mode x-semop)
+ x-endian x-mode x-semop x-isas)
(begin
;; dst = dst OP immediate
(dni (.sym x-basename x-suffix "i" x-endian)
(.str x-basename x-suffix " immediate")
- ((ISA (.sym ebpf x-endian)))
+ (.splice (.unsplice x-isas))
(.str x-basename x-suffix " $dst" x-endian ",$imm32")
(+ imm32 (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian)
x-op-class OP_SRC_K x-op-code)
;; dst = dst OP src
(dni (.sym x-basename x-suffix "r" x-endian)
(.str x-basename x-suffix " register")
- ((ISA (.sym ebpf x-endian)))
+ (.splice (.unsplice x-isas))
(.str x-basename x-suffix " $dst" x-endian ",$src" x-endian)
(+ (f-imm32 0) (f-offset16 0) (.sym src x-endian) (.sym dst x-endian)
x-op-class OP_SRC_X x-op-code)
(begin
(dni (.sym mov x-suffix "i" x-endian)
(.str mov x-suffix " immediate")
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str x-basename x-suffix " $dst" x-endian ",$imm32")
(+ imm32 (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian)
x-op-class OP_SRC_K x-op-code)
())
(dni (.sym mov x-suffix "r" x-endian)
(.str mov x-suffix " register")
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str x-basename x-suffix " $dst" x-endian ",$src" x-endian)
(+ (f-imm32 0) (f-offset16 0) (.sym src x-endian) (.sym dst x-endian)
x-op-class OP_SRC_X x-op-code)
;; Binary ALU instructions (all the others)
;; For ALU32: DST = (u32) DST OP (u32) SRC is correct semantics
-(define-pmacro (daib x-basename x-op-code x-endian x-semop)
+(define-pmacro (daib x-basename x-op-code x-endian x-semop x-isas)
(begin
- (define-alu-insn-bin x-basename "" OP_CLASS_ALU64 x-op-code x-endian DI x-semop)
- (define-alu-insn-bin x-basename "32" OP_CLASS_ALU x-op-code x-endian USI x-semop)))
+ (define-alu-insn-bin x-basename "" OP_CLASS_ALU64 x-op-code x-endian DI x-semop x-isas)
+ (define-alu-insn-bin x-basename "32" OP_CLASS_ALU x-op-code x-endian USI x-semop x-isas)))
;; Move ALU instructions (mov)
(define-pmacro (daim x-basename x-op-code x-endian)
(define-pmacro (define-alu-instructions x-endian)
(begin
- (daib add OP_CODE_ADD x-endian add)
- (daib sub OP_CODE_SUB x-endian sub)
- (daib mul OP_CODE_MUL x-endian mul)
- (daib div OP_CODE_DIV x-endian div)
- (daib or OP_CODE_OR x-endian or)
- (daib and OP_CODE_AND x-endian and)
- (daib lsh OP_CODE_LSH x-endian sll)
- (daib rsh OP_CODE_RSH x-endian srl)
- (daib mod OP_CODE_MOD x-endian mod)
- (daib xor OP_CODE_XOR x-endian xor)
- (daib arsh OP_CODE_ARSH x-endian sra)
+ (daib add OP_CODE_ADD x-endian add (endian-isas x-endian))
+ (daib sub OP_CODE_SUB x-endian sub (endian-isas x-endian))
+ (daib mul OP_CODE_MUL x-endian mul (endian-isas x-endian))
+ (daib div OP_CODE_DIV x-endian udiv (endian-isas x-endian))
+ (daib or OP_CODE_OR x-endian or (endian-isas x-endian))
+ (daib and OP_CODE_AND x-endian and (endian-isas x-endian))
+ (daib lsh OP_CODE_LSH x-endian sll (endian-isas x-endian))
+ (daib rsh OP_CODE_RSH x-endian srl (endian-isas x-endian))
+ (daib mod OP_CODE_MOD x-endian umod (endian-isas x-endian))
+ (daib xor OP_CODE_XOR x-endian xor (endian-isas x-endian))
+ (daib arsh OP_CODE_ARSH x-endian sra (endian-isas x-endian))
+ (daib sdiv OP_CODE_SDIV x-endian div ((ISA (.sym xbpf x-endian))))
+ (daib smod OP_CODE_SMOD x-endian mod ((ISA (.sym xbpf x-endian))))
(daiu neg OP_CODE_NEG x-endian neg)
(daim mov OP_CODE_MOV x-endian)))
(define-pmacro (define-endian-insn x-suffix x-op-src x-endian)
(dni (.sym "end" x-suffix x-endian)
(.str "end" x-suffix " register")
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "end" x-suffix " $dst" x-endian ",$endsize")
(+ (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian) endsize
OP_CLASS_ALU x-op-src OP_CODE_END)
(set (.sym dst x-endian)
- (c-call DI "bpfbf_end" (.sym dst x-endian) endsize))
+ (c-call DI (.str "bpfbf_end" x-suffix) (.sym dst x-endian) endsize))
()))
(define-endian-insn "le" OP_SRC_K le)
(define-pmacro (define-lddw x-endian)
(dni (.sym lddw x-endian)
(.str "lddw" x-endian)
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "lddw $dst" x-endian ",$imm64")
(+ imm64 (f-offset16 0) ((.sym f-src x-endian) 0)
(.sym dst x-endian)
(mem DI
(add DI
(reg DI h-gpr 6) ;; Pointer to struct sk_buff
- (const DI 0))) ;; XXX offsetof
- ;; (struct sk_buff, data) XXX but the offset
- ;; depends on CONFIG_* options, so this should
- ;; be configured in the simulator and driven by
- ;; command-line options. Handle with a c-call.
+ (c-call "bpfbf_skb_data_offset")))
imm32)))
;; XXX this clobbers R1-R5
()))
(define-pmacro (dlind x-suffix x-size x-endian x-smode)
(dni (.sym "ldind" x-suffix x-endian)
(.str "ldind" x-suffix)
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "ldind" x-suffix " $src" x-endian ",$imm32")
(+ imm32 (f-offset16 0) ((.sym f-dst x-endian) 0) (.sym src x-endian)
OP_CLASS_LD OP_MODE_IND (.sym OP_SIZE_ x-size))
(mem DI
(add DI
(reg DI h-gpr 6) ;; Pointer to struct sk_buff
- (const DI 0))) ;; XXX offsetof
- ;; (struct sk_buff, data) XXX but the offset
- ;; depends on CONFIG_* options, so this should
- ;; be configured in the simulator and driven by
- ;; command-line options. Handle with a c-call.
+ (c-call "bpfbf_skb_data_offset")))
(add DI
(.sym src x-endian)
imm32))))
(define-pmacro (dxli x-basename x-suffix x-size x-endian x-mode)
(dni (.sym x-basename x-suffix x-endian)
(.str x-basename x-suffix)
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str x-basename x-suffix " $dst" x-endian ",[$src" x-endian "+$offset16]")
(+ (f-imm32 0) offset16 (.sym src x-endian) (.sym dst x-endian)
OP_CLASS_LDX (.sym OP_SIZE_ x-size) OP_MODE_MEM)
(set x-mode
(.sym dst x-endian)
- (mem x-mode (add DI (.sym src x-endian) (ext DI (trunc HI offset16)))))
+ (mem x-mode (add DI (.sym src x-endian) offset16)))
()))
(define-pmacro (dxsi x-basename x-suffix x-size x-endian x-mode)
(dni (.sym x-basename x-suffix x-endian)
(.str x-basename x-suffix)
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str x-basename x-suffix " [$dst" x-endian "+$offset16],$src" x-endian)
(+ (f-imm32 0) offset16 (.sym src x-endian) (.sym dst x-endian)
OP_CLASS_STX (.sym OP_SIZE_ x-size) OP_MODE_MEM)
(set x-mode
- (mem x-mode (add DI (.sym dst x-endian) (ext DI (trunc HI offset16))))
+ (mem x-mode (add DI (.sym dst x-endian) offset16))
(.sym src x-endian)) ;; XXX address is section-relative
()))
(define-pmacro (dsti x-suffix x-size x-endian x-mode)
(dni (.sym "st" x-suffix x-endian)
(.str "st" x-suffix)
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "st" x-suffix " [$dst" x-endian "+$offset16],$imm32")
(+ imm32 offset16 ((.sym f-src x-endian) 0) (.sym dst x-endian)
OP_CLASS_ST (.sym OP_SIZE_ x-size) OP_MODE_MEM)
(begin
(dni (.sym j x-cond x-suffix i x-endian)
(.str j x-cond x-suffix " i")
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "j" x-cond x-suffix " $dst" x-endian ",$imm32,$disp16")
(+ imm32 disp16 ((.sym f-src x-endian) 0) (.sym dst x-endian)
x-op-class OP_SRC_K (.sym OP_CODE_ x-op-code))
())
(dni (.sym j x-cond x-suffix r x-endian)
(.str j x-cond x-suffix " r")
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "j" x-cond x-suffix " $dst" x-endian ",$src" x-endian ",$disp16")
(+ (f-imm32 0) disp16 (.sym src x-endian) (.sym dst x-endian)
x-op-class OP_SRC_X (.sym OP_CODE_ x-op-code))
(define-pmacro (define-call-insn x-endian)
(dni (.sym call x-endian)
"call"
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
"call $disp32"
(+ disp32 (f-offset16 0) (f-regs 0)
OP_CLASS_JMP OP_SRC_K OP_CODE_CALL)
(define-call-insn le)
(define-call-insn be)
+(define-pmacro (define-callr-insn x-endian)
+ (dni (.sym callr x-endian)
+ "callr"
+ ((ISA (.sym xbpf x-endian)))
+ (.str "call $dst" x-endian)
+ (+ (f-imm32 0) (f-offset16 0) ((.sym f-src x-endian) 0) (.sym dst x-endian)
+ OP_CLASS_JMP OP_SRC_X OP_CODE_CALL)
+ (c-call VOID
+ "bpfbf_callr" (ifield (.sym f-dst x-endian)))
+ ()))
+
+(define-callr-insn le)
+(define-callr-insn be)
+
;; The jump-always and `exit' instructions dont make use of either
;; source nor destination registers, so only one variant per
;; instruction is defined.
(begin
(dni (.str "xadddw" x-endian)
"xadddw"
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "xadddw [$dst" x-endian "+$offset16],$src" x-endian)
(+ (f-imm32 0) (.sym src x-endian) (.sym dst x-endian)
offset16 OP_MODE_XADD OP_SIZE_DW OP_CLASS_STX)
())
(dni (.str "xaddw" x-endian)
"xaddw"
- ((ISA (.sym ebpf x-endian)))
+ (endian-isas x-endian)
(.str "xaddw [$dst" x-endian "+$offset16],$src" x-endian)
(+ (f-imm32 0) (.sym src x-endian) (.sym dst x-endian)
offset16 OP_MODE_XADD OP_SIZE_W OP_CLASS_STX)