[PATCH] bpf: add may_goto instruction [PR32176]
Jose E. Marchesi
jemarch@gnu.org
Thu Feb 5 20:01:24 GMT 2026
Hi David.
Thanks for the patch.
OK.
> 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",
More information about the Binutils
mailing list