aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNelson Chu <nelson.chu@sifive.com>2020-02-12 02:18:51 -0800
committerJim Wilson <jimw@sifive.com>2020-02-20 16:49:09 -0800
commit54b2aec10df9ad032184c556ec9cc3f611a91830 (patch)
treeb8a42a4500cd3a7faf247ab0ef07789ab2b4628f /gas
parent2ca89224b1ce2cf170bb891b211bede4f6eda473 (diff)
downloadgdb-54b2aec10df9ad032184c556ec9cc3f611a91830.zip
gdb-54b2aec10df9ad032184c556ec9cc3f611a91830.tar.gz
gdb-54b2aec10df9ad032184c556ec9cc3f611a91830.tar.bz2
RISC-V: Support the read-only CSR checking.
CSRRW and CSRRWI always write CSR. CSRRS, CSRRC, CSRRSI and CSRRCI write CSR when RS1 isn't zero. The CSR is read only if the [11:10] bits of CSR address is 0x3. The read-only CSR can not be written by the CSR instructions. gas/ * config/tc-riscv.c (riscv_ip): New boolean insn_with_csr to indicate we are assembling instruction with CSR. Call riscv_csr_read_only_check after parsing all arguments. (enum csr_insn_type): New enum is used to classify the CSR instruction. (riscv_csr_insn_type, riscv_csr_read_only_check): New functions. These are used to check if we write a read-only CSR by the CSR instruction. * testsuite/gas/riscv/priv-reg-fail-read-only-01.s: New testcase. Test all CSR for the read-only CSR checking. * testsuite/gas/riscv/priv-reg-fail-read-only-01.d: Likewise. * testsuite/gas/riscv/priv-reg-fail-read-only-01.l: Likewise. * testsuite/gas/riscv/priv-reg-fail-read-only-02.s: New testcase. Test all CSR instructions for the read-only CSR checking. * testsuite/gas/riscv/priv-reg-fail-read-only-02.d: Likewise. * testsuite/gas/riscv/priv-reg-fail-read-only-02.l: Likewise.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog15
-rw-r--r--gas/config/tc-riscv.c69
-rw-r--r--gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.d3
-rw-r--r--gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.l69
-rw-r--r--gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.s269
-rw-r--r--gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.d3
-rw-r--r--gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.l25
-rw-r--r--gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.s90
8 files changed, 543 insertions, 0 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 643f8c7..d472353 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,20 @@
2020-02-20 Nelson Chu <nelson.chu@sifive.com>
+ * config/tc-riscv.c (riscv_ip): New boolean insn_with_csr to indicate
+ we are assembling instruction with CSR. Call riscv_csr_read_only_check
+ after parsing all arguments.
+ (enum csr_insn_type): New enum is used to classify the CSR instruction.
+ (riscv_csr_insn_type, riscv_csr_read_only_check): New functions. These
+ are used to check if we write a read-only CSR by the CSR instruction.
+ * testsuite/gas/riscv/priv-reg-fail-read-only-01.s: New testcase. Test
+ all CSR for the read-only CSR checking.
+ * testsuite/gas/riscv/priv-reg-fail-read-only-01.d: Likewise.
+ * testsuite/gas/riscv/priv-reg-fail-read-only-01.l: Likewise.
+ * testsuite/gas/riscv/priv-reg-fail-read-only-02.s: New testcase. Test
+ all CSR instructions for the read-only CSR checking.
+ * testsuite/gas/riscv/priv-reg-fail-read-only-02.d: Likewise.
+ * testsuite/gas/riscv/priv-reg-fail-read-only-02.l: Likewise.
+
* config/tc-riscv.c (struct riscv_set_options): New field csr_check.
(riscv_opts): Initialize it.
(reg_lookup_internal): Check the `riscv_opts.csr_check`
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 5972f02..1559b08 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1486,6 +1486,56 @@ riscv_handle_implicit_zero_offset (expressionS *ep, const char *s)
return FALSE;
}
+/* All RISC-V CSR instructions belong to one of these classes. */
+
+enum csr_insn_type
+{
+ INSN_NOT_CSR,
+ INSN_CSRRW,
+ INSN_CSRRS,
+ INSN_CSRRC
+};
+
+/* Return which CSR instruction is checking. */
+
+static enum csr_insn_type
+riscv_csr_insn_type (insn_t insn)
+{
+ if (((insn ^ MATCH_CSRRW) & MASK_CSRRW) == 0
+ || ((insn ^ MATCH_CSRRWI) & MASK_CSRRWI) == 0)
+ return INSN_CSRRW;
+ else if (((insn ^ MATCH_CSRRS) & MASK_CSRRS) == 0
+ || ((insn ^ MATCH_CSRRSI) & MASK_CSRRSI) == 0)
+ return INSN_CSRRS;
+ else if (((insn ^ MATCH_CSRRC) & MASK_CSRRC) == 0
+ || ((insn ^ MATCH_CSRRCI) & MASK_CSRRCI) == 0)
+ return INSN_CSRRC;
+ else
+ return INSN_NOT_CSR;
+}
+
+/* CSRRW and CSRRWI always write CSR. CSRRS, CSRRC, CSRRSI and CSRRCI write
+ CSR when RS1 isn't zero. The CSR is read only if the [11:10] bits of
+ CSR address is 0x3. */
+
+static bfd_boolean
+riscv_csr_read_only_check (insn_t insn)
+{
+ int csr = (insn & (OP_MASK_CSR << OP_SH_CSR)) >> OP_SH_CSR;
+ int rs1 = (insn & (OP_MASK_RS1 << OP_SH_RS1)) >> OP_SH_RS1;
+ int readonly = (((csr & (0x3 << 10)) >> 10) == 0x3);
+ enum csr_insn_type csr_insn = riscv_csr_insn_type (insn);
+
+ if (readonly
+ && (((csr_insn == INSN_CSRRS
+ || csr_insn == INSN_CSRRC)
+ && rs1 != 0)
+ || csr_insn == INSN_CSRRW))
+ return FALSE;
+
+ return TRUE;
+}
+
/* This routine assembles an instruction into its binary format. As a
side effect, it sets the global variable imm_reloc to the type of
relocation to do if one of the operands is an address expression. */
@@ -1504,6 +1554,8 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
int argnum;
const struct percent_op_match *p;
const char *error = "unrecognized opcode";
+ /* Indicate we are assembling instruction with CSR. */
+ bfd_boolean insn_with_csr = FALSE;
/* Parse the name of the instruction. Terminate the string if whitespace
is found so that hash_find only sees the name part of the string. */
@@ -1550,11 +1602,26 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
: insn->match) == 2
&& !riscv_opts.rvc)
break;
+
+ /* Check if we write a read-only CSR by the CSR
+ instruction. */
+ if (insn_with_csr
+ && riscv_opts.csr_check
+ && !riscv_csr_read_only_check (ip->insn_opcode))
+ {
+ /* Restore the character in advance, since we want to
+ report the detailed warning message here. */
+ if (save_c)
+ *(argsStart - 1) = save_c;
+ as_warn (_("Read-only CSR is written `%s'"), str);
+ insn_with_csr = FALSE;
+ }
}
if (*s != '\0')
break;
/* Successful assembly. */
error = NULL;
+ insn_with_csr = FALSE;
goto out;
case 'C': /* RVC */
@@ -1899,6 +1966,7 @@ rvc_lui:
continue;
case 'E': /* Control register. */
+ insn_with_csr = TRUE;
if (reg_lookup (&s, RCLASS_CSR, &regno))
INSERT_OPERAND (CSR, *ip, regno);
else
@@ -2219,6 +2287,7 @@ jump:
}
s = argsStart;
error = _("illegal operands");
+ insn_with_csr = FALSE;
}
out:
diff --git a/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.d b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.d
new file mode 100644
index 0000000..ae190c0
--- /dev/null
+++ b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.d
@@ -0,0 +1,3 @@
+#as: -march=rv32if -mcsr-check
+#source: priv-reg-fail-read-only-01.s
+#warning_output: priv-reg-fail-read-only-01.l
diff --git a/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.l b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.l
new file mode 100644
index 0000000..7e52bd7
--- /dev/null
+++ b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.l
@@ -0,0 +1,69 @@
+.*Assembler messages:
+.*Warning: Read-only CSR is written `csrw cycle,a1'
+.*Warning: Read-only CSR is written `csrw time,a1'
+.*Warning: Read-only CSR is written `csrw instret,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter3,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter4,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter5,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter6,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter7,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter8,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter9,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter10,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter11,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter12,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter13,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter14,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter15,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter16,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter17,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter18,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter19,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter20,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter21,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter22,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter23,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter24,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter25,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter26,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter27,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter28,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter29,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter30,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter31,a1'
+.*Warning: Read-only CSR is written `csrw cycleh,a1'
+.*Warning: Read-only CSR is written `csrw timeh,a1'
+.*Warning: Read-only CSR is written `csrw instreth,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter3h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter4h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter5h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter6h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter7h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter8h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter9h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter10h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter11h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter12h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter13h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter14h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter15h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter16h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter17h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter18h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter19h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter20h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter21h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter22h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter23h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter24h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter25h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter26h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter27h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter28h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter29h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter30h,a1'
+.*Warning: Read-only CSR is written `csrw hpmcounter31h,a1'
+.*Warning: Read-only CSR is written `csrw mvendorid,a1'
+.*Warning: Read-only CSR is written `csrw marchid,a1'
+.*Warning: Read-only CSR is written `csrw mimpid,a1'
+.*Warning: Read-only CSR is written `csrw mhartid,a1'
diff --git a/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.s b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.s
new file mode 100644
index 0000000..501a52e
--- /dev/null
+++ b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-01.s
@@ -0,0 +1,269 @@
+ .macro csr val
+ csrw \val, a1
+ .endm
+# 1.9.1 registers
+ csr ustatus
+ csr uie
+ csr utvec
+
+ csr uscratch
+ csr uepc
+ csr ucause
+ csr ubadaddr
+ csr uip
+
+ csr fflags
+ csr frm
+ csr fcsr
+
+ csr cycle
+ csr time
+ csr instret
+ csr hpmcounter3
+ csr hpmcounter4
+ csr hpmcounter5
+ csr hpmcounter6
+ csr hpmcounter7
+ csr hpmcounter8
+ csr hpmcounter9
+ csr hpmcounter10
+ csr hpmcounter11
+ csr hpmcounter12
+ csr hpmcounter13
+ csr hpmcounter14
+ csr hpmcounter15
+ csr hpmcounter16
+ csr hpmcounter17
+ csr hpmcounter18
+ csr hpmcounter19
+ csr hpmcounter20
+ csr hpmcounter21
+ csr hpmcounter22
+ csr hpmcounter23
+ csr hpmcounter24
+ csr hpmcounter25
+ csr hpmcounter26
+ csr hpmcounter27
+ csr hpmcounter28
+ csr hpmcounter29
+ csr hpmcounter30
+ csr hpmcounter31
+ csr cycleh
+ csr timeh
+ csr instreth
+ csr hpmcounter3h
+ csr hpmcounter4h
+ csr hpmcounter5h
+ csr hpmcounter6h
+ csr hpmcounter7h
+ csr hpmcounter8h
+ csr hpmcounter9h
+ csr hpmcounter10h
+ csr hpmcounter11h
+ csr hpmcounter12h
+ csr hpmcounter13h
+ csr hpmcounter14h
+ csr hpmcounter15h
+ csr hpmcounter16h
+ csr hpmcounter17h
+ csr hpmcounter18h
+ csr hpmcounter19h
+ csr hpmcounter20h
+ csr hpmcounter21h
+ csr hpmcounter22h
+ csr hpmcounter23h
+ csr hpmcounter24h
+ csr hpmcounter25h
+ csr hpmcounter26h
+ csr hpmcounter27h
+ csr hpmcounter28h
+ csr hpmcounter29h
+ csr hpmcounter30h
+ csr hpmcounter31h
+
+ csr sstatus
+ csr sedeleg
+ csr sideleg
+ csr sie
+ csr stvec
+
+ csr sscratch
+ csr sepc
+ csr scause
+ csr sbadaddr
+ csr sip
+
+ csr sptbr
+
+ csr hstatus
+ csr hedeleg
+ csr hideleg
+ csr hie
+ csr htvec
+
+ csr hscratch
+ csr hepc
+ csr hcause
+ csr hbadaddr
+ csr hip
+
+ csr mvendorid
+ csr marchid
+ csr mimpid
+ csr mhartid
+
+ csr mstatus
+ csr misa
+ csr medeleg
+ csr mideleg
+ csr mie
+ csr mtvec
+
+ csr mscratch
+ csr mepc
+ csr mcause
+ csr mbadaddr
+ csr mip
+
+ csr mbase
+ csr mbound
+ csr mibase
+ csr mibound
+ csr mdbase
+ csr mdbound
+
+ csr mcycle
+ csr minstret
+ csr mhpmcounter3
+ csr mhpmcounter4
+ csr mhpmcounter5
+ csr mhpmcounter6
+ csr mhpmcounter7
+ csr mhpmcounter8
+ csr mhpmcounter9
+ csr mhpmcounter10
+ csr mhpmcounter11
+ csr mhpmcounter12
+ csr mhpmcounter13
+ csr mhpmcounter14
+ csr mhpmcounter15
+ csr mhpmcounter16
+ csr mhpmcounter17
+ csr mhpmcounter18
+ csr mhpmcounter19
+ csr mhpmcounter20
+ csr mhpmcounter21
+ csr mhpmcounter22
+ csr mhpmcounter23
+ csr mhpmcounter24
+ csr mhpmcounter25
+ csr mhpmcounter26
+ csr mhpmcounter27
+ csr mhpmcounter28
+ csr mhpmcounter29
+ csr mhpmcounter30
+ csr mhpmcounter31
+ csr mcycleh
+ csr minstreth
+ csr mhpmcounter3h
+ csr mhpmcounter4h
+ csr mhpmcounter5h
+ csr mhpmcounter6h
+ csr mhpmcounter7h
+ csr mhpmcounter8h
+ csr mhpmcounter9h
+ csr mhpmcounter10h
+ csr mhpmcounter11h
+ csr mhpmcounter12h
+ csr mhpmcounter13h
+ csr mhpmcounter14h
+ csr mhpmcounter15h
+ csr mhpmcounter16h
+ csr mhpmcounter17h
+ csr mhpmcounter18h
+ csr mhpmcounter19h
+ csr mhpmcounter20h
+ csr mhpmcounter21h
+ csr mhpmcounter22h
+ csr mhpmcounter23h
+ csr mhpmcounter24h
+ csr mhpmcounter25h
+ csr mhpmcounter26h
+ csr mhpmcounter27h
+ csr mhpmcounter28h
+ csr mhpmcounter29h
+ csr mhpmcounter30h
+ csr mhpmcounter31h
+
+ csr mucounteren
+ csr mscounteren
+ csr mhcounteren
+
+ csr mhpmevent3
+ csr mhpmevent4
+ csr mhpmevent5
+ csr mhpmevent6
+ csr mhpmevent7
+ csr mhpmevent8
+ csr mhpmevent9
+ csr mhpmevent10
+ csr mhpmevent11
+ csr mhpmevent12
+ csr mhpmevent13
+ csr mhpmevent14
+ csr mhpmevent15
+ csr mhpmevent16
+ csr mhpmevent17
+ csr mhpmevent18
+ csr mhpmevent19
+ csr mhpmevent20
+ csr mhpmevent21
+ csr mhpmevent22
+ csr mhpmevent23
+ csr mhpmevent24
+ csr mhpmevent25
+ csr mhpmevent26
+ csr mhpmevent27
+ csr mhpmevent28
+ csr mhpmevent29
+ csr mhpmevent30
+ csr mhpmevent31
+
+ csr tselect
+ csr tdata1
+ csr tdata2
+ csr tdata3
+
+ csr dcsr
+ csr dpc
+ csr dscratch
+# 1.10 registers
+ csr utval
+
+ csr scounteren
+ csr stval
+ csr satp
+
+ csr mcounteren
+ csr mtval
+
+ csr pmpcfg0
+ csr pmpcfg1
+ csr pmpcfg2
+ csr pmpcfg3
+ csr pmpaddr0
+ csr pmpaddr1
+ csr pmpaddr2
+ csr pmpaddr3
+ csr pmpaddr4
+ csr pmpaddr5
+ csr pmpaddr6
+ csr pmpaddr7
+ csr pmpaddr8
+ csr pmpaddr9
+ csr pmpaddr10
+ csr pmpaddr11
+ csr pmpaddr12
+ csr pmpaddr13
+ csr pmpaddr14
+ csr pmpaddr15
diff --git a/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.d b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.d
new file mode 100644
index 0000000..3c4715f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.d
@@ -0,0 +1,3 @@
+#as: -march=rv32if -mcsr-check
+#source: priv-reg-fail-read-only-02.s
+#warning_output: priv-reg-fail-read-only-02.l
diff --git a/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.l b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.l
new file mode 100644
index 0000000..660f19d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.l
@@ -0,0 +1,25 @@
+.*Assembler messages:
+.*Warning: Read-only CSR is written `csrrw a0,cycle,a1'
+.*Warning: Read-only CSR is written `csrrw a0,cycle,zero'
+.*Warning: Read-only CSR is written `csrrw zero,cycle,a1'
+.*Warning: Read-only CSR is written `csrrw zero,cycle,zero'
+.*Warning: Read-only CSR is written `csrw cycle,a1'
+.*Warning: Read-only CSR is written `csrw cycle,zero'
+.*Warning: Read-only CSR is written `csrrwi a0,cycle,0xb'
+.*Warning: Read-only CSR is written `csrrwi a0,cycle,0x0'
+.*Warning: Read-only CSR is written `csrrwi zero,cycle,0xb'
+.*Warning: Read-only CSR is written `csrrwi zero,cycle,0x0'
+.*Warning: Read-only CSR is written `csrwi cycle,0xb'
+.*Warning: Read-only CSR is written `csrwi cycle,0x0'
+.*Warning: Read-only CSR is written `csrrs a0,cycle,a1'
+.*Warning: Read-only CSR is written `csrrs zero,cycle,a1'
+.*Warning: Read-only CSR is written `csrs cycle,a0'
+.*Warning: Read-only CSR is written `csrrsi a0,cycle,0xb'
+.*Warning: Read-only CSR is written `csrrsi zero,cycle,0xb'
+.*Warning: Read-only CSR is written `csrsi cycle,0xb'
+.*Warning: Read-only CSR is written `csrrc a0,cycle,a1'
+.*Warning: Read-only CSR is written `csrrc zero,cycle,a1'
+.*Warning: Read-only CSR is written `csrc cycle,a0'
+.*Warning: Read-only CSR is written `csrrci a0,cycle,0xb'
+.*Warning: Read-only CSR is written `csrrci zero,cycle,0xb'
+.*Warning: Read-only CSR is written `csrci cycle,0xb'
diff --git a/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.s b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.s
new file mode 100644
index 0000000..7afb26e
--- /dev/null
+++ b/gas/testsuite/gas/riscv/priv-reg-fail-read-only-02.s
@@ -0,0 +1,90 @@
+# CSRRW and CSRRWI always write CSR
+# CSRRS, CSRRC, CSRRSI and CSRRCI write CSR when rs isn't zero.
+
+# csrrw rd, csr, rs
+ csrrw a0, ustatus, a1
+ csrrw a0, cycle, a1
+ csrrw a0, cycle, zero
+ csrrw zero, cycle, a1
+ csrrw zero, cycle, zero
+ fscsr a0, a1
+ fsrm a0, a1
+ fsflags a0, a1
+# csrrw zero, csr, rs
+ csrw ustatus, a1
+ csrw cycle, a1
+ csrw cycle, zero
+ fscsr a1
+ fsrm a1
+ fsflags a1
+# csrrwi rd, csr, imm
+ csrrwi a0, ustatus, 0xb
+ csrrwi a0, cycle, 0xb
+ csrrwi a0, cycle, 0x0
+ csrrwi zero, cycle, 0xb
+ csrrwi zero, cycle, 0x0
+# csrrwi zero, csr, imm
+ csrwi ustatus, 0xb
+ csrwi cycle, 0xb
+ csrwi cycle, 0x0
+
+# csrrs rd, csr, rs
+ csrrs a0, ustatus, a1
+ csrrs a0, cycle, a1
+ csrrs a0, cycle, zero
+ csrrs zero, cycle, a1
+ csrrs zero, cycle, zero
+# csrrs rd, csr, zero
+ csrr a0, ustatus
+ csrr a0, cycle
+ csrr zero, cycle
+ rdinstret a0
+ rdinstret zero
+ rdinstreth a0
+ rdinstreth zero
+ rdcycle a0
+ rdcycle zero
+ rdcycleh a0
+ rdcycleh zero
+ rdtime a0
+ rdtime zero
+ rdtimeh a0
+ rdtimeh zero
+ frcsr a0
+ frrm a0
+ frflags a0
+# csrrs zero, csr, rs
+ csrs ustatus, a0
+ csrs cycle, a0
+ csrs cycle, zero
+# csrrsi rd, csr, imm
+ csrrsi a0, ustatus, 0xb
+ csrrsi a0, cycle, 0xb
+ csrrsi a0, cycle, 0x0
+ csrrsi zero, cycle, 0xb
+ csrrsi zero, cycle, 0x0
+# csrrsi zero, csr, imm
+ csrsi ustatus, 0xb
+ csrsi cycle, 0xb
+ csrsi cycle, 0x0
+
+# csrrc a0, csr, a1
+ csrrc a0, ustatus, a1
+ csrrc a0, cycle, a1
+ csrrc a0, cycle, zero
+ csrrc zero, cycle, a1
+ csrrc zero, cycle, zero
+# csrrc zero, csr, rs
+ csrc ustatus, a0
+ csrc cycle, a0
+ csrc cycle, zero
+# csrrci rd, csr, imm
+ csrrci a0, ustatus, 0xb
+ csrrci a0, cycle, 0xb
+ csrrci a0, cycle, 0x0
+ csrrci zero, cycle, 0xb
+ csrrci zero, cycle, 0x0
+# csrrci zero, csr, imm
+ csrci ustatus, 0xb
+ csrci cycle, 0xb
+ csrci cycle, 0x0