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`
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. */
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. */
: 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 */
continue;
case 'E': /* Control register. */
+ insn_with_csr = TRUE;
if (reg_lookup (&s, RCLASS_CSR, ®no))
INSERT_OPERAND (CSR, *ip, regno);
else
}
s = argsStart;
error = _("illegal operands");
+ insn_with_csr = FALSE;
}
out:
--- /dev/null
+#as: -march=rv32if -mcsr-check
+#source: priv-reg-fail-read-only-01.s
+#warning_output: priv-reg-fail-read-only-01.l
--- /dev/null
+.*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'
--- /dev/null
+ .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
--- /dev/null
+#as: -march=rv32if -mcsr-check
+#source: priv-reg-fail-read-only-02.s
+#warning_output: priv-reg-fail-read-only-02.l
--- /dev/null
+.*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'
--- /dev/null
+# 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