Skip to content

Commit c6ab6d2

Browse files
committed
RISC-V: Add support for 'Zacas' atomic CAS
This commit adds support for the 'Zacas' extension, adding atomic CAS instructions. Beware that this extension also introduces the concept of register pairs and it checks the validity of rs1 and rs2 if applicable. This is based on the latest (frozen) draft: <https://github.com/riscv/riscv-zacas/releases/tag/v1.0-rc5> bfd/ChangeLog: * elfxx-riscv.c (riscv_implicit_subsets): Make 'Zacas' to imply 'A' extension. (riscv_supported_std_z_ext): Add 'Zacas' to the supported list. (riscv_multi_subset_supports, riscv_multi_subset_supports_ext): Add handling for new instruction class. gas/ChangeLog: * testsuite/gas/riscv/zacas-32.s: New test. * testsuite/gas/riscv/zacas-32.d: Likewise. * testsuite/gas/riscv/zacas-64.s: Likewise. * testsuite/gas/riscv/zacas-64.d: Likewise. * testsuite/gas/riscv/zacas-32-fail.s: New failure test. * testsuite/gas/riscv/zacas-32-fail.d: Likewise. * testsuite/gas/riscv/zacas-32-fail.l: Likewise. * testsuite/gas/riscv/zacas-64-fail.s: New failure test. * testsuite/gas/riscv/zacas-64-fail.d: Likewise. * testsuite/gas/riscv/zacas-64-fail.l: Likewise. include/ChangeLog: * opcode/riscv-opc.h (MATCH_AMOCAS_D, MASK_AMOCAS_D, MATCH_AMOCAS_Q, MASK_AMOCAS_Q, MATCH_AMOCAS_W, MASK_AMOCAS_W): New. * opcode/riscv.h (enum riscv_insn_class): Add new instruction class INSN_CLASS_ZACAS. opcodes/ChangeLog: * riscv-opc.c (REGGROUP_REGS_x, REGGROUP_REGS_1, REGGROUP_REGS_2, DEFINE_MATCH_FUNC_R_3): New match function template with register groups. (match_reggroup_r_1_1_1, match_reggroup_r_1_2_2): New. (riscv_opcodes): Add atomic CAS instructions.
1 parent 6f85247 commit c6ab6d2

14 files changed

+152
-0
lines changed

bfd/elfxx-riscv.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
11481148
{"zhinx", "zhinxmin", check_implicit_always},
11491149
{"zhinxmin", "zfinx", check_implicit_always},
11501150
{"zfinx", "zicsr", check_implicit_always},
1151+
{"zacas", "a", check_implicit_always},
11511152
{"zk", "zkn", check_implicit_always},
11521153
{"zk", "zkr", check_implicit_always},
11531154
{"zk", "zkt", check_implicit_always},
@@ -1259,6 +1260,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
12591260
{"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12601261
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
12611262
{"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
1263+
{"zacas", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12621264
{"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
12631265
{"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
12641266
{"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@@ -2409,6 +2411,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
24092411
return riscv_subset_supports (rps, "zmmul");
24102412
case INSN_CLASS_A:
24112413
return riscv_subset_supports (rps, "a");
2414+
case INSN_CLASS_ZACAS:
2415+
return riscv_subset_supports (rps, "zacas");
24122416
case INSN_CLASS_ZAWRS:
24132417
return riscv_subset_supports (rps, "zawrs");
24142418
case INSN_CLASS_F:
@@ -2619,6 +2623,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
26192623
return _ ("m' or `zmmul");
26202624
case INSN_CLASS_A:
26212625
return "a";
2626+
case INSN_CLASS_ZACAS:
2627+
return "zacas";
26222628
case INSN_CLASS_ZAWRS:
26232629
return "zawrs";
26242630
case INSN_CLASS_F:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#as: -march=rv32i_zacas
2+
#error_output: zacas-32-fail.l
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.*: Assembler messages:
2+
.*: Error: illegal operands `amocas\.d a1,a4,\(a3\)'
3+
.*: Error: illegal operands `amocas\.d a1,a5,\(a2\)'
4+
.*: Error: illegal operands `amocas\.d\.aq a1,a4,\(a3\)'
5+
.*: Error: illegal operands `amocas\.d\.aq a1,a5,\(a2\)'
6+
.*: Error: illegal operands `amocas\.d\.rl a1,a4,\(a3\)'
7+
.*: Error: illegal operands `amocas\.d\.rl a1,a5,\(a2\)'
8+
.*: Error: illegal operands `amocas\.d\.aqrl a1,a4,\(a3\)'
9+
.*: Error: illegal operands `amocas\.d\.aqrl a1,a5,\(a2\)'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
target:
2+
# amocas.d (RV32): rs1 (operand 3) and rs2 (operand 2) must be even.
3+
amocas.d a1, a4, (a3)
4+
amocas.d a1, a5, (a2)
5+
amocas.d.aq a1, a4, (a3)
6+
amocas.d.aq a1, a5, (a2)
7+
amocas.d.rl a1, a4, (a3)
8+
amocas.d.rl a1, a5, (a2)
9+
amocas.d.aqrl a1, a4, (a3)
10+
amocas.d.aqrl a1, a5, (a2)

gas/testsuite/gas/riscv/zacas-32.d

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#as: -march=rv32i_zacas
2+
#objdump: -d
3+
4+
.*:[ ]+file format .*
5+
6+
7+
Disassembly of section .text:
8+
9+
0+000 <target>:
10+
[ ]+[0-9a-f]+:[ ]+28f6a5af[ ]+amocas\.w[ ]+a1,a5,\(a3\)
11+
[ ]+[0-9a-f]+:[ ]+2cf6a5af[ ]+amocas\.w\.aq[ ]+a1,a5,\(a3\)
12+
[ ]+[0-9a-f]+:[ ]+2af6a5af[ ]+amocas\.w\.rl[ ]+a1,a5,\(a3\)
13+
[ ]+[0-9a-f]+:[ ]+2ef6a5af[ ]+amocas\.w\.aqrl[ ]+a1,a5,\(a3\)
14+
[ ]+[0-9a-f]+:[ ]+28e635af[ ]+amocas\.d[ ]+a1,a4,\(a2\)
15+
[ ]+[0-9a-f]+:[ ]+2ce635af[ ]+amocas\.d\.aq[ ]+a1,a4,\(a2\)
16+
[ ]+[0-9a-f]+:[ ]+2ae635af[ ]+amocas\.d\.rl[ ]+a1,a4,\(a2\)
17+
[ ]+[0-9a-f]+:[ ]+2ee635af[ ]+amocas\.d\.aqrl[ ]+a1,a4,\(a2\)

gas/testsuite/gas/riscv/zacas-32.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
target:
2+
amocas.w a1, a5, (a3)
3+
amocas.w.aq a1, a5, (a3)
4+
amocas.w.rl a1, a5, (a3)
5+
amocas.w.aqrl a1, a5, (a3)
6+
amocas.d a1, a4, (a2)
7+
amocas.d.aq a1, a4, (a2)
8+
amocas.d.rl a1, a4, (a2)
9+
amocas.d.aqrl a1, a4, (a2)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#as: -march=rv64i_zacas
2+
#error_output: zacas-64-fail.l
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.*: Assembler messages:
2+
.*: Error: illegal operands `amocas\.q a1,a4,\(a3\)'
3+
.*: Error: illegal operands `amocas\.q a1,a5,\(a2\)'
4+
.*: Error: illegal operands `amocas\.q\.aq a1,a4,\(a3\)'
5+
.*: Error: illegal operands `amocas\.q\.aq a1,a5,\(a2\)'
6+
.*: Error: illegal operands `amocas\.q\.rl a1,a4,\(a3\)'
7+
.*: Error: illegal operands `amocas\.q\.rl a1,a5,\(a2\)'
8+
.*: Error: illegal operands `amocas\.q\.aqrl a1,a4,\(a3\)'
9+
.*: Error: illegal operands `amocas\.q\.aqrl a1,a5,\(a2\)'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
target:
2+
# amocas.q (RV64): rs1 (operand 3) and rs2 (operand 2) must be even.
3+
amocas.q a1, a4, (a3)
4+
amocas.q a1, a5, (a2)
5+
amocas.q.aq a1, a4, (a3)
6+
amocas.q.aq a1, a5, (a2)
7+
amocas.q.rl a1, a4, (a3)
8+
amocas.q.rl a1, a5, (a2)
9+
amocas.q.aqrl a1, a4, (a3)
10+
amocas.q.aqrl a1, a5, (a2)

gas/testsuite/gas/riscv/zacas-64.d

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#as: -march=rv64i_zacas
2+
#objdump: -d
3+
4+
.*:[ ]+file format .*
5+
6+
7+
Disassembly of section .text:
8+
9+
0+000 <target>:
10+
[ ]+[0-9a-f]+:[ ]+28f6b5af[ ]+amocas\.d[ ]+a1,a5,\(a3\)
11+
[ ]+[0-9a-f]+:[ ]+2cf6b5af[ ]+amocas\.d\.aq[ ]+a1,a5,\(a3\)
12+
[ ]+[0-9a-f]+:[ ]+2af6b5af[ ]+amocas\.d\.rl[ ]+a1,a5,\(a3\)
13+
[ ]+[0-9a-f]+:[ ]+2ef6b5af[ ]+amocas\.d\.aqrl[ ]+a1,a5,\(a3\)
14+
[ ]+[0-9a-f]+:[ ]+28e645af[ ]+amocas\.q[ ]+a1,a4,\(a2\)
15+
[ ]+[0-9a-f]+:[ ]+2ce645af[ ]+amocas\.q\.aq[ ]+a1,a4,\(a2\)
16+
[ ]+[0-9a-f]+:[ ]+2ae645af[ ]+amocas\.q\.rl[ ]+a1,a4,\(a2\)
17+
[ ]+[0-9a-f]+:[ ]+2ee645af[ ]+amocas\.q\.aqrl[ ]+a1,a4,\(a2\)

gas/testsuite/gas/riscv/zacas-64.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
target:
2+
amocas.d a1, a5, (a3)
3+
amocas.d.aq a1, a5, (a3)
4+
amocas.d.rl a1, a5, (a3)
5+
amocas.d.aqrl a1, a5, (a3)
6+
amocas.q a1, a4, (a2)
7+
amocas.q.aq a1, a4, (a2)
8+
amocas.q.rl a1, a4, (a2)
9+
amocas.q.aqrl a1, a4, (a2)

include/opcode/riscv-opc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,6 +2315,13 @@
23152315
#define MASK_C_NTL_S1 0xffff
23162316
#define MATCH_C_NTL_ALL 0x9016
23172317
#define MASK_C_NTL_ALL 0xffff
2318+
/* Zacas instructions. */
2319+
#define MATCH_AMOCAS_D 0x2800302f
2320+
#define MASK_AMOCAS_D 0xf800707f
2321+
#define MATCH_AMOCAS_Q 0x2800402f
2322+
#define MASK_AMOCAS_Q 0xf800707f
2323+
#define MATCH_AMOCAS_W 0x2800202f
2324+
#define MASK_AMOCAS_W 0xf800707f
23182325
/* Zawrs instructions. */
23192326
#define MATCH_WRS_NTO 0x00d00073
23202327
#define MASK_WRS_NTO 0xffffffff
@@ -3370,6 +3377,10 @@ DECLARE_INSN(c_ntl_p1, MATCH_C_NTL_P1, MASK_C_NTL_P1)
33703377
DECLARE_INSN(c_ntl_pall, MATCH_C_NTL_PALL, MASK_C_NTL_PALL)
33713378
DECLARE_INSN(c_ntl_s1, MATCH_C_NTL_S1, MASK_C_NTL_S1)
33723379
DECLARE_INSN(c_ntl_all, MATCH_C_NTL_ALL, MASK_C_NTL_ALL)
3380+
/* Zacas instructions. */
3381+
DECLARE_INSN(amocas_d, MATCH_AMOCAS_D, MASK_AMOCAS_D)
3382+
DECLARE_INSN(amocas_q, MATCH_AMOCAS_Q, MASK_AMOCAS_Q)
3383+
DECLARE_INSN(amocas_w, MATCH_AMOCAS_W, MASK_AMOCAS_W)
33733384
/* Zawrs instructions. */
33743385
DECLARE_INSN(wrs_nto, MATCH_WRS_NTO, MASK_WRS_NTO)
33753386
DECLARE_INSN(wrs_sto, MATCH_WRS_STO, MASK_WRS_STO)

include/opcode/riscv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ enum riscv_insn_class
396396
INSN_CLASS_ZIHINTNTL_AND_C,
397397
INSN_CLASS_ZIHINTPAUSE,
398398
INSN_CLASS_ZMMUL,
399+
INSN_CLASS_ZACAS,
399400
INSN_CLASS_ZAWRS,
400401
INSN_CLASS_F_INX,
401402
INSN_CLASS_D_INX,

opcodes/riscv-opc.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,28 @@ match_vd_eq_vs1_eq_vs2 (const struct riscv_opcode *op,
290290
return match_opcode (op, insn) && vd == vs1 && vs1 == vs2;
291291
}
292292

293+
/* Instructions with register groups. */
294+
295+
#define REGGROUP_REGS_x 1
296+
#define REGGROUP_REGS_1 1
297+
#define REGGROUP_REGS_2 2
298+
299+
#define DEFINE_MATCH_FUNC_R_3(G_RD,G_RS1,G_RS2) \
300+
static int \
301+
match_reggroup_r_##G_RD##_##G_RS1##_##G_RS2 (const struct riscv_opcode *op, \
302+
insn_t insn) \
303+
{ \
304+
int rd = (insn & MASK_RD) >> OP_SH_RD; \
305+
int rs1 = (insn & MASK_RS1) >> OP_SH_RS1; \
306+
int rs2 = (insn & MASK_RS2) >> OP_SH_RS2; \
307+
return match_opcode (op, insn) \
308+
&& (rd % REGGROUP_REGS_##G_RD == 0) \
309+
&& (rs1 % REGGROUP_REGS_##G_RS1 == 0) \
310+
&& (rs2 % REGGROUP_REGS_##G_RS2 == 0); \
311+
}
312+
DEFINE_MATCH_FUNC_R_3(1, 1, 1)
313+
DEFINE_MATCH_FUNC_R_3(1, 2, 2)
314+
293315
static int
294316
match_th_load_inc(const struct riscv_opcode *op,
295317
insn_t insn)
@@ -982,6 +1004,24 @@ const struct riscv_opcode riscv_opcodes[] =
9821004
{"czero.eqz", 0, INSN_CLASS_ZICOND, "d,s,t", MATCH_CZERO_EQZ, MASK_CZERO_EQZ, match_opcode, 0 },
9831005
{"czero.nez", 0, INSN_CLASS_ZICOND, "d,s,t", MATCH_CZERO_NEZ, MASK_CZERO_NEZ, match_opcode, 0 },
9841006

1007+
/* Zacas instructions. */
1008+
{"amocas.w", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
1009+
{"amocas.w.aq", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W|MASK_AQ, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
1010+
{"amocas.w.rl", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W|MASK_RL, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
1011+
{"amocas.w.aqrl", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W|MASK_AQRL, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
1012+
{"amocas.d", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_8_BYTE },
1013+
{"amocas.d", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_1_1, INSN_DREF|INSN_8_BYTE },
1014+
{"amocas.d.aq", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQ, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_8_BYTE },
1015+
{"amocas.d.aq", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQ, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_1_1, INSN_DREF|INSN_8_BYTE },
1016+
{"amocas.d.rl", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_RL, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_8_BYTE },
1017+
{"amocas.d.rl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_RL, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_1_1, INSN_DREF|INSN_8_BYTE },
1018+
{"amocas.d.aqrl", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQRL, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_8_BYTE },
1019+
{"amocas.d.aqrl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQRL, MASK_AMOCAS_D|MASK_AQRL, match_reggroup_r_1_1_1, INSN_DREF|INSN_8_BYTE },
1020+
{"amocas.q", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q, MASK_AMOCAS_Q|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_16_BYTE },
1021+
{"amocas.q.aq", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_AQ, MASK_AMOCAS_Q|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_16_BYTE },
1022+
{"amocas.q.rl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_RL, MASK_AMOCAS_Q|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_16_BYTE },
1023+
{"amocas.q.aqrl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_AQRL, MASK_AMOCAS_Q|MASK_AQRL, match_reggroup_r_1_2_2, INSN_DREF|INSN_16_BYTE },
1024+
9851025
/* Zawrs instructions. */
9861026
{"wrs.nto", 0, INSN_CLASS_ZAWRS, "", MATCH_WRS_NTO, MASK_WRS_NTO, match_opcode, 0 },
9871027
{"wrs.sto", 0, INSN_CLASS_ZAWRS, "", MATCH_WRS_STO, MASK_WRS_STO, match_opcode, 0 },

0 commit comments

Comments
 (0)