[03/11] sim: riscv: Add floating-point CSR instructions

Message ID 20240226142234.1628932-4-bhushan.attarde@imgtec.com
State New
Headers
Series sim: riscv: simulation of single and double precision floating point instructions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 fail Testing failed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Bhushan Attarde Feb. 26, 2024, 2:22 p.m. UTC
  From: Bhushan Attarde <bhushan.attarde@imgtec.com>

Added simulation of following single precision floating-point instructions
frcsr, fscsr, frrm, fsrm, fsrmi, frflags, fsflags and fsflagsi.

Added test file sim/testsuite/riscv/f-csr.s to test these instructions.
---
 sim/riscv/sim-main.c        | 64 +++++++++++++++++++++++++++++++++++++
 sim/testsuite/riscv/f-csr.s | 56 ++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+)
 create mode 100644 sim/testsuite/riscv/f-csr.s
  

Patch

diff --git a/sim/riscv/sim-main.c b/sim/riscv/sim-main.c
index 9c132d9a448..0e873895f76 100644
--- a/sim/riscv/sim-main.c
+++ b/sim/riscv/sim-main.c
@@ -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:
diff --git a/sim/testsuite/riscv/f-csr.s b/sim/testsuite/riscv/f-csr.s
new file mode 100644
index 00000000000..c8f930b0d86
--- /dev/null
+++ b/sim/testsuite/riscv/f-csr.s
@@ -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