diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index c070394a366..b7e067794ba 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -1148,6 +1148,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] = {"zhinx", "zhinxmin", check_implicit_always}, {"zhinxmin", "zfinx", check_implicit_always}, {"zfinx", "zicsr", check_implicit_always}, + {"zacas", "a", check_implicit_always}, {"zk", "zkn", check_implicit_always}, {"zk", "zkr", check_implicit_always}, {"zk", "zkt", check_implicit_always}, @@ -1259,6 +1260,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] = {"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 }, {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zacas", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 }, {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, @@ -2409,6 +2411,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps, return riscv_subset_supports (rps, "zmmul"); case INSN_CLASS_A: return riscv_subset_supports (rps, "a"); + case INSN_CLASS_ZACAS: + return riscv_subset_supports (rps, "zacas"); case INSN_CLASS_ZAWRS: return riscv_subset_supports (rps, "zawrs"); case INSN_CLASS_F: @@ -2619,6 +2623,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps, return _ ("m' or `zmmul"); case INSN_CLASS_A: return "a"; + case INSN_CLASS_ZACAS: + return "zacas"; case INSN_CLASS_ZAWRS: return "zawrs"; case INSN_CLASS_F: diff --git a/gas/testsuite/gas/riscv/zacas-32-fail.d b/gas/testsuite/gas/riscv/zacas-32-fail.d new file mode 100644 index 00000000000..12c1bd90ac8 --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-32-fail.d @@ -0,0 +1,2 @@ +#as: -march=rv32i_zacas +#error_output: zacas-32-fail.l diff --git a/gas/testsuite/gas/riscv/zacas-32-fail.l b/gas/testsuite/gas/riscv/zacas-32-fail.l new file mode 100644 index 00000000000..ecfb79d1306 --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-32-fail.l @@ -0,0 +1,9 @@ +.*: Assembler messages: +.*: Error: illegal operands `amocas\.d a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.d a1,a5,\(a2\)' +.*: Error: illegal operands `amocas\.d\.aq a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.d\.aq a1,a5,\(a2\)' +.*: Error: illegal operands `amocas\.d\.rl a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.d\.rl a1,a5,\(a2\)' +.*: Error: illegal operands `amocas\.d\.aqrl a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.d\.aqrl a1,a5,\(a2\)' diff --git a/gas/testsuite/gas/riscv/zacas-32-fail.s b/gas/testsuite/gas/riscv/zacas-32-fail.s new file mode 100644 index 00000000000..da7c6365858 --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-32-fail.s @@ -0,0 +1,10 @@ +target: + # amocas.d (RV32): rs1 (operand 3) and rs2 (operand 2) must be even. + amocas.d a1, a4, (a3) + amocas.d a1, a5, (a2) + amocas.d.aq a1, a4, (a3) + amocas.d.aq a1, a5, (a2) + amocas.d.rl a1, a4, (a3) + amocas.d.rl a1, a5, (a2) + amocas.d.aqrl a1, a4, (a3) + amocas.d.aqrl a1, a5, (a2) diff --git a/gas/testsuite/gas/riscv/zacas-32.d b/gas/testsuite/gas/riscv/zacas-32.d new file mode 100644 index 00000000000..e9f86b0d4e7 --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-32.d @@ -0,0 +1,17 @@ +#as: -march=rv32i_zacas +#objdump: -d + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+28f6a5af[ ]+amocas\.w[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+2cf6a5af[ ]+amocas\.w\.aq[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+2af6a5af[ ]+amocas\.w\.rl[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+2ef6a5af[ ]+amocas\.w\.aqrl[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+28e635af[ ]+amocas\.d[ ]+a1,a4,\(a2\) +[ ]+[0-9a-f]+:[ ]+2ce635af[ ]+amocas\.d\.aq[ ]+a1,a4,\(a2\) +[ ]+[0-9a-f]+:[ ]+2ae635af[ ]+amocas\.d\.rl[ ]+a1,a4,\(a2\) +[ ]+[0-9a-f]+:[ ]+2ee635af[ ]+amocas\.d\.aqrl[ ]+a1,a4,\(a2\) diff --git a/gas/testsuite/gas/riscv/zacas-32.s b/gas/testsuite/gas/riscv/zacas-32.s new file mode 100644 index 00000000000..1984ff9e6fa --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-32.s @@ -0,0 +1,9 @@ +target: + amocas.w a1, a5, (a3) + amocas.w.aq a1, a5, (a3) + amocas.w.rl a1, a5, (a3) + amocas.w.aqrl a1, a5, (a3) + amocas.d a1, a4, (a2) + amocas.d.aq a1, a4, (a2) + amocas.d.rl a1, a4, (a2) + amocas.d.aqrl a1, a4, (a2) diff --git a/gas/testsuite/gas/riscv/zacas-64-fail.d b/gas/testsuite/gas/riscv/zacas-64-fail.d new file mode 100644 index 00000000000..e1910d81f9e --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-64-fail.d @@ -0,0 +1,2 @@ +#as: -march=rv64i_zacas +#error_output: zacas-64-fail.l diff --git a/gas/testsuite/gas/riscv/zacas-64-fail.l b/gas/testsuite/gas/riscv/zacas-64-fail.l new file mode 100644 index 00000000000..e1e84347e76 --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-64-fail.l @@ -0,0 +1,9 @@ +.*: Assembler messages: +.*: Error: illegal operands `amocas\.q a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.q a1,a5,\(a2\)' +.*: Error: illegal operands `amocas\.q\.aq a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.q\.aq a1,a5,\(a2\)' +.*: Error: illegal operands `amocas\.q\.rl a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.q\.rl a1,a5,\(a2\)' +.*: Error: illegal operands `amocas\.q\.aqrl a1,a4,\(a3\)' +.*: Error: illegal operands `amocas\.q\.aqrl a1,a5,\(a2\)' diff --git a/gas/testsuite/gas/riscv/zacas-64-fail.s b/gas/testsuite/gas/riscv/zacas-64-fail.s new file mode 100644 index 00000000000..3236ed04199 --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-64-fail.s @@ -0,0 +1,10 @@ +target: + # amocas.q (RV64): rs1 (operand 3) and rs2 (operand 2) must be even. + amocas.q a1, a4, (a3) + amocas.q a1, a5, (a2) + amocas.q.aq a1, a4, (a3) + amocas.q.aq a1, a5, (a2) + amocas.q.rl a1, a4, (a3) + amocas.q.rl a1, a5, (a2) + amocas.q.aqrl a1, a4, (a3) + amocas.q.aqrl a1, a5, (a2) diff --git a/gas/testsuite/gas/riscv/zacas-64.d b/gas/testsuite/gas/riscv/zacas-64.d new file mode 100644 index 00000000000..c9eb723127b --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-64.d @@ -0,0 +1,17 @@ +#as: -march=rv64i_zacas +#objdump: -d + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+28f6b5af[ ]+amocas\.d[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+2cf6b5af[ ]+amocas\.d\.aq[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+2af6b5af[ ]+amocas\.d\.rl[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+2ef6b5af[ ]+amocas\.d\.aqrl[ ]+a1,a5,\(a3\) +[ ]+[0-9a-f]+:[ ]+28e645af[ ]+amocas\.q[ ]+a1,a4,\(a2\) +[ ]+[0-9a-f]+:[ ]+2ce645af[ ]+amocas\.q\.aq[ ]+a1,a4,\(a2\) +[ ]+[0-9a-f]+:[ ]+2ae645af[ ]+amocas\.q\.rl[ ]+a1,a4,\(a2\) +[ ]+[0-9a-f]+:[ ]+2ee645af[ ]+amocas\.q\.aqrl[ ]+a1,a4,\(a2\) diff --git a/gas/testsuite/gas/riscv/zacas-64.s b/gas/testsuite/gas/riscv/zacas-64.s new file mode 100644 index 00000000000..b9004487a2e --- /dev/null +++ b/gas/testsuite/gas/riscv/zacas-64.s @@ -0,0 +1,9 @@ +target: + amocas.d a1, a5, (a3) + amocas.d.aq a1, a5, (a3) + amocas.d.rl a1, a5, (a3) + amocas.d.aqrl a1, a5, (a3) + amocas.q a1, a4, (a2) + amocas.q.aq a1, a4, (a2) + amocas.q.rl a1, a4, (a2) + amocas.q.aqrl a1, a4, (a2) diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index 375483500e2..8fb59e3db93 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -2315,6 +2315,13 @@ #define MASK_C_NTL_S1 0xffff #define MATCH_C_NTL_ALL 0x9016 #define MASK_C_NTL_ALL 0xffff +/* Zacas instructions. */ +#define MATCH_AMOCAS_D 0x2800302f +#define MASK_AMOCAS_D 0xf800707f +#define MATCH_AMOCAS_Q 0x2800402f +#define MASK_AMOCAS_Q 0xf800707f +#define MATCH_AMOCAS_W 0x2800202f +#define MASK_AMOCAS_W 0xf800707f /* Zawrs instructions. */ #define MATCH_WRS_NTO 0x00d00073 #define MASK_WRS_NTO 0xffffffff @@ -3370,6 +3377,10 @@ DECLARE_INSN(c_ntl_p1, MATCH_C_NTL_P1, MASK_C_NTL_P1) DECLARE_INSN(c_ntl_pall, MATCH_C_NTL_PALL, MASK_C_NTL_PALL) DECLARE_INSN(c_ntl_s1, MATCH_C_NTL_S1, MASK_C_NTL_S1) DECLARE_INSN(c_ntl_all, MATCH_C_NTL_ALL, MASK_C_NTL_ALL) +/* Zacas instructions. */ +DECLARE_INSN(amocas_d, MATCH_AMOCAS_D, MASK_AMOCAS_D) +DECLARE_INSN(amocas_q, MATCH_AMOCAS_Q, MASK_AMOCAS_Q) +DECLARE_INSN(amocas_w, MATCH_AMOCAS_W, MASK_AMOCAS_W) /* Zawrs instructions. */ DECLARE_INSN(wrs_nto, MATCH_WRS_NTO, MASK_WRS_NTO) DECLARE_INSN(wrs_sto, MATCH_WRS_STO, MASK_WRS_STO) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 93dd5169ebc..aefbfc7db81 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -396,6 +396,7 @@ enum riscv_insn_class INSN_CLASS_ZIHINTNTL_AND_C, INSN_CLASS_ZIHINTPAUSE, INSN_CLASS_ZMMUL, + INSN_CLASS_ZACAS, INSN_CLASS_ZAWRS, INSN_CLASS_F_INX, INSN_CLASS_D_INX, diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 8e0ae85eb06..02e3f0ed482 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -290,6 +290,28 @@ match_vd_eq_vs1_eq_vs2 (const struct riscv_opcode *op, return match_opcode (op, insn) && vd == vs1 && vs1 == vs2; } +/* Instructions with register groups. */ + +#define REGGROUP_REGS_x 1 +#define REGGROUP_REGS_1 1 +#define REGGROUP_REGS_2 2 + +#define DEFINE_MATCH_FUNC_R_3(G_RD,G_RS1,G_RS2) \ + static int \ + match_reggroup_r_##G_RD##_##G_RS1##_##G_RS2 (const struct riscv_opcode *op, \ + insn_t insn) \ + { \ + int rd = (insn & MASK_RD) >> OP_SH_RD; \ + int rs1 = (insn & MASK_RS1) >> OP_SH_RS1; \ + int rs2 = (insn & MASK_RS2) >> OP_SH_RS2; \ + return match_opcode (op, insn) \ + && (rd % REGGROUP_REGS_##G_RD == 0) \ + && (rs1 % REGGROUP_REGS_##G_RS1 == 0) \ + && (rs2 % REGGROUP_REGS_##G_RS2 == 0); \ + } +DEFINE_MATCH_FUNC_R_3(1, 1, 1) +DEFINE_MATCH_FUNC_R_3(1, 2, 2) + static int match_th_load_inc(const struct riscv_opcode *op, insn_t insn) @@ -982,6 +1004,24 @@ const struct riscv_opcode riscv_opcodes[] = {"czero.eqz", 0, INSN_CLASS_ZICOND, "d,s,t", MATCH_CZERO_EQZ, MASK_CZERO_EQZ, match_opcode, 0 }, {"czero.nez", 0, INSN_CLASS_ZICOND, "d,s,t", MATCH_CZERO_NEZ, MASK_CZERO_NEZ, match_opcode, 0 }, +/* Zacas instructions. */ +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, +{"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 }, + /* Zawrs instructions. */ {"wrs.nto", 0, INSN_CLASS_ZAWRS, "", MATCH_WRS_NTO, MASK_WRS_NTO, match_opcode, 0 }, {"wrs.sto", 0, INSN_CLASS_ZAWRS, "", MATCH_WRS_STO, MASK_WRS_STO, match_opcode, 0 },