diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 49c644bafd1..5138b67f6ab 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -1288,7 +1288,9 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] = {"b", "zbs", check_implicit_always}, {"a", "zaamo", check_implicit_always}, {"a", "zalrsc", check_implicit_always}, - + {"zilsd", "zicsr", check_implicit_always}, + {"zclsd", "zilsd", check_implicit_always}, + {"zclsd", "zca", check_implicit_always}, {"xsfvcp", "zve32x", check_implicit_always}, {NULL, NULL, NULL} }; @@ -1435,6 +1437,8 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] = {"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zcmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zilsd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zclsd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {NULL, 0, 0, 0, 0} }; @@ -2103,6 +2107,31 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps) (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension")); no_conflict = false; } + //Add zclsd conflicts + if (riscv_lookup_subset (rps->subset_list, "zclsd", &subset) + && ((riscv_lookup_subset (rps->subset_list, "c", &subset) + && riscv_lookup_subset (rps->subset_list, "f", &subset)) + || riscv_lookup_subset (rps->subset_list, "zcf", &subset))) + { + rps->error_handler + (_("`zclsd' is conflict with the `c+f'/ `zcf' extension")); + no_conflict = false; + } + if (riscv_lookup_subset (rps->subset_list, "zclsd", &subset) + && xlen > 32) + { + rps->error_handler + (_("rv%d does not support the `zclsd' extension"), xlen); + no_conflict = false; + } + //Add zilsd conflicts + if (riscv_lookup_subset (rps->subset_list, "zilsd", &subset) + && xlen > 32) + { + rps->error_handler + (_("rv%d does not support the `zilsd' extension"), xlen); + no_conflict = false; + } if (riscv_lookup_subset (rps->subset_list, "xtheadvector", &subset) && riscv_lookup_subset (rps->subset_list, "v", &subset)) { @@ -2738,6 +2767,10 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps, return riscv_subset_supports (rps, "xsfvcp"); case INSN_CLASS_XSFCEASE: return riscv_subset_supports (rps, "xsfcease"); + case INSN_CLASS_ZILSD: + return riscv_subset_supports(rps, "zilsd"); + case INSN_CLASS_ZCLSD: + return riscv_subset_supports(rps, "zclsd"); default: rps->error_handler (_("internal: unreachable INSN_CLASS_*")); @@ -3008,6 +3041,10 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps, return "xtheadzvamo"; case INSN_CLASS_XSFCEASE: return "xsfcease"; + case INSN_CLASS_ZILSD: + return "zilsd"; + case INSN_CLASS_ZCLSD: + return "zclsd"; default: rps->error_handler (_("internal: unreachable INSN_CLASS_*")); diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index e0083702fbd..f71d089fc0d 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -1714,6 +1714,15 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length) goto unknown_validate_operand; } break; + case 'G': /* Zilsd operand */ + switch (*++oparg) + { + case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break; + case 't': USE_BITS (OP_MASK_RS2, OP_SH_RS2); break; + default: + goto unknown_validate_operand; + } + break; default: unknown_validate_operand: as_bad (_("internal: bad RISC-V opcode " @@ -4048,6 +4057,33 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, } break; + case 'G': /* Zilsd ld,sd specific operands. */ + switch(*++oparg) + { + case 'd': + case 't': + if (reg_lookup (&asarg, RCLASS_GPR, ®no)&&(regno%2==0)) + { + char c = *oparg; + if (*asarg == ' ') + ++asarg; + + /* Now that we have assembled one operand, we use the args + string to figure out where it goes in the instruction. */ + switch (c) + { + case 'd': + INSERT_OPERAND (RD, *ip, regno); + break; + case 't': + INSERT_OPERAND (RS2, *ip, regno); + break; + } + continue; + } + } + break; + default: unknown_riscv_ip_operand: as_fatal (_("internal: unknown argument type `%s'"), diff --git a/gas/testsuite/gas/riscv/march-fail-zclsd-01.d b/gas/testsuite/gas/riscv/march-fail-zclsd-01.d new file mode 100644 index 00000000000..003f26c14c7 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-fail-zclsd-01.d @@ -0,0 +1,3 @@ +#as: -march=rv64i_zca_zclsd +#source: empty.s +#error_output: march-fail-zclsd-01.l \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/march-fail-zclsd-01.l b/gas/testsuite/gas/riscv/march-fail-zclsd-01.l new file mode 100644 index 00000000000..07d631da9b3 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-fail-zclsd-01.l @@ -0,0 +1,2 @@ +.*Assembler messages: +.*Error: .*rv64 does not support the `zclsd' extension \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/march-fail-zclsd-02.d b/gas/testsuite/gas/riscv/march-fail-zclsd-02.d new file mode 100644 index 00000000000..91f3ce5d81a --- /dev/null +++ b/gas/testsuite/gas/riscv/march-fail-zclsd-02.d @@ -0,0 +1,3 @@ +#as: -march=rv32i_zcf_zclsd +#source: empty.s +#error_output: march-fail-zclsd-02.l \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/march-fail-zclsd-02.l b/gas/testsuite/gas/riscv/march-fail-zclsd-02.l new file mode 100644 index 00000000000..db5d57918e2 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-fail-zclsd-02.l @@ -0,0 +1,2 @@ +.*Assembler messages: +.*Error: .*`zclsd' is conflict with the `c+f'/ `zcf' extension \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/march-fail-zilsd.d b/gas/testsuite/gas/riscv/march-fail-zilsd.d new file mode 100644 index 00000000000..49866d2a078 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-fail-zilsd.d @@ -0,0 +1,3 @@ +#as: -march=rv64i_zilsd +#source: empty.s +#error_output: march-fail-zilsd.l \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/march-fail-zilsd.l b/gas/testsuite/gas/riscv/march-fail-zilsd.l new file mode 100644 index 00000000000..af8152fdf33 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-fail-zilsd.l @@ -0,0 +1,2 @@ +.*Assembler messages: +.*Error: .*rv64 does not support the `zilsd' extension \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/zclsd.d b/gas/testsuite/gas/riscv/zclsd.d new file mode 100644 index 00000000000..3b17630842c --- /dev/null +++ b/gas/testsuite/gas/riscv/zclsd.d @@ -0,0 +1,13 @@ +#as: -march=rv32g_zca_zilsd_zclsd +#source: zclsd.s +#objdump: -dr -Mno-aliases + +.*:[ ]+file format .* + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+7218[ ]+c.ld[ ]+a4,32\(a2\) +[ ]+[0-9a-f]+:[ ]+f218[ ]+c.sd[ ]+a4,32\(a2\) +[ ]+[0-9a-f]+:[ ]+6222[ ]+c.ldsp[ ]+tp,8\(sp\) +[ ]+[0-9a-f]+:[ ]+e412[ ]+c.sdsp[ ]+tp,8\(sp\) \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/zclsd.s b/gas/testsuite/gas/riscv/zclsd.s new file mode 100644 index 00000000000..c147bea4b71 --- /dev/null +++ b/gas/testsuite/gas/riscv/zclsd.s @@ -0,0 +1,6 @@ ++target: + c.ld a4, 32(a2) + c.sd a4, 32(a2) + c.ldsp x4, 8(x2) + c.sdsp x4, 8(x2) + \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/zilsd.d b/gas/testsuite/gas/riscv/zilsd.d new file mode 100644 index 00000000000..8d5aba659ba --- /dev/null +++ b/gas/testsuite/gas/riscv/zilsd.d @@ -0,0 +1,11 @@ +#as: -march=rv64g_zilsd +#source: zilsd.s +#objdump: -dr + +.*:[ ]+file format .* + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+00053503[ ]+ld[ ]+a0,0\(a0\) +[ ]+[0-9a-f]+:[ ]+00a53023[ ]+sd[ ]+a0,0\(a0\) \ No newline at end of file diff --git a/gas/testsuite/gas/riscv/zilsd.s b/gas/testsuite/gas/riscv/zilsd.s new file mode 100644 index 00000000000..15333cadc1a --- /dev/null +++ b/gas/testsuite/gas/riscv/zilsd.s @@ -0,0 +1,3 @@ +target: + ld a0, 0(a0) + sd a0, 0(a0) \ No newline at end of file diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index ece2963d531..52912a2c815 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -516,6 +516,8 @@ enum riscv_insn_class INSN_CLASS_XVENTANACONDOPS, INSN_CLASS_XSFVCP, INSN_CLASS_XSFCEASE, + INSN_CLASS_ZILSD, + INSN_CLASS_ZCLSD, }; /* This structure holds information for a particular instruction. */ diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 9c5e6ce1e69..02f9e59338a 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -838,6 +838,24 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info goto undefined_modifier; } break; + case 'G': /* Zilsd ld,sd specific operands. */ + switch (*++oparg) + { + case 'd': + if ((l & MASK_AUIPC) == MATCH_AUIPC) + pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l); + else if ((l & MASK_LUI) == MATCH_LUI) + pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l); + else if ((l & MASK_C_LUI) == MATCH_C_LUI) + pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l); + print (info->stream, dis_style_register, "%s", riscv_gpr_names[rd]); + break; + case 't': + print (info->stream, dis_style_register, "%s", + riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]); + break; + } + break; default: undefined_modifier: diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index f7c0f5c7c83..4d481e615f5 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -562,10 +562,18 @@ const struct riscv_opcode riscv_opcodes[] = {"xor", 0, INSN_CLASS_I, "d,s,t", MATCH_XOR, MASK_XOR, match_opcode, 0 }, {"lwu", 64, INSN_CLASS_I, "d,o(s)", MATCH_LWU, MASK_LWU, match_opcode, INSN_DREF|INSN_4_BYTE }, {"lwu", 64, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO }, +{"ld", 32, INSN_CLASS_ZCLSD, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, +{"ld", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, +{"ld", 32, INSN_CLASS_ZILSD, "Gd,o(s)", MATCH_LD, MASK_LD, match_opcode, INSN_DREF|INSN_8_BYTE }, +{"ld", 32, INSN_CLASS_ZILSD, "Gd,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO }, {"ld", 64, INSN_CLASS_C, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, {"ld", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, {"ld", 64, INSN_CLASS_I, "d,o(s)", MATCH_LD, MASK_LD, match_opcode, INSN_DREF|INSN_8_BYTE }, {"ld", 64, INSN_CLASS_I, "d,A", 0, (int) M_Lx, match_rd_nonzero, INSN_MACRO }, +{"sd", 32, INSN_CLASS_ZCLSD, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, +{"sd", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, +{"sd", 32, INSN_CLASS_ZILSD, "Gt,q(s)", MATCH_SD, MASK_SD, match_opcode, INSN_DREF|INSN_8_BYTE }, +{"sd", 32, INSN_CLASS_ZILSD, "Gt,A,s", 0, (int) M_Sx_FSx, match_rs1_nonzero, INSN_MACRO }, {"sd", 64, INSN_CLASS_C, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, {"sd", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS|INSN_DREF|INSN_8_BYTE }, {"sd", 64, INSN_CLASS_I, "t,q(s)", MATCH_SD, MASK_SD, match_opcode, INSN_DREF|INSN_8_BYTE }, @@ -1093,9 +1101,13 @@ const struct riscv_opcode riscv_opcodes[] = {"c.addiw", 64, INSN_CLASS_C, "d,Co", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, 0 }, {"c.addw", 64, INSN_CLASS_C, "Cs,Ct", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, 0 }, {"c.subw", 64, INSN_CLASS_C, "Cs,Ct", MATCH_C_SUBW, MASK_C_SUBW, match_opcode, 0 }, +{"c.ldsp", 32, INSN_CLASS_ZCLSD, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_DREF|INSN_8_BYTE }, {"c.ldsp", 64, INSN_CLASS_C, "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_DREF|INSN_8_BYTE }, +{"c.ld", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_DREF|INSN_8_BYTE }, {"c.ld", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_DREF|INSN_8_BYTE }, +{"c.sdsp", 32, INSN_CLASS_ZCLSD, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_DREF|INSN_8_BYTE }, {"c.sdsp", 64, INSN_CLASS_C, "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_DREF|INSN_8_BYTE }, +{"c.sd", 32, INSN_CLASS_ZCLSD, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_DREF|INSN_8_BYTE }, {"c.sd", 64, INSN_CLASS_C, "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_DREF|INSN_8_BYTE }, {"c.fldsp", 0, INSN_CLASS_D_AND_C, "D,Cn(Cc)", MATCH_C_FLDSP, MASK_C_FLDSP, match_opcode, INSN_DREF|INSN_8_BYTE }, {"c.fld", 0, INSN_CLASS_D_AND_C, "CD,Cl(Cs)", MATCH_C_FLD, MASK_C_FLD, match_opcode, INSN_DREF|INSN_8_BYTE },