@@ -599,6 +599,21 @@ execute_i (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
riscv_cpu->regs[rs1]); \
break;
#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+ }
+ break;
+ case MATCH_CSRRWI:
+ TRACE_INSN (cpu, "csrrwi");
+ switch (csr)
+ {
+#define DECLARE_CSR(name, num, ...) \
+ case num: \
+ store_rd (cpu, rd, \
+ fetch_csr (cpu, #name, num, &riscv_cpu->csr.name)); \
+ store_csr (cpu, #name, num, &riscv_cpu->csr.name, \
+ rs1); \
+ break;
+#include "opcode/riscv-opc.h"
#undef DECLARE_CSR
}
break;
@@ -949,6 +964,54 @@ execute_f (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
case MATCH_FMAX_S:
float32_math (cpu, rd, rs1, rs2, FMAX);
break;
+ case MATCH_FRCSR:
+ TRACE_INSN (cpu, "frcsr %s;", rd_name);
+ store_rd (cpu, rd, riscv_cpu->csr.fcsr);
+ break;
+ case MATCH_FSCSR:
+ TRACE_INSN (cpu, "fscsr %s, %s;", rd_name, rs1_name);
+ store_rd (cpu, rd, riscv_cpu->csr.fcsr);
+ riscv_cpu->csr.fcsr = riscv_cpu->regs[rs1] & 0xff;
+ riscv_cpu->csr.frm = (riscv_cpu->regs[rs1] >> 5) & 0x7;
+ riscv_cpu->csr.fflags = riscv_cpu->regs[rs1] & 0x1f;
+ TRACE_REGISTER (cpu, "wrote CSR fcsr = %#" PRIxTW, riscv_cpu->regs[rs1]);
+ break;
+ case MATCH_FRRM:
+ TRACE_INSN (cpu, "frrm %s;", rd_name);
+ store_rd (cpu, rd, riscv_cpu->csr.frm);
+ break;
+ case MATCH_FSRM:
+ TRACE_INSN (cpu, "fsrm %s, %s;", rd_name, rs1_name);
+ store_rd (cpu, rd, riscv_cpu->csr.frm);
+ riscv_cpu->csr.frm = riscv_cpu->regs[rs1] & 0x7;
+ riscv_cpu->csr.fcsr |= (riscv_cpu->regs[rs1] & 0x7) << 5;
+ TRACE_REGISTER (cpu, "wrote CSR fcsr = %#" PRIxTW, riscv_cpu->csr.fcsr);
+ break;
+ case MATCH_FSRMI:
+ TRACE_INSN (cpu, "fsrmi %s, %x;", rd_name, rs1);
+ store_rd (cpu, rd, riscv_cpu->csr.frm);
+ riscv_cpu->csr.frm = rs1 & 0x7;
+ riscv_cpu->csr.fcsr |= (rs1 & 0x7) << 5;
+ TRACE_REGISTER (cpu, "wrote CSR fcsr = %#" PRIxTW, riscv_cpu->csr.fcsr);
+ break;
+ case MATCH_FRFLAGS:
+ TRACE_INSN (cpu, "frflags %s;", rd_name);
+ store_rd (cpu, rd, riscv_cpu->csr.fflags);
+ break;
+ case MATCH_FSFLAGS:
+ TRACE_INSN (cpu, "fsflags %s, %s;", rd_name, rs1_name);
+ store_rd (cpu, rd, riscv_cpu->csr.fflags);
+ riscv_cpu->csr.fflags = riscv_cpu->regs[rs1] & 0x1f;
+ riscv_cpu->csr.fcsr |= riscv_cpu->regs[rs1] & 0x1f;
+ TRACE_REGISTER (cpu, "wrote CSR fcsr = %#" PRIxTW, riscv_cpu->csr.fcsr);
+ break;
+ case MATCH_FSFLAGSI:
+ TRACE_INSN (cpu, "fsflagsi %s, %x;", rd_name, rs1);
+ store_rd (cpu, rd, riscv_cpu->csr.fflags);
+ riscv_cpu->csr.fflags = rs1 & 0x1f;
+ riscv_cpu->csr.fcsr |= rs1 & 0x1f;
+ TRACE_REGISTER (cpu, "wrote CSR fcsr = %#" PRIxTW, riscv_cpu->csr.fcsr);
+ break;
default:
TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
@@ -1592,6 +1655,7 @@ execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
case INSN_CLASS_F_INX:
return execute_f (cpu, iw, op);
case INSN_CLASS_I:
+ case INSN_CLASS_ZICSR:
return execute_i (cpu, iw, op);
case INSN_CLASS_M:
case INSN_CLASS_ZMMUL:
new file mode 100644
@@ -0,0 +1,56 @@
+# Floating-point CSR instructions tests
+# mach: riscv32 riscv64
+# sim(riscv32): --model RV32IF
+# sim(riscv64): --model RV64ID
+# ld(riscv32): -m elf32lriscv
+# ld(riscv64): -m elf64lriscv
+# as(riscv32): -march=rv32if
+# as(riscv64): -march=rv64id
+
+.include "testutils.inc"
+
+ start
+ # Test fscsr and frcsr instruction.
+ li a4,0x44 # mode:RDN, exception flags:OF
+ fscsr a5,a4
+ frcsr a6
+ bne a4,a6,test_fail
+
+ # Test rounding mode and flags read instruction.
+ li a4,0x2 # mode:RDN
+ frrm a5
+ bne a4,a5,test_fail
+ frflags a5
+ li a6,0x4 # exception flags:OF
+ bne a6,a5,test_fail
+
+ # Test swap rounding mode instruction.
+ li a6,0x7 # mode:Dynamic
+ fsrm a5,a6
+ bne a4,a5,test_fail # earlier mode should be RDN
+ frrm a5
+ bne a6,a5,test_fail # new mode should be Dynamic
+
+ # Test swap rounding mode with immediate value instruction.
+ fsrmi a5,0x2 # set new mode RDN (0x2)
+ frrm a5 # read the mode
+ li a6,0x2
+ bne a6,a5,test_fail # should be RDN (0x2)
+
+ # Test swap exception flags instruction.
+ li a6,0x8 # flag:Divide by zero
+ fsflags a5,a6
+ frflags a5
+ bne a5,a6,test_fail
+
+ # Test swap exception flags with immediate value instruction.
+ fsflagsi a5,0x2 # set new flag to underflow (0x2)
+ frflags a5 # read the flag
+ li a6,0x2
+ bne a5,a6,test_fail # should be underflow (0x2)
+
+test_pass:
+ pass
+
+test_fail:
+ fail