aboutsummaryrefslogtreecommitdiff
path: root/sim/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'sim/testsuite')
-rw-r--r--sim/testsuite/ChangeLog17
-rwxr-xr-xsim/testsuite/configure3
-rw-r--r--sim/testsuite/sim/bpf/allinsn.exp26
-rw-r--r--sim/testsuite/sim/bpf/alu.s109
-rw-r--r--sim/testsuite/sim/bpf/alu32.s99
-rw-r--r--sim/testsuite/sim/bpf/endbe.s46
-rw-r--r--sim/testsuite/sim/bpf/endle.s43
-rw-r--r--sim/testsuite/sim/bpf/jmp.s120
-rw-r--r--sim/testsuite/sim/bpf/jmp32.s120
-rw-r--r--sim/testsuite/sim/bpf/ldabs.s87
-rw-r--r--sim/testsuite/sim/bpf/mem.s56
-rw-r--r--sim/testsuite/sim/bpf/mov.s54
-rw-r--r--sim/testsuite/sim/bpf/testutils.inc38
-rw-r--r--sim/testsuite/sim/bpf/xadd.s44
14 files changed, 862 insertions, 0 deletions
diff --git a/sim/testsuite/ChangeLog b/sim/testsuite/ChangeLog
index e3b47aa..f2df734 100644
--- a/sim/testsuite/ChangeLog
+++ b/sim/testsuite/ChangeLog
@@ -1,3 +1,20 @@
+2020-08-04 David Faust <david.faust@oracle.com>
+ Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * configure: Regenerate.
+ * sim/bpf/allinsn.exp: New file.
+ * sim/bpf/alu.s: Likewise.
+ * sim/bpf/alu32.s: Likewise.
+ * sim/bpf/endbe.s: Likewise.
+ * sim/bpf/endle.s: Likewise.
+ * sim/bpf/jmp.s: Likewise.
+ * sim/bpf/jmp32.s: Likewise.
+ * sim/bpf/ldabs.s: Likewise.
+ * sim/bpf/mem.s: Likewise.
+ * sim/bpf/mov.s: Likewise.
+ * sim/bpf/testutils.inc: Likewise.
+ * sim/bpf/xadd.s: Likewise.
+
2020-07-29 Simon Marchi <simon.marchi@efficios.com>
* configure: Re-generate.
diff --git a/sim/testsuite/configure b/sim/testsuite/configure
index d15fbba..c3674c2 100755
--- a/sim/testsuite/configure
+++ b/sim/testsuite/configure
@@ -1875,6 +1875,9 @@ case "${target}" in
bfin-*-*)
sim_arch=bfin
;;
+ bpf-*-*)
+ sim_arch=bpf
+ ;;
cr16*-*-*)
sim_arch=cr16
;;
diff --git a/sim/testsuite/sim/bpf/allinsn.exp b/sim/testsuite/sim/bpf/allinsn.exp
new file mode 100644
index 0000000..2cca770
--- /dev/null
+++ b/sim/testsuite/sim/bpf/allinsn.exp
@@ -0,0 +1,26 @@
+# eBPF simulator testsuite
+
+if [istarget bpf-unknown-none] {
+ # all machines
+ set all_machs "bpf"
+
+ global global_sim_options
+ if ![info exists global_sim_options] {
+ set global_sim_options "--memory-size=4Mb"
+ }
+
+ global global_ld_options
+ if ![info exists global_ld_options] {
+ set global_ld_options "-Ttext=0x0"
+ }
+
+ foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.s]] {
+ # If we're only testing specific files and this isn't one of them,
+ # skip it.
+ if ![runtest_file_p $runtests $src] {
+ continue
+ }
+
+ run_sim_test $src $all_machs
+ }
+}
diff --git a/sim/testsuite/sim/bpf/alu.s b/sim/testsuite/sim/bpf/alu.s
new file mode 100644
index 0000000..6013ac7
--- /dev/null
+++ b/sim/testsuite/sim/bpf/alu.s
@@ -0,0 +1,109 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;;; alu.s
+;;; Tests for ALU64 BPF instructions in simulator
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ mov %r1, 0
+ mov %r2, -1
+
+ ;; add
+ add %r1, 1
+ add %r2, -1
+ add %r1, %r2
+ fail_ne %r1, -1
+
+ ;; sub
+ sub %r1, %r1
+ fail_ne %r1, 0
+ sub %r1, 10
+ sub %r2, %r1
+ fail_ne %r2, 8
+
+ ;; mul
+ mul %r2, %r2 ; r2 = 64
+ mul %r2, 3 ; r2 = 192
+ mov %r1, -3
+ mul %r1, %r2 ; r1 = -576
+ mul %r2, 0
+ fail_ne %r1, -576
+ fail_ne %r2, 0
+ mul %r1, %r1
+ mul %r1, %r1
+ fail_ne %r1, 110075314176
+
+ ;; div
+ div %r2, %r1
+ fail_ne %r2, 0
+ div %r1, -10000
+ fail_ne %r1, -11007531
+ div %r1, %r1
+ fail_ne %r1, 1
+
+ ;; and
+ lddw %r1, 0xaaaaaaaa55555555
+ and %r1, 0x55aaaaaa ; we still only have 32-bit imm.
+ fail_ne %r1, 0x0000000055000000
+ lddw %r2, 0x5555555a5aaaaaaa
+ and %r2, %r1
+ fail_ne %r2, 0x0000000050000000
+
+ ;; or
+ or %r2, 0xdeadbeef
+ fail_ne %r2, 0xffffffffdeadbeef ; 0xdeadbeef gets sign extended
+ lddw %r1, 0xdead00000000beef
+ lddw %r2, 0x0000123456780000
+ or %r1, %r2
+ fail_ne %r1, 0xdead12345678beef
+
+ ;; lsh
+ mov %r1, 0xdeadbeef
+ lsh %r1, 11
+ fail_ne %r1, 0xfffffef56df77800 ; because deadbeef gets sign ext.
+ mov %r2, 21
+ lsh %r1, %r2
+ fail_ne %r1, 0xdeadbeef00000000
+
+ ;; rsh
+ rsh %r1, 11
+ fail_ne %r1, 0x001bd5b7dde00000 ; 0xdeadbeef 00000000 >> 0xb
+ rsh %r1, %r2
+ fail_ne %r1, 0x00000000deadbeef
+
+ ;; arsh
+ arsh %r1, 8
+ fail_ne %r1, 0x0000000000deadbe
+ lsh %r1, 40 ; r1 = 0xdead be00 0000 0000
+ arsh %r1, %r2 ; r1 arsh (r2 == 21)
+ fail_ne %r1, 0xfffffef56df00000
+
+ ;; mod
+ mov %r1, 1025
+ mod %r1, -16
+ fail_ne %r1, 1
+ mov %r1, -25
+ mov %r2, 5
+ mod %r1, %r2
+ fail_ne %r1, 0
+
+ ;; xor
+ xor %r1, %r2
+ fail_ne %r1, 5
+ xor %r1, 0x7eadbeef
+ fail_ne %r1, 0x7eadbeea
+ xor %r1, %r1
+ fail_ne %r1, 0
+
+ ;; neg
+ neg %r2
+ fail_ne %r2, -5
+ mov %r1, -1025
+ neg %r1
+ fail_ne %r1, 1025
+
+ pass
diff --git a/sim/testsuite/sim/bpf/alu32.s b/sim/testsuite/sim/bpf/alu32.s
new file mode 100644
index 0000000..fcd6699
--- /dev/null
+++ b/sim/testsuite/sim/bpf/alu32.s
@@ -0,0 +1,99 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;; alu32.s
+;; Tests for ALU(32) BPF instructions in simulator
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ mov32 %r1, 10 ; r1 = 10
+ mov32 %r2, -5 ; r2 = -5
+
+ ;; add
+ add32 %r1, 1 ; r1 += 1 (r1 = 11)
+ add32 %r2, -1 ; r2 += -1 (r2 = -6)
+ add32 %r1, %r2 ; r1 += r2 (r1 = 11 + -6 = 5)
+ fail_ne32 %r1, 5
+
+ ;; sub
+ sub32 %r1, 5 ; r1 -= 5 (r1 = 0)
+ sub32 %r1, -5 ; r1 -= -5 (r1 = 5)
+ sub32 %r1, %r2 ; r1 -= r2 (r1 = 5 - -6 = 11)
+ fail_ne32 %r1, 11
+
+ ;; mul
+ mul32 %r1, 2 ; r1 *= 2 (r1 = 22)
+ mul32 %r1, -2 ; r1 *= -2 (r1 = -44)
+ mul32 %r1, %r2 ; r1 *= r2 (r1 = -44 * -6 = 264)
+ fail_ne32 %r1, 264
+
+ ;; div
+ div32 %r1, %r2 ; r1 /= r2 (r1 = 264 / -6 = -44)
+ div32 %r1, -2 ; r1 /= -2 (r1 = 22)
+ div32 %r1, 2 ; r1 /= 2 (r1 = 11)
+ fail_ne32 %r1, 11
+
+ ;; and (bitwise)
+ mov32 %r1, 0xb ; r1 = (0xb = 0b1011)
+ mov32 %r2, 0x5 ; r2 = (0x5 = 0b0101)
+ and32 %r1, 0xa ; r1 &= (0xa = 0b1010) = (0b1010 = 0xa)
+ fail_ne32 %r1, 0xa
+ and32 %r1, %r2 ; r1 &= r2 = 0x0
+ fail_ne32 %r1, 0x0
+
+ ;; or (bitwise)
+ or32 %r1, 0xb
+ or32 %r1, %r2
+ fail_ne32 %r1, 0xf
+
+ ;; lsh (left shift)
+ lsh32 %r1, 4 ; r1 <<= 4 (r1 = 0xf0)
+ mov32 %r2, 24 ; r2 = 24
+ lsh32 %r1, %r2
+ fail_ne32 %r1, 0xf0000000
+
+ ;; rsh (right logical shift)
+ rsh32 %r1, 2
+ rsh32 %r1, %r2
+ fail_ne32 %r1, 0x3c ; (0xf000 0000 >> 26)
+
+ ;; arsh (right arithmetic shift)
+ arsh32 %r1, 1
+ or32 %r1, 0x80000000
+ mov32 %r2, 3
+ arsh32 %r1, %r2
+ fail_ne %r1, 0x00000000F0000003
+ ; Note: make sure r1 is NOT sign-extended
+ ; i.e. upper-32 bits should be untouched
+
+ ;; mod
+ mov32 %r1, -25
+ mov32 %r2, 4
+ mod32 %r1, %r2
+ fail_ne32 %r1, -1
+ mov32 %r1, 25
+ mod32 %r1, 5
+ fail_ne32 %r1, 0
+
+ ;; xor
+ xor32 %r1, %r2
+ fail_ne32 %r1, 4
+ xor32 %r1, 0xF000000F
+ fail_ne %r1, 0xF000000B ; Note: check for (bad) sign-extend
+ xor32 %r1, %r1
+ fail_ne %r1, 0
+
+ ;; neg
+ mov32 %r1, -1
+ mov32 %r2, 0x7fffffff
+ neg32 %r1
+ neg32 %r2
+ fail_ne32 %r1, 1
+ fail_ne %r2, 0x80000001 ; Note: check for (bad) sign-extend
+ neg32 %r2
+ fail_ne32 %r2, 0x7fffffff
+
+ pass
diff --git a/sim/testsuite/sim/bpf/endbe.s b/sim/testsuite/sim/bpf/endbe.s
new file mode 100644
index 0000000..2f662ae
--- /dev/null
+++ b/sim/testsuite/sim/bpf/endbe.s
@@ -0,0 +1,46 @@
+# mach: bpf
+# as: --EB
+# ld: --EB
+# sim: -E big
+# output: pass\nexit 0 (0x0)\n
+;;; endbe.s
+;;; Tests for BPF endianness-conversion instructions in simulator
+;;; running in BIG ENDIAN
+;;;
+;;; Both 'be' and 'le' ISAs have both endbe and endle instructions.
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ lddw %r1, 0x12345678deadbeef
+ endle %r1, 64
+ fail_ne %r1, 0xefbeadde78563412
+ endle %r1, 64
+ fail_ne %r1, 0x12345678deadbeef
+
+ ;; `bitsize` < 64 will truncate
+ endle %r1, 32
+ fail_ne %r1, 0xefbeadde
+ endle %r1, 32
+ fail_ne %r1, 0xdeadbeef
+
+ endle %r1, 16
+ fail_ne %r1, 0xefbe
+ endle %r1, 16
+ fail_ne %r1, 0xbeef
+
+ ;; endbe on be should be noop (except truncate)
+ lddw %r1, 0x12345678deadbeef
+ endbe %r1, 64
+ fail_ne %r1, 0x12345678deadbeef
+
+ endbe %r1, 32
+ fail_ne %r1, 0xdeadbeef
+
+ endbe %r1, 16
+ fail_ne %r1, 0xbeef
+
+ pass
diff --git a/sim/testsuite/sim/bpf/endle.s b/sim/testsuite/sim/bpf/endle.s
new file mode 100644
index 0000000..d8f5ceb
--- /dev/null
+++ b/sim/testsuite/sim/bpf/endle.s
@@ -0,0 +1,43 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;;; endle.s
+;;; Tests for BPF endianness-conversion instructions in simulator
+;;; running in LITTLE ENDIAN
+;;;
+;;; Both 'be' and 'le' ISAs have both endbe and endle instructions.
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ lddw %r1, 0x12345678deadbeef
+ endbe %r1, 64
+ fail_ne %r1, 0xefbeadde78563412
+ endbe %r1, 64
+ fail_ne %r1, 0x12345678deadbeef
+
+ ;; `bitsize` < 64 will truncate
+ endbe %r1, 32
+ fail_ne %r1, 0xefbeadde
+ endbe %r1, 32
+ fail_ne %r1, 0xdeadbeef
+
+ endbe %r1, 16
+ fail_ne %r1, 0xefbe
+ endbe %r1, 16
+ fail_ne %r1, 0xbeef
+
+ ;; endle on le should be noop (except truncate)
+ lddw %r1, 0x12345678deadbeef
+ endle %r1, 64
+ fail_ne %r1, 0x12345678deadbeef
+
+ endle %r1, 32
+ fail_ne %r1, 0xdeadbeef
+
+ endle %r1, 16
+ fail_ne %r1, 0xbeef
+
+ pass
diff --git a/sim/testsuite/sim/bpf/jmp.s b/sim/testsuite/sim/bpf/jmp.s
new file mode 100644
index 0000000..5ab5de0
--- /dev/null
+++ b/sim/testsuite/sim/bpf/jmp.s
@@ -0,0 +1,120 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;;; jmp.s
+;;; Tests for eBPF JMP instructions in simulator
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ mov %r1, 5
+ mov %r2, 2
+ mov %r3, 7
+ mov %r4, -1
+
+ ;; ja - jump absolute (unconditional)
+ ja 2f
+1: fail
+
+2: ;; jeq - jump eq
+ jeq %r1, 4, 1b ; no
+ jeq %r1, %r2, 1b ; no
+ jeq %r1, 5, 2f ; yes
+ fail
+2: jeq %r1, %r1, 2f ; yes
+ fail
+
+2: ;; jgt - jump (unsigned) greater-than
+ jgt %r1, 6, 1b ; no
+ jgt %r1, -5, 1b ; no - unsigned
+ jgt %r1, %r4, 1b ; no - unsigned
+ jgt %r1, 4, 2f ; yes
+ fail
+2: jgt %r1, %r2, 2f ; yes
+ fail
+
+2: ;; jge - jump (unsigned) greater-than-or-equal-to
+ jge %r1, 6, 1b ; no
+ jge %r1, 5, 2f ; yes
+ fail
+2: jge %r1, %r3, 1b ; no
+ jge %r1, -5, 1b ; no - unsigned
+ jge %r1, %r2, 2f ; yes
+ fail
+
+2: ;; jlt - jump (unsigned) less-than
+ jlt %r1, 5, 1b ; no
+ jlt %r1, %r2, 1b ; no
+ jlt %r4, %r1, 1b ; no - unsigned
+ jlt %r1, 6, 2f ; yes
+ fail
+2:
+ jlt %r1, %r3, 2f ; yes
+ fail
+
+2: ;; jle - jump (unsigned) less-than-or-equal-to
+ jle %r1, 4, 1b ; no
+ jle %r1, %r2, 1b ; no
+ jle %r4, %r1, 1b ; no
+ jle %r1, 5, 2f ; yes
+ fail
+2: jle %r1, %r1, 2f ; yes
+ fail
+
+2: ;; jset - jump "test" (AND)
+ jset %r1, 2, 1b ; no (5 & 2 = 0)
+ jset %r1, %r2, 1b ; no (same)
+ jset %r1, 4, 2f ; yes (5 & 4 != 0)
+ fail
+
+2: ;; jne - jump not-equal-to
+ jne %r1, 5, 1b ; no
+ jne %r1, %r1, 1b ; no
+ jne %r1, 6, 2f ; yes
+ fail
+2: jne %r1, %r4, 2f ; yes
+ fail
+
+2: ;; jsgt - jump (signed) greater-than
+ jsgt %r1, %r3, 1b ; no
+ jsgt %r1, %r1, 1b ; no
+ jsgt %r1, 5, 1b ; no
+ jsgt %r1, -4, 2f ; yes
+ fail
+2: jsgt %r1, %r4, 2f ; yes
+ fail
+
+2: ;; jsge - jump (signed) greater-than-or-equal-to
+ jsge %r1, %r3, 1b ; no
+ jsge %r1, %r1, 2f ; yes
+ fail
+2: jsge %r1, 7, 1b ; no
+ jsge %r1, -4, 2f ; yes
+ fail
+2: jsge %r1, %r4, 2f ; yes
+ fail
+
+2: ;; jslt - jump (signed) less-than
+ jslt %r1, 5, 1b ; no
+ jslt %r1, %r2, 1b ; no
+ jslt %r4, %r1, 2f ; yes
+ fail
+2: jslt %r1, 6, 2f ; yes
+ fail
+2: jslt %r1, %r3, 2f ; yes
+ fail
+
+2: ;; jsle - jump (signed) less-than-or-equal-to
+ jsle %r1, 4, 1b ; no
+ jsle %r1, %r2, 1b ; no
+ jsle %r4, %r1, 2f ; yes
+ fail
+2: jsle %r1, 5, 2f ; yes
+ fail
+2: jsle %r1, %r3, 2f ; yes
+ fail
+
+2:
+ pass
diff --git a/sim/testsuite/sim/bpf/jmp32.s b/sim/testsuite/sim/bpf/jmp32.s
new file mode 100644
index 0000000..a6074cd
--- /dev/null
+++ b/sim/testsuite/sim/bpf/jmp32.s
@@ -0,0 +1,120 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;;; jmp32.s
+;;; Tests for eBPF JMP32 instructions in simulator
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ mov32 %r1, 5
+ mov32 %r2, 2
+ mov32 %r3, 7
+ mov32 %r4, -1
+
+ ;; ja - jump absolute (unconditional)
+ ja 2f
+1: fail
+
+2: ;; jeq - jump eq
+ jeq32 %r1, 4, 1b ; no
+ jeq32 %r1, %r2, 1b ; no
+ jeq32 %r1, 5, 2f ; yes
+ fail
+2: jeq32 %r1, %r1, 2f ; yes
+ fail
+
+2: ;; jgt - jump (unsigned) greater-than
+ jgt32 %r1, 6, 1b ; no
+ jgt32 %r1, -5, 1b ; no - unsigned
+ jgt32 %r1, %r4, 1b ; no - unsigned
+ jgt32 %r1, 4, 2f ; yes
+ fail
+2: jgt32 %r1, %r2, 2f ; yes
+ fail
+
+2: ;; jge - jump (unsigned) greater-than-or-equal-to
+ jge32 %r1, 6, 1b ; no
+ jge32 %r1, 5, 2f ; yes
+ fail
+2: jge32 %r1, %r3, 1b ; no
+ jge32 %r1, -5, 1b ; no - unsigned
+ jge32 %r1, %r2, 2f ; yes
+ fail
+
+2: ;; jlt - jump (unsigned) less-than
+ jlt32 %r1, 5, 1b ; no
+ jlt32 %r1, %r2, 1b ; no
+ jlt32 %r4, %r1, 1b ; no - unsigned
+ jlt32 %r1, 6, 2f ; yes
+ fail
+2:
+ jlt32 %r1, %r3, 2f ; yes
+ fail
+
+2: ;; jle - jump (unsigned) less-than-or-equal-to
+ jle32 %r1, 4, 1b ; no
+ jle32 %r1, %r2, 1b ; no
+ jle32 %r4, %r1, 1b ; no
+ jle32 %r1, 5, 2f ; yes
+ fail
+2: jle32 %r1, %r1, 2f ; yes
+ fail
+
+2: ;; jset - jump "test" (AND)
+ jset32 %r1, 2, 1b ; no (5 & 2 = 0)
+ jset32 %r1, %r2, 1b ; no (same)
+ jset32 %r1, 4, 2f ; yes (5 & 4 != 0)
+ fail
+
+2: ;; jne - jump not-equal-to
+ jne32 %r1, 5, 1b ; no
+ jne32 %r1, %r1, 1b ; no
+ jne32 %r1, 6, 2f ; yes
+ fail
+2: jne32 %r1, %r4, 2f ; yes
+ fail
+
+2: ;; jsgt - jump (signed) greater-than
+ jsgt32 %r1, %r3, 1b ; no
+ jsgt32 %r1, %r1, 1b ; no
+ jsgt32 %r1, 5, 1b ; no
+ jsgt32 %r1, -4, 2f ; yes
+ fail
+2: jsgt32 %r1, %r4, 2f ; yes
+ fail
+
+2: ;; jsge - jump (signed) greater-than-or-equal-to
+ jsge32 %r1, %r3, 1b ; no
+ jsge32 %r1, %r1, 2f ; yes
+ fail
+2: jsge32 %r1, 7, 1b ; no
+ jsge32 %r1, -4, 2f ; yes
+ fail
+2: jsge32 %r1, %r4, 2f ; yes
+ fail
+
+2: ;; jslt - jump (signed) less-than
+ jslt32 %r1, 5, 1b ; no
+ jslt32 %r1, %r2, 1b ; no
+ jslt32 %r4, %r1, 2f ; yes
+ fail
+2: jslt32 %r1, 6, 2f ; yes
+ fail
+2: jslt32 %r1, %r3, 2f ; yes
+ fail
+
+2: ;; jsle - jump (signed) less-than-or-equal-to
+ jsle32 %r1, 4, 1b ; no
+ jsle32 %r1, %r2, 1b ; no
+ jsle32 %r4, %r1, 2f ; yes
+ fail
+2: jsle32 %r1, 5, 2f ; yes
+ fail
+2: jsle32 %r1, %r3, 2f ; yes
+ fail
+
+2:
+ pass
diff --git a/sim/testsuite/sim/bpf/ldabs.s b/sim/testsuite/sim/bpf/ldabs.s
new file mode 100644
index 0000000..ae777f1
--- /dev/null
+++ b/sim/testsuite/sim/bpf/ldabs.s
@@ -0,0 +1,87 @@
+# mach: bpf
+# sim: --skb-data-offset=0x20
+# output: pass\nexit 0 (0x0)\n
+;;; ldabs.s
+;;; Tests for non-generic BPF load instructions in simulator.
+;;; These instructions (ld{abs,ind}{b,h,w,dw}) are used to access
+;;; kernel socket data from BPF programs for high performance filters.
+;;;
+;;; Register r6 is an implicit input holding a pointer to a struct sk_buff.
+;;; Register r0 is an implicit output, holding the fetched data.
+;;;
+;;; e.g.
+;;; ldabsw means:
+;;; r0 = ntohl (*(u32 *) (((struct sk_buff *)r6)->data + imm32))
+;;;
+;;; ldindw means
+;;; r0 = ntohl (*(u32 *) (((struct sk_buff *)r6)->data + src_reg + imm32))
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ ;; R6 holds a pointer to a struct sk_buff, which we pretend
+ ;; exists at 0x1000
+ mov %r6, 0x1000
+
+ ;; We configure skb-data-offset=0x20
+ ;; This specifies offsetof(struct sk_buff, data), where the field 'data'
+ ;; is a pointer a data buffer, in this case at 0x2000
+ stw [%r6+0x20], 0x2000
+
+ ;; Write the value 0x7eadbeef into memory at 0x2004
+ ;; i.e. offset 4 within the data buffer pointed to by
+ ;; ((struct sk_buff *)r6)->data
+ stw [%r6+0x1004], 0xdeadbeef
+
+ ;; Now load data[4] into r0 using the ldabsw instruction
+ ldabsw 0x4
+
+ ;; ...and compare to what we expect
+ fail_ne32 %r0, 0xdeadbeef
+
+ ;; Repeat for a half-word (2-bytes)
+ sth [%r6+0x1008], 0x1234
+ ldabsh 0x8
+ fail_ne32 %r0, 0x1234
+
+ ;; Repeat for a single byte
+ stb [%r6+0x1010], 0x5a
+ ldabsb 0x10
+ fail_ne32 %r0, 0x5a
+
+ ;; Repeat for a double-word (8-byte)
+ ;; (note: fail_ne macro uses r0, so copy to another r1 to compare)
+ lddw %r2, 0x1234deadbeef5678
+ stxdw [%r6+0x1018], %r2
+ ldabsdw 0x18
+ mov %r1, %r0
+ fail_ne %r1, 0x1234deadbeef5678
+
+ ;; Now, we do the same for the indirect loads
+ mov %r7, 0x100
+ stw [%r6+0x1100], 0xfeedbeef
+
+ ldindw %r7, 0x0
+ fail_ne32 %r0, 0xfeedbeef
+
+ ;; half-word
+ sth [%r6+0x1104], 0x6789
+ ldindh %r7, 0x4
+ fail_ne32 %r0, 0x6789
+
+ ;; byte
+ stb [%r6+0x1108], 0x5f
+ ldindb %r7, 0x8
+ fail_ne32 %r0, 0x5f
+
+ ;; double-word
+ lddw %r2, 0xcafe12345678d00d
+ stxdw [%r6+0x1110], %r2
+ ldinddw %r7, 0x10
+ mov %r1, %r0
+ fail_ne %r1, 0xcafe12345678d00d
+
+ pass
diff --git a/sim/testsuite/sim/bpf/mem.s b/sim/testsuite/sim/bpf/mem.s
new file mode 100644
index 0000000..f9c6a19
--- /dev/null
+++ b/sim/testsuite/sim/bpf/mem.s
@@ -0,0 +1,56 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;;; mem.s
+;;; Tests for BPF memory (ldx, stx, ..) instructions in simulator
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ lddw %r1, 0x1234deadbeef5678
+ mov %r2, 0x1000
+
+ ;; basic store/load check
+ stxb [%r2+0], %r1
+ stxh [%r2+2], %r1
+ stxw [%r2+4], %r1
+ stxdw [%r2+8], %r1
+
+ stb [%r2+16], 0x5a
+ sth [%r2+18], 0xcafe
+ stw [%r2+20], 0xbeefface
+ stdw [%r2+24], 0x7eadbeef
+
+ ldxb %r1, [%r2+16]
+ fail_ne %r1, 0x5a
+ ldxh %r1, [%r2+18]
+ fail_ne %r1, 0xffffffffffffcafe
+ ldxw %r1, [%r2+20]
+ fail_ne %r1, 0xffffffffbeefface
+ ldxdw %r1, [%r2+24]
+ fail_ne %r1, 0x7eadbeef
+
+ ldxb %r3, [%r2+0]
+ fail_ne %r3, 0x78
+ ldxh %r3, [%r2+2]
+ fail_ne %r3, 0x5678
+ ldxw %r3, [%r2+4]
+ fail_ne %r3, 0xffffffffbeef5678
+ ldxdw %r3, [%r2+8]
+ fail_ne %r3, 0x1234deadbeef5678
+
+ ldxw %r4, [%r2+10]
+ fail_ne %r4, 0xffffffffdeadbeef
+
+ ;; negative offsets
+ add %r2, 16
+ ldxh %r5, [%r2+-14]
+ fail_ne %r5, 0x5678
+ ldxw %r5, [%r2+-12]
+ fail_ne %r5, 0xffffffffbeef5678
+ ldxdw %r5, [%r2+-8]
+ fail_ne %r5, 0x1234deadbeef5678
+
+ pass
diff --git a/sim/testsuite/sim/bpf/mov.s b/sim/testsuite/sim/bpf/mov.s
new file mode 100644
index 0000000..6665450
--- /dev/null
+++ b/sim/testsuite/sim/bpf/mov.s
@@ -0,0 +1,54 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;; mov.s
+;; Tests for mov and mov32 instructions
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ ;; some basic sanity checks
+ mov32 %r1, 5
+ fail_ne %r1, 5
+
+ mov32 %r2, %r1
+ fail_ne %r2, 5
+
+ mov %r2, %r1
+ fail_ne %r2, 5
+
+ mov %r1, -666
+ fail_ne %r1, -666
+
+ ;; should NOT sign extend
+ mov32 %r1, -1
+ fail_ne %r1, 0x00000000ffffffff
+
+ ;; should sign extend
+ mov %r2, -1
+ fail_ne %r2, 0xffffffffffffffff
+
+ mov %r3, 0x80000000
+
+ ;; should NOT sign extend
+ mov32 %r4, %r3
+ fail_ne %r4, 0x0000000080000000
+
+ ;; should sign extend
+ mov %r5, %r3
+ fail_ne %r5, 0xffffffff80000000
+
+ mov32 %r1, -2147483648
+ mov32 %r1, %r1
+ fail_ne32 %r1, -2147483648
+
+ ;; casting shenanigans
+ mov %r1, %r1
+ fail_ne %r1, +2147483648
+ mov32 %r2, -1
+ mov %r2, %r2
+ fail_ne %r2, +4294967295
+
+ pass
diff --git a/sim/testsuite/sim/bpf/testutils.inc b/sim/testsuite/sim/bpf/testutils.inc
new file mode 100644
index 0000000..d3d6b17
--- /dev/null
+++ b/sim/testsuite/sim/bpf/testutils.inc
@@ -0,0 +1,38 @@
+
+ ;; Print "pass\n" and 'exit 0'
+ .macro pass
+ .data
+mpass:
+ .string "pass\n"
+ .text
+_pass:
+ mov %r1, mpass ; point to "pass\n" string
+ mov %r2, 5 ; strlen mpass
+ call 7 ; printk
+ mov %r0, 0 ;
+ exit ; exit 0
+ .endm
+
+;;; MACRO fail
+;;; Exit with status 1
+ .macro fail
+ mov %r0, 1
+ exit
+ .endm
+
+;;; MACRO fail_ne32
+;;; Exit with status 1 if \reg32 != \val
+ .macro fail_ne32 reg val
+ jeq32 \reg, \val, 2
+ mov %r0, 1
+ exit
+ .endm
+
+;;; MACRO fail_ne
+;;; Exit with status1 if \reg ne \val
+ .macro fail_ne reg val
+ lddw %r0, \val
+ jeq \reg, %r0, 2
+ mov %r0, 1
+ exit
+ .endm
diff --git a/sim/testsuite/sim/bpf/xadd.s b/sim/testsuite/sim/bpf/xadd.s
new file mode 100644
index 0000000..be60714
--- /dev/null
+++ b/sim/testsuite/sim/bpf/xadd.s
@@ -0,0 +1,44 @@
+# mach: bpf
+# output: pass\nexit 0 (0x0)\n
+;;; xadd.s
+;;; Tests for BPF atomic exchange-and-add instructions in simulator
+;;;
+;;; The xadd instructions (XADDW, XADDDW) operate on a memory location
+;;; specified in $dst + offset16, atomically adding the value in $src.
+;;;
+;;; In the simulator, there isn't anything else happening. The atomic
+;;; instructions are identical to a non-atomic load/add/store.
+
+ .include "testutils.inc"
+
+ .text
+ .global main
+ .type main, @function
+main:
+ mov %r1, 0x1000
+ mov %r2, 5
+
+ ;; basic xadd w
+ stw [%r1+0], 10
+ xaddw [%r1+0], %r2
+ ldxw %r3, [%r1+0]
+ fail_ne %r3, 15
+
+ ;; basic xadd dw
+ stdw [%r1+8], 42
+ xadddw [%r1+8], %r2
+ ldxdw %r3, [%r1+8]
+ fail_ne %r3, 47
+
+ ;; xadd w negative value
+ mov %r4, -1
+ xaddw [%r1+0], %r4
+ ldxw %r3, [%r1+0]
+ fail_ne %r3, 14
+
+ ;; xadd dw negative val
+ xadddw [%r1+8], %r4
+ ldxdw %r3, [%r1+8]
+ fail_ne %r3, 46
+
+ pass