[PATCH] bpf: add may_goto instruction [PR32176]
David Faust
david.faust@oracle.com
Thu Feb 5 19:35:54 GMT 2026
The BPF "may_goto" instruction is a special sort of conditional jump
where the condition is determined by the BPF runtime. That is, it is
a no-op until the runtime decides otherwise.
For normal asm syntax, the mnemonic "jcond" is chosen in keeping with
the style of following the opcode definitions in the Linux kernel uapi
BPF headers.
This instruction is not currently emitted by GCC, but it can be inserted
into BPF programs via macros defined in the Linux kernel.
Tested on x86_64-linux-gnu for bpf-unknown-none.
Sanity checked building Linux kernel bpf-next selftests.
PR gas/32176
include/
* opcode/bpf.h (BPF_CODE_JCOND): New.
(bpf_insn_id): Add BPF_INSN_JCOND.
opcodes/
* bpf-opc.c: Add entry for BPF_INSN_JCOND.
gas/testsuite/
* gas/bpf/bpf.exp: Run new dump tests.
* gas/bpf/jcond-be-pseudoc.d: New.
* gas/bpf/jcond-be.d: New.
* gas/bpf/jcond-pseudoc.d: New.
* gas/bpf/jcond-pseudoc.s: New.
* gas/bpf/jcond.d: New.
* gas/bpf/jcond.s: New.
---
gas/testsuite/gas/bpf/bpf.exp | 6 ++++++
gas/testsuite/gas/bpf/jcond-be-pseudoc.d | 14 ++++++++++++++
gas/testsuite/gas/bpf/jcond-be.d | 14 ++++++++++++++
gas/testsuite/gas/bpf/jcond-pseudoc.d | 14 ++++++++++++++
gas/testsuite/gas/bpf/jcond-pseudoc.s | 8 ++++++++
gas/testsuite/gas/bpf/jcond.d | 14 ++++++++++++++
gas/testsuite/gas/bpf/jcond.s | 8 ++++++++
include/opcode/bpf.h | 4 ++++
opcodes/bpf-opc.c | 4 ++++
9 files changed, 86 insertions(+)
create mode 100644 gas/testsuite/gas/bpf/jcond-be-pseudoc.d
create mode 100644 gas/testsuite/gas/bpf/jcond-be.d
create mode 100644 gas/testsuite/gas/bpf/jcond-pseudoc.d
create mode 100644 gas/testsuite/gas/bpf/jcond-pseudoc.s
create mode 100644 gas/testsuite/gas/bpf/jcond.d
create mode 100644 gas/testsuite/gas/bpf/jcond.s
diff --git a/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp
index 89955e1a9e4..f1932212252 100644
--- a/gas/testsuite/gas/bpf/bpf.exp
+++ b/gas/testsuite/gas/bpf/bpf.exp
@@ -47,6 +47,9 @@ if {[istarget bpf*-*-*]} {
run_dump_test jump-relax-ja
run_dump_test jump-relax-jump
+ run_dump_test jcond
+ run_dump_test jcond-pseudoc
+
# Big-endian BPF tests
run_dump_test call-be
run_dump_test exit-be
@@ -70,6 +73,9 @@ if {[istarget bpf*-*-*]} {
run_dump_test jump-relax-ja-be
run_dump_test jump-relax-jump-be
+ run_dump_test jcond-be
+ run_dump_test jcond-be-pseudoc
+
# Overflow tests
run_dump_test offset16-overflow
run_dump_test disp16-overflow
diff --git a/gas/testsuite/gas/bpf/jcond-be-pseudoc.d b/gas/testsuite/gas/bpf/jcond-be-pseudoc.d
new file mode 100644
index 00000000000..5bd24e194a7
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jcond-be-pseudoc.d
@@ -0,0 +1,14 @@
+#as: -EB -mdialect=pseudoc
+#objdump: -dr -M dec,pseudoc
+#source: jcond-pseudoc.s
+#name: BPF conditional pseudo-jump instruction, pseudoc syntax, big-endian
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: e5 00 00 00 00 00 00 00 may_goto 0
+ 8: e5 00 00 01 00 00 00 00 may_goto 1
+ 10: e5 00 ff fe 00 00 00 00 may_goto -2
+ 18: e5 00 ff fd 00 00 00 00 may_goto -3
diff --git a/gas/testsuite/gas/bpf/jcond-be.d b/gas/testsuite/gas/bpf/jcond-be.d
new file mode 100644
index 00000000000..da2cfbaf481
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jcond-be.d
@@ -0,0 +1,14 @@
+#as: -EB -mdialect=normal
+#objdump: -dr -M dec
+#source: jcond.s
+#name: BPF conditional pseudo-jump instruction, normal syntax, big-endian
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: e5 00 00 00 00 00 00 00 jcond 0
+ 8: e5 00 00 01 00 00 00 00 jcond 1
+ 10: e5 00 ff fe 00 00 00 00 jcond -2
+ 18: e5 00 ff fd 00 00 00 00 jcond -3
diff --git a/gas/testsuite/gas/bpf/jcond-pseudoc.d b/gas/testsuite/gas/bpf/jcond-pseudoc.d
new file mode 100644
index 00000000000..34c14c2bdd2
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jcond-pseudoc.d
@@ -0,0 +1,14 @@
+#as: -EL -mdialect=pseudoc
+#objdump: -dr -M dec,pseudoc
+#source: jcond-pseudoc.s
+#name: BPF conditional pseudo-jump instruction, pseudoc syntax
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: e5 00 00 00 00 00 00 00 may_goto 0
+ 8: e5 00 01 00 00 00 00 00 may_goto 1
+ 10: e5 00 fe ff 00 00 00 00 may_goto -2
+ 18: e5 00 fd ff 00 00 00 00 may_goto -3
diff --git a/gas/testsuite/gas/bpf/jcond-pseudoc.s b/gas/testsuite/gas/bpf/jcond-pseudoc.s
new file mode 100644
index 00000000000..b48ef38d97a
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jcond-pseudoc.s
@@ -0,0 +1,8 @@
+# Test for conditional pseudo-jump instruction in pseudo-c syntax
+ .text
+ may_goto 1f
+1:
+ may_goto 2f
+ may_goto 1b
+2:
+ may_goto 1b
diff --git a/gas/testsuite/gas/bpf/jcond.d b/gas/testsuite/gas/bpf/jcond.d
new file mode 100644
index 00000000000..69570e2f4d8
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jcond.d
@@ -0,0 +1,14 @@
+#as: -EL -mdialect=normal
+#objdump: -dr -M dec
+#source: jcond.s
+#name: BPF conditional pseudo-jump instruction, normal syntax, little-endian
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: e5 00 00 00 00 00 00 00 jcond 0
+ 8: e5 00 01 00 00 00 00 00 jcond 1
+ 10: e5 00 fe ff 00 00 00 00 jcond -2
+ 18: e5 00 fd ff 00 00 00 00 jcond -3
diff --git a/gas/testsuite/gas/bpf/jcond.s b/gas/testsuite/gas/bpf/jcond.s
new file mode 100644
index 00000000000..9c61644ca18
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jcond.s
@@ -0,0 +1,8 @@
+# Test for conditional pseudo-jump instruction
+ .text
+ jcond 1f
+1:
+ jcond 2f
+ jcond 1b
+2:
+ jcond 1b
diff --git a/include/opcode/bpf.h b/include/opcode/bpf.h
index d4d4f6d8557..e4ccd430f0c 100644
--- a/include/opcode/bpf.h
+++ b/include/opcode/bpf.h
@@ -106,6 +106,7 @@ typedef uint64_t bpf_insn_word;
#define BPF_CODE_JLE ((uint64_t)0xb0 << 56)
#define BPF_CODE_JSLT ((uint64_t)0xc0 << 56)
#define BPF_CODE_JSLE ((uint64_t)0xd0 << 56)
+#define BPF_CODE_JCOND ((uint64_t)0xe0 << 56)
#define BPF_MODE_IMM ((uint64_t)0x00 << 56)
#define BPF_MODE_ABS ((uint64_t)0x20 << 56)
@@ -229,6 +230,9 @@ enum bpf_insn_id
BPF_INSN_ACMP, BPF_INSN_AXCHG,
/* Atomic compare-and-swap, atomic exchange (32-bit). */
BPF_INSN_ACMP32, BPF_INSN_AXCHG32,
+ /* Conditional pseudo-jump "may_goto". A NOP until the BPF runtime
+ decides it isn't. */
+ BPF_INSN_JCOND,
/* GNU simulator specific instruction. */
BPF_INSN_BRKPT,
};
diff --git a/opcodes/bpf-opc.c b/opcodes/bpf-opc.c
index 91ee561ea10..aa5493280ea 100644
--- a/opcodes/bpf-opc.c
+++ b/opcodes/bpf-opc.c
@@ -413,6 +413,10 @@ const struct bpf_opcode bpf_opcodes[] =
{BPF_INSN_AADD32, "xaddw%W[ %dr %o16 ] , %sr", "* ( u32 * ) ( %dr %o16 ) += %sr",
BPF_V1, BPF_CODE|BPF_IMM32, BPF_CLASS_STX|BPF_SIZE_W|BPF_MODE_ATOMIC|BPF_IMM32_AADD},
+ /* The "conditional pseudo-jump" instruction, a.k.a. "may_goto". */
+ {BPF_INSN_JCOND, "jcond%W%d16", "may_goto%w%d16",
+ BPF_V4, BPF_CODE|BPF_IMM32, BPF_CLASS_JMP|BPF_CODE_JCOND|BPF_SRC_K},
+
/* the brkpt instruction is used by the BPF simulator and it doesn't
really belong to the BPF instruction set. */
{BPF_INSN_BRKPT, "brkpt", "brkpt",
--
2.51.0
More information about the Binutils
mailing list