[PATCH] bpf: add the addr_space_cast instruction

Vineet Gupta vineet.gupta@linux.dev
Tue Sep 29 18:36:03 GMT 2026


gas doesn't support bpf arenas as it is missing addr_space_cast BPF
instruction. It is essentially a `mov' with a distinguised offset and
the two address spaces supported (0: generic, 1: arena) ecoded in the
immediate.

To keep implementation simple, spell out the two combinations as literal
template text.  The entries have to precede `mov', whose mask covers only
the opcode byte and would otherwise match first; movs8 and friends are
already written this way.

The instruction is available at every ISA spec (just as clang).

gas/
	* testsuite/gas/bpf/ascast.s: New test.
	* testsuite/gas/bpf/ascast.d: New test.
	* testsuite/gas/bpf/ascast-pseudoc.s: New test.
	* testsuite/gas/bpf/ascast-pseudoc.d: New test.
	* testsuite/gas/bpf/bpf.exp: Run them.

include/
	* opcode/bpf.h (BPF_OFFSET16_ASCAST): Define.
	(BPF_IMM32_ASCAST_K, BPF_IMM32_ASCAST_U): Likewise.
	(enum bpf_insn_id): Add BPF_INSN_ASCASTK and BPF_INSN_ASCASTU.

opcodes/
	* bpf-opc.c (bpf_opcodes): Add entries for addr_space_cast.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 gas/testsuite/gas/bpf/ascast-pseudoc.d | 14 ++++++++++++++
 gas/testsuite/gas/bpf/ascast-pseudoc.s |  6 ++++++
 gas/testsuite/gas/bpf/ascast.d         | 14 ++++++++++++++
 gas/testsuite/gas/bpf/ascast.s         |  6 ++++++
 gas/testsuite/gas/bpf/bpf.exp          |  2 ++
 include/opcode/bpf.h                   | 12 ++++++++++++
 opcodes/bpf-opc.c                      |  8 ++++++++
 7 files changed, 62 insertions(+)
 create mode 100644 gas/testsuite/gas/bpf/ascast-pseudoc.d
 create mode 100644 gas/testsuite/gas/bpf/ascast-pseudoc.s
 create mode 100644 gas/testsuite/gas/bpf/ascast.d
 create mode 100644 gas/testsuite/gas/bpf/ascast.s

diff --git a/gas/testsuite/gas/bpf/ascast-pseudoc.d b/gas/testsuite/gas/bpf/ascast-pseudoc.d
new file mode 100644
index 000000000000..07cf304a4bd8
--- /dev/null
+++ b/gas/testsuite/gas/bpf/ascast-pseudoc.d
@@ -0,0 +1,14 @@
+#as: -EL -mdialect=pseudoc
+#objdump: -dr -M dec,pseudoc
+#source: ascast-pseudoc.s
+#name: BPF address space cast instructions, pseudoc syntax
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:	bf 11 01 00 01 00 00 00 	r1 = addr_space_cast\(r1, 0, 1\)
+   8:	bf 10 01 00 00 00 01 00 	r0 = addr_space_cast\(r1, 1, 0\)
+  10:	bf 29 01 00 01 00 00 00 	r9 = addr_space_cast\(r2, 0, 1\)
+  18:	bf 32 00 00 00 00 00 00 	r2=r3
diff --git a/gas/testsuite/gas/bpf/ascast-pseudoc.s b/gas/testsuite/gas/bpf/ascast-pseudoc.s
new file mode 100644
index 000000000000..0d0c35a278f8
--- /dev/null
+++ b/gas/testsuite/gas/bpf/ascast-pseudoc.s
@@ -0,0 +1,6 @@
+# Test for address space cast instructions
+    .text
+    r1 = addr_space_cast(r1, 0, 1)
+    r0 = addr_space_cast(r1, 1, 0)
+    r9 = addr_space_cast(r2, 0, 1)
+    r2 = r3
diff --git a/gas/testsuite/gas/bpf/ascast.d b/gas/testsuite/gas/bpf/ascast.d
new file mode 100644
index 000000000000..6069bbb1b00e
--- /dev/null
+++ b/gas/testsuite/gas/bpf/ascast.d
@@ -0,0 +1,14 @@
+#as: -EL -mdialect=normal
+#objdump: -dr -M dec
+#source: ascast.s
+#name: BPF address space cast instructions, normal syntax
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:	bf 11 01 00 01 00 00 00 	addr_space_cast %r1,%r1,0,1
+   8:	bf 10 01 00 00 00 01 00 	addr_space_cast %r0,%r1,1,0
+  10:	bf 29 01 00 01 00 00 00 	addr_space_cast %r9,%r2,0,1
+  18:	bf 32 00 00 00 00 00 00 	mov %r2,%r3
diff --git a/gas/testsuite/gas/bpf/ascast.s b/gas/testsuite/gas/bpf/ascast.s
new file mode 100644
index 000000000000..1411f236b64a
--- /dev/null
+++ b/gas/testsuite/gas/bpf/ascast.s
@@ -0,0 +1,6 @@
+# Test for address space cast instructions
+    .text
+    addr_space_cast %r1, %r1, 0, 1
+    addr_space_cast %r0, %r1, 1, 0
+    addr_space_cast %r9, %r2, 0, 1
+    mov %r2, %r3
diff --git a/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp
index 9884b36678c2..f58387b90705 100644
--- a/gas/testsuite/gas/bpf/bpf.exp
+++ b/gas/testsuite/gas/bpf/bpf.exp
@@ -43,6 +43,8 @@ if {[istarget bpf*-*-*]} {
     run_dump_test atomic-v1
     run_dump_test atomic
     run_dump_test atomic-pseudoc
+    run_dump_test ascast
+    run_dump_test ascast-pseudoc
     run_dump_test indcall-1
     run_dump_test indcall-1-pseudoc
 
diff --git a/include/opcode/bpf.h b/include/opcode/bpf.h
index 1128c8307c5f..0ab542d5de03 100644
--- a/include/opcode/bpf.h
+++ b/include/opcode/bpf.h
@@ -136,6 +136,15 @@ typedef uint64_t bpf_insn_word;
 #define BPF_OFFSET16_MOVS8 ((uint64_t)8 << 32)
 #define BPF_OFFSET16_MOVS16 ((uint64_t)16 << 32)
 #define BPF_OFFSET16_MOVS32 ((uint64_t)32 << 32)
+#define BPF_OFFSET16_ASCAST ((uint64_t)0x1 << 32)
+
+/* In an address space cast the immediate holds the destination address
+   space in its upper half and the source address space in its lower
+   half.  Only the generic address space 0 and the arena address space
+   1 exist, so only these two combinations are meaningful.  */
+
+#define BPF_IMM32_ASCAST_K ((uint64_t)0x00000001) /* 0 <- 1.  */
+#define BPF_IMM32_ASCAST_U ((uint64_t)0x00010000) /* 1 <- 0.  */
 
 #define BPF_IMM32_END16 ((uint64_t)0x00000010)
 #define BPF_IMM32_END32 ((uint64_t)0x00000020)
@@ -172,6 +181,9 @@ enum bpf_insn_id
   BPF_INSN_NEGR, BPF_INSN_LSHR, BPF_INSN_LSHI,
   BPF_INSN_RSHR, BPF_INSN_RSHI, BPF_INSN_ARSHR, BPF_INSN_ARSHI,
   BPF_INSN_MOVS8R, BPF_INSN_MOVS16R, BPF_INSN_MOVS32R,
+  /* Address space casts.  ASCASTK yields a pointer in the generic
+     address space, ASCASTU one in the arena address space.  */
+  BPF_INSN_ASCASTK, BPF_INSN_ASCASTU,
   BPF_INSN_MOVR, BPF_INSN_MOVI,
   /* ALU32 instructions.  */
   BPF_INSN_ADD32R, BPF_INSN_ADD32I, BPF_INSN_SUB32R, BPF_INSN_SUB32I,
diff --git a/opcodes/bpf-opc.c b/opcodes/bpf-opc.c
index 15fe5dfd1163..bbadd5e2c827 100644
--- a/opcodes/bpf-opc.c
+++ b/opcodes/bpf-opc.c
@@ -93,6 +93,14 @@ const struct bpf_opcode bpf_opcodes[] =
    BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_X|BPF_OFFSET16_MOVS16},
   {BPF_INSN_MOVS32R, "movs%W%dr , %sr , 32", "%dr%w=%w( s32 )%w%sr",
    BPF_V4, BPF_CODE|BPF_OFFSET16, BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_X|BPF_OFFSET16_MOVS32},
+  {BPF_INSN_ASCASTK, "addr_space_cast%W%dr , %sr , 0 , 1",
+   "%dr%w=%waddr_space_cast ( %sr ,%w0 ,%w1 )",
+   BPF_V1, BPF_CODE|BPF_OFFSET16|BPF_IMM32,
+   BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_X|BPF_OFFSET16_ASCAST|BPF_IMM32_ASCAST_K},
+  {BPF_INSN_ASCASTU, "addr_space_cast%W%dr , %sr , 1 , 0",
+   "%dr%w=%waddr_space_cast ( %sr ,%w1 ,%w0 )",
+   BPF_V1, BPF_CODE|BPF_OFFSET16|BPF_IMM32,
+   BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_X|BPF_OFFSET16_ASCAST|BPF_IMM32_ASCAST_U},
   {BPF_INSN_MOVR, "mov%W%dr , %sr", "%dr = %sr",
    BPF_V1, BPF_CODE, BPF_CLASS_ALU64|BPF_CODE_MOV|BPF_SRC_X},
   {BPF_INSN_MOVI, "mov%W%dr , %i32", "%dr = %i32",
-- 
2.53.0-Meta



More information about the bpf mailing list