[RFC] RISC-V: Support Zibi extension.
Checks
Commit Message
This patch supports Zibi extension(Branch with immediate) instructions.
https://github.com/riscv/zibi
bfd/ChangeLog:
* elfxx-riscv.c (riscv_multi_subset_supports): New ext.
(riscv_multi_subset_supports_ext): Ditto.
gas/ChangeLog:
* NEWS: Support Zibi extension.
* testsuite/gas/riscv/march-help.l: New ext.
* testsuite/gas/riscv/zibi.d: New test.
* testsuite/gas/riscv/zibi.s: New test.
include/ChangeLog:
* opcode/riscv-opc.h (MATCH_BEQI): New match opcode.
(MASK_BEQI): New mask opcode.
(MATCH_BNEI): New match opcode.
(MASK_BNEI): New mask opcode.
(DECLARE_INSN): New insn declare.
* opcode/riscv.h (enum riscv_insn_class): New ext.
opcodes/ChangeLog:
* riscv-opc.c: New instructions def.
---
bfd/elfxx-riscv.c | 5 +++++
gas/NEWS | 3 +++
gas/testsuite/gas/riscv/march-help.l | 1 +
gas/testsuite/gas/riscv/zibi.d | 16 ++++++++++++++++
gas/testsuite/gas/riscv/zibi.s | 7 +++++++
include/opcode/riscv-opc.h | 8 ++++++++
include/opcode/riscv.h | 1 +
opcodes/riscv-opc.c | 2 ++
8 files changed, 43 insertions(+)
create mode 100644 gas/testsuite/gas/riscv/zibi.d
create mode 100644 gas/testsuite/gas/riscv/zibi.s
Comments
On 13.03.2026 13:30, Jiawei wrote:
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zibi.d
> @@ -0,0 +1,16 @@
> +#as: -march=rv64ic_zibi
> +#source: zibi.s
> +#objdump: -drw
> +
> +.*:[ ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+ <target>:
> +[ ]+[0-9a-f]+:[ ]+00042063[ ]+beqi[ ]+s0,0x0,0 <target>[ ]+0: R_RISCV_BRANCH .*
While the immediate looks correct here, ...
> +[ ]+[0-9a-f]+:[ ]+fe442ee3[ ]+beqi[ ]+s0,0x24,0 <target>[ ]+4: R_RISCV_BRANCH .*
> +[ ]+[0-9a-f]+:[ ]+fe043ce3[ ]+bnei[ ]+s0,0x20,0 <target>[ ]+8: R_RISCV_BRANCH .*
> +[ ]+[0-9a-f]+:[ ]+fe443ae3[ ]+bnei[ ]+s0,0x24,0 <target>[ ]+c: R_RISCV_BRANCH .*
... these three don't match ...
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zibi.s
> @@ -0,0 +1,7 @@
> + .text
> +target:
> + beqi x8, 0, target
> + beqi x8, 4, target
> + bnei x8, 0, target
> + bnei x8, 4, target
... the input.
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -527,6 +527,7 @@ const struct riscv_opcode riscv_opcodes[] =
> {"beqz", 0, INSN_CLASS_I, "s,p", MATCH_BEQ, MASK_BEQ|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
> {"beq", 0, INSN_CLASS_ZCA, "Cs,Cz,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
> {"beq", 0, INSN_CLASS_I, "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, INSN_CONDBRANCH },
> +{"beqi", 0, INSN_CLASS_ZIBI, "s,>,p", MATCH_BEQI, MASK_BEQI, match_opcode, INSN_CONDBRANCH },
> {"blez", 0, INSN_CLASS_I, "t,p", MATCH_BGE, MASK_BGE|MASK_RS1, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
> {"bgez", 0, INSN_CLASS_I, "s,p", MATCH_BGE, MASK_BGE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
> {"bge", 0, INSN_CLASS_I, "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_CONDBRANCH },
The new MATCH_BEQI imo wants to align with the adjacent MATCH_*.
> @@ -543,6 +544,7 @@ const struct riscv_opcode riscv_opcodes[] =
> {"bnez", 0, INSN_CLASS_I, "s,p", MATCH_BNE, MASK_BNE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
> {"bne", 0, INSN_CLASS_ZCA, "Cs,Cz,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
> {"bne", 0, INSN_CLASS_I, "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, INSN_CONDBRANCH },
> +{"bnei", 0, INSN_CLASS_ZIBI, "s,>,p", MATCH_BNEI, MASK_BNEI, match_opcode, INSN_CONDBRANCH },
> {"addi", 0, INSN_CLASS_ZCA, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
> {"addi", 0, INSN_CLASS_ZCA, "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
> {"addi", 0, INSN_CLASS_ZCA, "d,CU,z", MATCH_C_NOP, MASK_C_ADDI|MASK_RVC_IMM, match_c_nop, INSN_ALIAS },
Here it wants to align with at least one of the two.
And then, just like one can write ADD instead of ADDI, shouldn't this similarly
be possible for these two new insns (possibly requiring a spec amendment)?
Jan
On 13.03.2026 13:40, Jan Beulich wrote:
> On 13.03.2026 13:30, Jiawei wrote:
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/zibi.d
>> @@ -0,0 +1,16 @@
>> +#as: -march=rv64ic_zibi
>> +#source: zibi.s
>> +#objdump: -drw
>> +
>> +.*:[ ]+file format .*
>> +
>> +
>> +Disassembly of section .text:
>> +
>> +0+ <target>:
>> +[ ]+[0-9a-f]+:[ ]+00042063[ ]+beqi[ ]+s0,0x0,0 <target>[ ]+0: R_RISCV_BRANCH .*
>
> While the immediate looks correct here, ...
Now having looked at the spec - this one isn't correct either. It ought
to be -1.
>> +[ ]+[0-9a-f]+:[ ]+fe442ee3[ ]+beqi[ ]+s0,0x24,0 <target>[ ]+4: R_RISCV_BRANCH .*
>> +[ ]+[0-9a-f]+:[ ]+fe043ce3[ ]+bnei[ ]+s0,0x20,0 <target>[ ]+8: R_RISCV_BRANCH .*
>> +[ ]+[0-9a-f]+:[ ]+fe443ae3[ ]+bnei[ ]+s0,0x24,0 <target>[ ]+c: R_RISCV_BRANCH .*
>
> ... these three don't match ...
>
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/zibi.s
>> @@ -0,0 +1,7 @@
>> + .text
>> +target:
>> + beqi x8, 0, target
>> + beqi x8, 4, target
>> + bnei x8, 0, target
>> + bnei x8, 4, target
>
> ... the input.
And here 0 shouldn't be accepted (or converted to the register forms
of the insns).
Jan
On 3/13/2026 6:30 AM, Jiawei wrote:
> This patch supports Zibi extension(Branch with immediate) instructions.
>
> https://github.com/riscv/zibi
>
> bfd/ChangeLog:
>
> * elfxx-riscv.c (riscv_multi_subset_supports): New ext.
> (riscv_multi_subset_supports_ext): Ditto.
>
> gas/ChangeLog:
>
> * NEWS: Support Zibi extension.
> * testsuite/gas/riscv/march-help.l: New ext.
> * testsuite/gas/riscv/zibi.d: New test.
> * testsuite/gas/riscv/zibi.s: New test.
>
> include/ChangeLog:
>
> * opcode/riscv-opc.h (MATCH_BEQI): New match opcode.
> (MASK_BEQI): New mask opcode.
> (MATCH_BNEI): New match opcode.
> (MASK_BNEI): New mask opcode.
> (DECLARE_INSN): New insn declare.
> * opcode/riscv.h (enum riscv_insn_class): New ext.
>
> opcodes/ChangeLog:
>
> * riscv-opc.c: New instructions def.
THanks Jaiwei. What's the current state of this extension? Policy
to-date has been to not include things into the GNU tools until spec
hits the frozen state. It looks like this one is still at 0.1, which I
don't think is frozen.
Definitely looking forward to more expressive conditional branches
though :-) We generate some truly silly code because the ISA is so
limited in its conditional branch capabilities.
jeff
Hi Jan,
Thanks for your review, will update in next version.
Best regards,
Jiawei
在 2026/3/13 20:40, Jan Beulich 写道:
> On 13.03.2026 13:30, Jiawei wrote:
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/zibi.d
>> @@ -0,0 +1,16 @@
>> +#as: -march=rv64ic_zibi
>> +#source: zibi.s
>> +#objdump: -drw
>> +
>> +.*:[ ]+file format .*
>> +
>> +
>> +Disassembly of section .text:
>> +
>> +0+ <target>:
>> +[ ]+[0-9a-f]+:[ ]+00042063[ ]+beqi[ ]+s0,0x0,0 <target>[ ]+0: R_RISCV_BRANCH .*
> While the immediate looks correct here, ...
>
>> +[ ]+[0-9a-f]+:[ ]+fe442ee3[ ]+beqi[ ]+s0,0x24,0 <target>[ ]+4: R_RISCV_BRANCH .*
>> +[ ]+[0-9a-f]+:[ ]+fe043ce3[ ]+bnei[ ]+s0,0x20,0 <target>[ ]+8: R_RISCV_BRANCH .*
>> +[ ]+[0-9a-f]+:[ ]+fe443ae3[ ]+bnei[ ]+s0,0x24,0 <target>[ ]+c: R_RISCV_BRANCH .*
> ... these three don't match ...
>
>> --- /dev/null
>> +++ b/gas/testsuite/gas/riscv/zibi.s
>> @@ -0,0 +1,7 @@
>> + .text
>> +target:
>> + beqi x8, 0, target
>> + beqi x8, 4, target
>> + bnei x8, 0, target
>> + bnei x8, 4, target
> ... the input.
>
>> --- a/opcodes/riscv-opc.c
>> +++ b/opcodes/riscv-opc.c
>> @@ -527,6 +527,7 @@ const struct riscv_opcode riscv_opcodes[] =
>> {"beqz", 0, INSN_CLASS_I, "s,p", MATCH_BEQ, MASK_BEQ|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
>> {"beq", 0, INSN_CLASS_ZCA, "Cs,Cz,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
>> {"beq", 0, INSN_CLASS_I, "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, INSN_CONDBRANCH },
>> +{"beqi", 0, INSN_CLASS_ZIBI, "s,>,p", MATCH_BEQI, MASK_BEQI, match_opcode, INSN_CONDBRANCH },
>> {"blez", 0, INSN_CLASS_I, "t,p", MATCH_BGE, MASK_BGE|MASK_RS1, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
>> {"bgez", 0, INSN_CLASS_I, "s,p", MATCH_BGE, MASK_BGE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
>> {"bge", 0, INSN_CLASS_I, "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_CONDBRANCH },
> The new MATCH_BEQI imo wants to align with the adjacent MATCH_*.
>
>> @@ -543,6 +544,7 @@ const struct riscv_opcode riscv_opcodes[] =
>> {"bnez", 0, INSN_CLASS_I, "s,p", MATCH_BNE, MASK_BNE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
>> {"bne", 0, INSN_CLASS_ZCA, "Cs,Cz,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
>> {"bne", 0, INSN_CLASS_I, "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, INSN_CONDBRANCH },
>> +{"bnei", 0, INSN_CLASS_ZIBI, "s,>,p", MATCH_BNEI, MASK_BNEI, match_opcode, INSN_CONDBRANCH },
>> {"addi", 0, INSN_CLASS_ZCA, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
>> {"addi", 0, INSN_CLASS_ZCA, "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
>> {"addi", 0, INSN_CLASS_ZCA, "d,CU,z", MATCH_C_NOP, MASK_C_ADDI|MASK_RVC_IMM, match_c_nop, INSN_ALIAS },
> Here it wants to align with at least one of the two.
>
> And then, just like one can write ADD instead of ADDI, shouldn't this similarly
> be possible for these two new insns (possibly requiring a spec amendment)?
>
> Jan
On 3/15/2026 8:13 PM, Jiawei wrote:
> Hi Jeff,
>
>
> So far as I know, Zibi is in public review period, currently latest
> version is 0.6,
>
> and it is plan to ratify within this year.
Sounds good. Thanks,
jeff
@@ -1451,6 +1451,7 @@ static const struct riscv_supported_ext riscv_supported_std_ext[] =
static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
{
+ {"zibi", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zic64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ziccamoa", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ziccif", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@@ -2804,6 +2805,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
{
case INSN_CLASS_I:
return riscv_subset_supports (rps, "i");
+ case INSN_CLASS_ZIBI:
+ return riscv_subset_supports (rps, "zibi");
case INSN_CLASS_ZICBOM:
return riscv_subset_supports (rps, "zicbom");
case INSN_CLASS_ZICBOP:
@@ -3080,6 +3083,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
{
case INSN_CLASS_I:
return "i";
+ case INSN_CLASS_ZIBI:
+ return "zibi";
case INSN_CLASS_ZICBOM:
return "zicbom";
case INSN_CLASS_ZICBOP:
@@ -1,5 +1,8 @@
-*- text -*-
+* Add support for RISC-V standard extensions:
+ zibi v1.0.
+
Changes in 2.46:
* Add support for AMD Zen6 processor.
@@ -10,6 +10,7 @@ All available -march extensions for RISC-V:
b 1.0
v 1.0
h 1.0
+ zibi 1.0
zic64b 1.0
ziccamoa 1.0
ziccif 1.0
new file mode 100644
@@ -0,0 +1,16 @@
+#as: -march=rv64ic_zibi
+#source: zibi.s
+#objdump: -drw
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+ <target>:
+[ ]+[0-9a-f]+:[ ]+00042063[ ]+beqi[ ]+s0,0x0,0 <target>[ ]+0: R_RISCV_BRANCH .*
+[ ]+[0-9a-f]+:[ ]+fe442ee3[ ]+beqi[ ]+s0,0x24,0 <target>[ ]+4: R_RISCV_BRANCH .*
+[ ]+[0-9a-f]+:[ ]+fe043ce3[ ]+bnei[ ]+s0,0x20,0 <target>[ ]+8: R_RISCV_BRANCH .*
+[ ]+[0-9a-f]+:[ ]+fe443ae3[ ]+bnei[ ]+s0,0x24,0 <target>[ ]+c: R_RISCV_BRANCH .*
+[ ]+[0-9a-f]+:[ ]+8082[ ]+ret
+#...
new file mode 100644
@@ -0,0 +1,7 @@
+ .text
+target:
+ beqi x8, 0, target
+ beqi x8, 4, target
+ bnei x8, 0, target
+ bnei x8, 4, target
+ ret
@@ -2400,6 +2400,11 @@
#define MASK_C_SSPUSH 0xffff
#define MATCH_C_SSPOPCHK 0x6281
#define MASK_C_SSPOPCHK 0xffff
+/* Zibi instructions. */
+#define MATCH_BEQI 0x2063
+#define MASK_BEQI 0x707f
+#define MATCH_BNEI 0x3063
+#define MASK_BNEI 0x707f
/* Zicfilp instructions. */
#define MATCH_LPAD 0x17
#define MASK_LPAD 0xfff
@@ -4717,6 +4722,9 @@ DECLARE_INSN(hsv_b, MATCH_HSV_B, MASK_HSV_B)
DECLARE_INSN(hsv_h, MATCH_HSV_H, MASK_HSV_H)
DECLARE_INSN(hsv_w, MATCH_HSV_W, MASK_HSV_W)
DECLARE_INSN(hsv_d, MATCH_HSV_D, MASK_HSV_D)
+/* Zibi instructions. */
+DECLARE_INSN(beqi, MATCH_BEQI, MASK_BEQI)
+DECLARE_INSN(bnei, MATCH_BNEI, MASK_BNEI)
/* Zicbop instructions. */
DECLARE_INSN(prefetch_r, MATCH_PREFETCH_R, MASK_PREFETCH_R)
DECLARE_INSN(prefetch_w, MATCH_PREFETCH_W, MASK_PREFETCH_W)
@@ -500,6 +500,7 @@ enum riscv_insn_class
INSN_CLASS_Q,
INSN_CLASS_ZCF,
INSN_CLASS_ZCD,
+ INSN_CLASS_ZIBI,
INSN_CLASS_ZICOND,
INSN_CLASS_ZICSR,
INSN_CLASS_ZIFENCEI,
@@ -527,6 +527,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"beqz", 0, INSN_CLASS_I, "s,p", MATCH_BEQ, MASK_BEQ|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"beq", 0, INSN_CLASS_ZCA, "Cs,Cz,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"beq", 0, INSN_CLASS_I, "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, INSN_CONDBRANCH },
+{"beqi", 0, INSN_CLASS_ZIBI, "s,>,p", MATCH_BEQI, MASK_BEQI, match_opcode, INSN_CONDBRANCH },
{"blez", 0, INSN_CLASS_I, "t,p", MATCH_BGE, MASK_BGE|MASK_RS1, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"bgez", 0, INSN_CLASS_I, "s,p", MATCH_BGE, MASK_BGE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"bge", 0, INSN_CLASS_I, "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_CONDBRANCH },
@@ -543,6 +544,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"bnez", 0, INSN_CLASS_I, "s,p", MATCH_BNE, MASK_BNE|MASK_RS2, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"bne", 0, INSN_CLASS_ZCA, "Cs,Cz,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
{"bne", 0, INSN_CLASS_I, "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, INSN_CONDBRANCH },
+{"bnei", 0, INSN_CLASS_ZIBI, "s,>,p", MATCH_BNEI, MASK_BNEI, match_opcode, INSN_CONDBRANCH },
{"addi", 0, INSN_CLASS_ZCA, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS },
{"addi", 0, INSN_CLASS_ZCA, "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
{"addi", 0, INSN_CLASS_ZCA, "d,CU,z", MATCH_C_NOP, MASK_C_ADDI|MASK_RVC_IMM, match_c_nop, INSN_ALIAS },