[PATCH] RISC-V: Add optional register argument to tail pseudo

Kito Cheng kito.cheng@sifive.com
Mon Sep 14 09:53:59 GMT 2026


The lpad instruction of Zicfilp is encoded using an auipc hint encoding, so
an instrumented binary still runs correctly on a CPU without Zicfilp.  For
that to work, compilers must be able to emit a software guarded tail call
using t2 as the scratch register without Zicfilp appearing in the ISA
string.

Add `tail <symbol>, <rt>' for that, which expands the same way as
`jump <symbol>, <rt>'.

See more: https://github.com/riscv-non-isa/riscv-asm-manual/pull/227
---
 gas/testsuite/gas/riscv/tail-fail.d | 3 +++
 gas/testsuite/gas/riscv/tail-fail.l | 3 +++
 gas/testsuite/gas/riscv/tail-fail.s | 3 +++
 gas/testsuite/gas/riscv/tail.d      | 6 ++++++
 gas/testsuite/gas/riscv/tail.s      | 3 +++
 opcodes/riscv-opc.c                 | 1 +
 6 files changed, 19 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/tail-fail.d
 create mode 100644 gas/testsuite/gas/riscv/tail-fail.l
 create mode 100644 gas/testsuite/gas/riscv/tail-fail.s

diff --git a/gas/testsuite/gas/riscv/tail-fail.d b/gas/testsuite/gas/riscv/tail-fail.d
new file mode 100644
index 00000000000..8568b7b5522
--- /dev/null
+++ b/gas/testsuite/gas/riscv/tail-fail.d
@@ -0,0 +1,3 @@
+#as: -march=rv32i
+#source: tail-fail.s
+#error_output: tail-fail.l
diff --git a/gas/testsuite/gas/riscv/tail-fail.l b/gas/testsuite/gas/riscv/tail-fail.l
new file mode 100644
index 00000000000..4b9b3d136ac
--- /dev/null
+++ b/gas/testsuite/gas/riscv/tail-fail.l
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:2: Error: illegal operands `tail foo,x0'
+.*:3: Error: illegal operands `tail foo,zero'
diff --git a/gas/testsuite/gas/riscv/tail-fail.s b/gas/testsuite/gas/riscv/tail-fail.s
new file mode 100644
index 00000000000..713591ab197
--- /dev/null
+++ b/gas/testsuite/gas/riscv/tail-fail.s
@@ -0,0 +1,3 @@
+foo:
+	tail foo, x0
+	tail foo, zero
diff --git a/gas/testsuite/gas/riscv/tail.d b/gas/testsuite/gas/riscv/tail.d
index 6e5db231061..1879c06fec8 100644
--- a/gas/testsuite/gas/riscv/tail.d
+++ b/gas/testsuite/gas/riscv/tail.d
@@ -11,3 +11,9 @@ Disassembly of section .text:
 [ 	]+[0-9a-f]+:[ 	]+00030067[ 	]+jr[ 	]+t1 # 0 <foo>
 [ 	]+[0-9a-f]+:[ 	]+00000397[ 	]+auipc[ 	]+t2,0x0
 [ 	]+[0-9a-f]+:[ 	]+00038067[ 	]+jr[ 	]+t2 # 8 <foo\+0x8>
+[ 	]+[0-9a-f]+:[ 	]+00000517[ 	]+auipc[ 	]+a0,0x0
+[ 	]+[0-9a-f]+:[ 	]+00050067[ 	]+jr[ 	]+a0 # 10 <foo\+0x10>
+[ 	]+[0-9a-f]+:[ 	]+00000397[ 	]+auipc[ 	]+t2,0x0
+[ 	]+[0-9a-f]+:[ 	]+00038067[ 	]+jr[ 	]+t2 # 18 <foo\+0x18>
+[ 	]+[0-9a-f]+:[ 	]+00000317[ 	]+auipc[ 	]+t1,0x0
+[ 	]+[0-9a-f]+:[ 	]+00030067[ 	]+jr[ 	]+t1 # 20 <foo\+0x20>
diff --git a/gas/testsuite/gas/riscv/tail.s b/gas/testsuite/gas/riscv/tail.s
index 8058244367b..7d738ebec4f 100644
--- a/gas/testsuite/gas/riscv/tail.s
+++ b/gas/testsuite/gas/riscv/tail.s
@@ -2,8 +2,11 @@ foo:
 .option push
 .option arch, rv32i
 	tail foo
+	tail foo, t2
+	tail foo, a0
 .option pop
 .option push
 .option arch, rv32i_zicfilp
 	tail foo
+	tail foo, t1
 .option pop
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 7ef6e157d4f..1f7d43050bf 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -510,6 +510,7 @@ const struct riscv_opcode riscv_opcodes[] =
 {"call",        0, INSN_CLASS_I, "c",         (X_RA << OP_SH_RS1)|(X_RA << OP_SH_RD), (int) M_CALL, NULL, INSN_MACRO },
 {"tail",        0, INSN_CLASS_ZICFILP, "c",   (X_T2 << OP_SH_RS1), (int) M_CALL, NULL, INSN_MACRO },
 {"tail",        0, INSN_CLASS_I, "c",         (X_T1 << OP_SH_RS1), (int) M_CALL, NULL, INSN_MACRO },
+{"tail",        0, INSN_CLASS_I, "c,s",       0, (int) M_CALL, match_rs1_nonzero, INSN_MACRO },
 {"jump",        0, INSN_CLASS_I, "c,s",       0, (int) M_CALL, match_rs1_nonzero, INSN_MACRO },
 {"nop",         0, INSN_CLASS_ZCA, "",          MATCH_C_ADDI, 0xffff, match_opcode, INSN_ALIAS },
 {"nop",         0, INSN_CLASS_I, "",          MATCH_ADDI, MASK_ADDI|MASK_RD|MASK_RS1|MASK_IMM, match_opcode, INSN_ALIAS },
-- 
2.54.0



More information about the Binutils mailing list