summaryrefslogtreecommitdiff
path: root/tests/run.scm
blob: fc7c3d6a73339286350824d45ef7a1624335dd77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
(use test matchable)

(include "../bpf-assembler.scm")

(import bpf-assembler)

(test-begin "BPF assembler")

(test-group "single instruction assembly/disassembly invariance"
  (for-each (lambda (expr)
              (test (->string expr)
                    expr
                    (car (bpf-bytecode->exprs
                          (exprs->bpf-bytecode (list expr))))))
            `(;; load word into accumulator register
              (ld len) (ld 1) (ld (mem 1)) (ld (pkt 1)) (ld (pkt x 1))
              ;; load byte/halfword into accumulator register
              (ldb (pkt 1)) (ldb (pkt x 1)) (ldh (pkt 1)) (ldh (pkt x 1))
              ;; load index register
              (ldx len) (ldx 1) (ldx (mem 1)) (ldx (pkt 4* 1))
              ;; store accumulator/index register
              (st (mem 1)) (stx (mem 1))
              ;; jump unconditionally (sometimes called JA instead of JMP)
              (jmp 1)
              ;; Jump conditionally on comparison of acc w/ immediate or idx
              (jeq 1 2 3) (jeq x 2 3) (jgt 1 2 3) (jgt x 2 3)
              (jge 1 2 3) (jge x 2 3)
              ;; Jump if bit # from immediate/index register is set in acc
              (jset 1 2 3) (jset x 2 3)
              ;; ALU instructions: operates on acc w/ immediate or index
              (add 1) (add x) (sub 1) (sub x) (mul 1) (mul x) (div 1) (div x)
              (or 1) (or x) (and 1) (and x) (lsh 1) (lsh x) (rsh 1) (rsh x)
              ;; Negate accumulator (no operands)
              (neg)
              ;; Return # of bytes in acc or idx registers or immediate
              (ret 1) (ret a) (ret x)
              ;; Transfer value between accumulator and index
              (tax) (txa))))

(test-group "Invalid opcode/addressing mode combinations"
  (for-each (match-lambda
              ((subgroup-name exprs ...)
               (test-group subgroup-name
                 (for-each (lambda (expr)
                             (test-error
                              (->string expr)
                              (car (bpf-bytecode->exprs
                                    (exprs->bpf-bytecode (list expr))))))
                           exprs))))
            `(("load of word into accumulator from invalid types"
               (ld x) (ld a) (ld (pkt 4* 1)))
              ("load of halfword into accumulator from invalid types"
               (ldh len) (ldh x) (ldh a) (ldh (pkt 4* 1)))
              ("load of byte into accumulator from invalid types"
               (ldb len) (ldb x) (ldb a) (ldb (pkt 4* 1)))
              ("load of word into index from invalid types"
               (ldx (pkt 1)) (ldx a) (ldx x) (ldx (pkt 1)) (ldx (pkt x 1)))

              ("store of accumulator into memory must be immediate memory index"
               (st 1) (st len) (st a) (st x) (st (mem x 1))
               (st (pkt 1)) (st (pkt 4* 1)))
              ("store of index into memory must be immediate memory index"
               (stx 1) (stx len) (stx a) (stx x) (stx (mem x 1))
               (stx (pkt 1)) (stx (pkt 4* 1)))

              ("bogus jump types"
               (jmp x) (jmp a) (jmp (mem 1)) (jmp len))
              
              ("unconditional jumps can't work conditionally"
               (jmp 1 2 3) (jmp x 2 3))

              ("bogus unconditional jumps"
               (jmp (mem 1) 2 3) (jmp len 2 3) (jmp a 2 3))

              ("conditional jumps can't work unconditionally"
               (jeq 1) (jeq x) (jgt 1) (jgt x) (jge 1) (jge x) (jset 1) (jset x))

              ;; Only test add, the rest are defined identically
              ("diadic ALU instructions with disallowed operands"
               (add a) (add (mem 1)) (add (pkt 1)) (add (pkt x 1)) (add (pkt 4* 1)))
              
              ("monadic instructions with operands"
               (neg 1) (neg x) (neg a) (neg (mem 1))
               ;; Only do txa, tax is defined identically
               (txa 1) (txa x) (txa a) (txa (mem 1)))
              
              ("returning non-immediate, non-register values"
               (ret (mem 1)) (ret (pkt 1)) (ret (pkt x 1)) (ret (pkt 4* 1))))))

(test-end "BPF assembler")

(test-exit)