Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Jim Wilson <jimw@sifive.com>
To: gdb-patches@sourceware.org
Cc: Monk Chiang <monk@andestech.com>
Subject: [PATCH 06/24] RISC-V: Add fp support.
Date: Sat, 17 Apr 2021 10:58:13 -0700	[thread overview]
Message-ID: <20210417175831.16413-7-jimw@sifive.com> (raw)
In-Reply-To: <20210417175831.16413-1-jimw@sifive.com>

From: Monk Chiang <monk@andestech.com>

Add F and D instruction support.

	sim/riscv/
	* sim-main.c: Include sim-fpu.h.
	(store_frd, store_frd64, execute_d, execute_f): New functions.
	(execute_i): Call new execute functions.
	* sim-main.h (union FRegisterValue): New.
	(struct _sim_cpu): Change fpregs to use FRegisterValue.
---
 sim/riscv/sim-main.c | 662 +++++++++++++++++++++++++++++++++++++++++++++++++++
 sim/riscv/sim-main.h |  15 +-
 2 files changed, 676 insertions(+), 1 deletion(-)

diff --git a/sim/riscv/sim-main.c b/sim/riscv/sim-main.c
index 1b9fb89..de76089 100644
--- a/sim/riscv/sim-main.c
+++ b/sim/riscv/sim-main.c
@@ -27,6 +27,7 @@
 #include <time.h>
 
 #include "sim-main.h"
+#include "sim-fpu.h"
 #include "sim-syscall.h"
 
 #include "opcode/riscv.h"
@@ -72,6 +73,18 @@ store_rd (SIM_CPU *cpu, int rd, unsigned_word val)
     }
 }
 
+static INLINE void
+store_frd (SIM_CPU *cpu, int rd, unsigned_word val)
+{
+  cpu->fpregs[rd].w[0] = val;
+}
+
+static inline void
+store_frd64 (SIM_CPU *cpu, int rd, uint64_t val)
+{
+  cpu->fpregs[rd].v[0] = val;
+}
+
 static INLINE unsigned_word
 fetch_csr (SIM_CPU *cpu, const char *name, int csr, unsigned_word *reg)
 {
@@ -144,6 +157,651 @@ ashiftrt64 (unsigned_word val, unsigned_word shift)
 }
 
 static sim_cia
+execute_d (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  unsigned int mask_arithmetic = MASK_FADD_D;
+  unsigned int mask_mul_add = MASK_FMADD_S;
+  unsigned int mask_convert = MASK_FCVT_S_W;
+
+  static const int round_modes[] =
+  {
+      sim_fpu_round_near, sim_fpu_round_zero,
+      sim_fpu_round_down, sim_fpu_round_up,
+      sim_fpu_round_default, sim_fpu_round_default,
+      sim_fpu_round_default
+  };
+
+  int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
+  int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
+  int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
+  int rs3 = (iw >> OP_SH_RS3) & OP_MASK_RS3;
+  const char *frd_name = riscv_fpr_names_abi[rd];
+  const char *frs1_name = riscv_fpr_names_abi[rs1];
+  const char *frs2_name = riscv_fpr_names_abi[rs2];
+  const char *frs3_name = riscv_fpr_names_abi[rs3];
+  const char *rd_name = riscv_gpr_names_abi[rd];
+  const char *rs1_name = riscv_gpr_names_abi[rs1];
+  unsigned_word i_imm = EXTRACT_ITYPE_IMM (iw);
+  unsigned_word s_imm = EXTRACT_STYPE_IMM (iw);
+  uint32_t u32;
+  int32_t i32;
+  uint64_t u64;
+  int64_t i64;
+  sim_cia pc = cpu->pc + 4;
+
+  /* Rounding mode.  */
+  int rm = (iw >> OP_SH_RM) & OP_MASK_RM;
+  int rounding = round_modes[rm];
+
+  sim_fpu sft, sft2;
+  sim_fpu sfa, sfb, sfc;
+  sim_fpu_64to (&sfa, cpu->fpregs[rs1].v[0]);
+  sim_fpu_64to (&sfb, cpu->fpregs[rs2].v[0]);
+
+  switch (op->match & mask_mul_add)
+    {
+    case MATCH_FMADD_D:
+      TRACE_INSN (cpu, "fmadd.d %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_64to (&sfc, cpu->fpregs[rs3].v[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_add (&sft, &sfc, &sft2);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FMSUB_D:
+      TRACE_INSN (cpu, "fmsub.d %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_64to (&sfc, cpu->fpregs[rs3].v[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_sub (&sft, &sft2, &sfc);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FNMADD_D:
+      TRACE_INSN (cpu, "fnmadd.d %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_64to (&sfc, cpu->fpregs[rs3].v[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_add (&sft, &sfc, &sft2);
+      sim_fpu_neg (&sft, &sft);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FNMSUB_D:
+      TRACE_INSN (cpu, "fnmsub.d %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_64to (&sfc, cpu->fpregs[rs3].v[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_sub (&sft, &sft2, &sfc);
+      sim_fpu_neg (&sft, &sft);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    }
+
+  switch (op->match & mask_arithmetic)
+    {
+    case MATCH_FADD_D:
+      TRACE_INSN (cpu, "fadd.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_add (&sft, &sfa, &sfb);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FSUB_D:
+      TRACE_INSN (cpu, "fsub.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_sub (&sft, &sfa, &sfb);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FMUL_D:
+      TRACE_INSN (cpu, "fmul.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_mul (&sft, &sfa, &sfb);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FDIV_D:
+      TRACE_INSN (cpu, "fdiv.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_div (&sft, &sfa, &sfb);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FSQRT_D:
+      TRACE_INSN (cpu, "fsqrt.d %s, %s",
+		  frd_name, frs1_name);
+      sim_fpu_sqrt (&sft, &sfa);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    }
+
+  switch (op->match & mask_convert)
+    {
+    case MATCH_FCVT_W_D:
+      TRACE_INSN (cpu, "fcvt.w.d %s, %s",
+		  rd_name, frs1_name);
+      sim_fpu_to32i (&i32, &sfa, rounding);
+      cpu->regs[rd] = i32;
+      goto done;
+    case MATCH_FCVT_WU_D:
+      TRACE_INSN (cpu, "fcvt.wu.d %s, %s",
+		  rd_name, frs1_name);
+      sim_fpu_to32u (&u32, &sfa, rounding);
+      i32 = u32;
+      cpu->regs[rd] = i32;
+      goto done;
+    case MATCH_FCVT_D_W:
+      TRACE_INSN (cpu, "fcvt.d.w %s, %s",
+		  frd_name, rs1_name);
+      sim_fpu_i32to (&sft, cpu->regs[rs1], rounding);
+      sim_fpu_to64 ((unsigned64 *) (cpu->fpregs + rd), &sft);
+      goto done;
+    case MATCH_FCVT_D_WU:
+      TRACE_INSN (cpu, "fcvt.d.wu %s, %s",
+		  frd_name, rs1_name);
+      sim_fpu_u32to (&sft, cpu->regs[rs1], rounding);
+      sim_fpu_to64 ((unsigned64 *) (cpu->fpregs + rd), &sft);
+      goto done;
+    case MATCH_FCVT_S_D:
+      TRACE_INSN (cpu, "fcvt.s.d %s, %s",
+		  frd_name, frs1_name);
+      sft = sfa;
+      sim_fpu_round_32 (&sft, sim_fpu_round_near, sim_fpu_denorm_default);
+      sim_fpu_to32 ((unsigned32 *) (cpu -> fpregs + rd), &sft);
+      goto done;
+    case MATCH_FCVT_D_S:
+      TRACE_INSN (cpu, "fcvt.d.s %s, %s",
+		  frd_name, frs1_name);
+      sim_fpu_32to (&sft, cpu->fpregs[rs1].w[0]);
+      sim_fpu_to64 (&cpu->fpregs[rd].v[0], &sft);
+      goto done;
+    case MATCH_FCVT_L_D:
+      TRACE_INSN (cpu, "fcvt.l.d %s, %s",
+		  rd_name, frs1_name);
+      cpu->regs[rd] = (int64_t) cpu->fpregs[rs1].D[0];
+      goto done;
+    case MATCH_FCVT_LU_D:
+      TRACE_INSN (cpu, "fcvt.lu.d %s, %s",
+		  rd_name, frs1_name);
+      cpu->regs[rd] = (uint64_t) cpu->fpregs[rs1].D[0];
+      goto done;
+    case MATCH_FCVT_D_L:
+      TRACE_INSN (cpu, "fcvt.d.l %s, %s",
+		  frd_name, rs1_name);
+      cpu->fpregs[rd].D[0] = (double) ((int64_t) cpu->regs[rs1]);
+      goto done;
+    case MATCH_FCVT_D_LU:
+      TRACE_INSN (cpu, "fcvt.d.lu %s, %s",
+		  frd_name, rs1_name);
+      cpu->fpregs[rd].D[0] = (double) cpu->regs[rs1];
+      goto done;
+    }
+
+  switch (op->match)
+    {
+    case MATCH_FLD:
+      TRACE_INSN (cpu, "fld %s, %" PRIiTW "(%s)",
+		  frd_name, i_imm, rs1_name);
+      store_frd64 (cpu, rd,
+	sim_core_read_unaligned_8 (cpu, cpu->pc, read_map,
+				   cpu->regs[rs1] + i_imm));
+      break;
+    case MATCH_FSD:
+      TRACE_INSN (cpu, "fsd %s, %" PRIiTW "(%s)",
+		  frs2_name, s_imm, rs1_name);
+      sim_core_write_unaligned_8 (cpu, cpu->pc, write_map,
+				  cpu->regs[rs1] + s_imm,
+				  cpu->fpregs[rs2].v[0]);
+      break;
+    case MATCH_FSGNJ_D:
+      TRACE_INSN (cpu, "fsgnj.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      u32 = cpu->fpregs[rs1].w[1] & 0x7fffffff;
+      u32 |= cpu->fpregs[rs2].w[1] & 0x80000000;
+      cpu->fpregs[rd].w[1] = u32;
+      cpu->fpregs[rd].w[0] = cpu->fpregs[rs1].w[0];
+      break;
+    case MATCH_FSGNJN_D:
+      TRACE_INSN (cpu, "fsgnjn.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      u32 = cpu->fpregs[rs1].w[1] & 0x7fffffff;
+      u32 |= (cpu->fpregs[rs2].w[1] & 0x80000000) ^ 0x80000000;
+      cpu->fpregs[rd].w[1] = u32;
+      cpu->fpregs[rd].w[0] = cpu->fpregs[rs1].w[0];
+      break;
+    case MATCH_FSGNJX_D:
+      TRACE_INSN (cpu, "fsgnjx.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      u32 = cpu->fpregs[rs1].w[1] & 0x7fffffff;
+      u32 |= (cpu->fpregs[rs1].w[1] & 0x80000000) ^ (cpu->fpregs[rs2].w[1] & 0x80000000);
+      cpu->fpregs[rd].w[1] = u32;
+      cpu->fpregs[rd].w[0] = cpu->fpregs[rs1].w[0];
+      break;
+    case MATCH_FMIN_D:
+      TRACE_INSN (cpu, "fmin.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      if (cpu->fpregs[rs1].D[0] < cpu->fpregs[rs2].D[0])
+	cpu->fpregs[rd].D[0] = cpu->fpregs[rs1].D[0];
+      else
+	cpu->fpregs[rd].D[0] = cpu->fpregs[rs2].D[0];
+      break;
+    case MATCH_FMAX_D:
+      TRACE_INSN (cpu, "fmax.d %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      if (cpu->fpregs[rs1].D[0] > cpu->fpregs[rs2].D[0])
+	cpu->fpregs[rd].D[0] = cpu->fpregs[rs1].D[0];
+      else
+	cpu->fpregs[rd].D[0] = cpu->fpregs[rs2].D[0];
+      break;
+    case MATCH_FMV_X_D:
+      TRACE_INSN (cpu, "fmv.x.d %s, %s",
+		  rd_name, frs1_name);
+      cpu->regs[rd] = cpu->fpregs[rs1].v[0];
+      break;
+    case MATCH_FMV_D_X:
+      TRACE_INSN (cpu, "fmv.d.x %s, %s",
+		  frd_name, frs1_name);
+      cpu->fpregs[rd].v[0] = cpu->regs[rs1];
+      break;
+    case MATCH_FEQ_D:
+      TRACE_INSN (cpu, "feq.d %s, %s, %s",
+		  rd_name, frs1_name, frs2_name);
+      cpu->regs[rd] = sim_fpu_is_eq (&sfa, &sfb);
+      break;
+    case MATCH_FLE_D:
+      TRACE_INSN (cpu, "fle.d %s, %s, %s",
+		  rd_name, frs1_name, frs2_name);
+      cpu->regs[rd] = sim_fpu_is_le (&sfa, &sfb);
+      break;
+    case MATCH_FLT_D:
+      TRACE_INSN (cpu, "flt.d %s, %s, %s",
+		  rd_name, frs1_name, frs2_name);
+      cpu->regs[rd] = sim_fpu_is_lt (&sfa, &sfb);
+      break;
+    case MATCH_FCLASS_D:
+      TRACE_INSN (cpu, "fclass.d %s, %s",
+		  rd_name, frs1_name);
+      switch (sim_fpu_is (&sfa))
+	{
+	case SIM_FPU_IS_NINF:
+	  cpu->regs[rd] = 1;
+	  break;
+	case SIM_FPU_IS_NNUMBER:
+	  cpu->regs[rd] = 1 << 1;
+	  break;
+	case SIM_FPU_IS_NDENORM:
+	  cpu->regs[rd] = 1 << 2;
+	  break;
+	case SIM_FPU_IS_NZERO:
+	  cpu->regs[rd] = 1 << 3;
+	  break;
+	case SIM_FPU_IS_PZERO:
+	  cpu->regs[rd] = 1 << 4;
+	  break;
+	case SIM_FPU_IS_PDENORM:
+	  cpu->regs[rd] = 1 << 5;
+	  break;
+	case SIM_FPU_IS_PNUMBER:
+	  cpu->regs[rd] = 1 << 6;
+	  break;
+	case SIM_FPU_IS_PINF:
+	  cpu->regs[rd] = 1 << 7;
+	  break;
+	case SIM_FPU_IS_SNAN:
+	  cpu->regs[rd] = 1 << 8;
+	  break;
+	case SIM_FPU_IS_QNAN:
+	  cpu->regs[rd] = 1 << 9;
+	  break;
+	}
+      break;
+    default:
+      TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
+      sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
+    }
+
+ done:
+  return pc;
+
+}
+
+static sim_cia
+execute_f (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
+{
+  SIM_DESC sd = CPU_STATE (cpu);
+  unsigned int mask_arithmetic = MASK_FADD_S;
+  unsigned int mask_mul_add = MASK_FMADD_S;
+  unsigned int mask_convert = MASK_FCVT_S_W;
+
+  static const int round_modes[] =
+  {
+      sim_fpu_round_near, sim_fpu_round_zero,
+      sim_fpu_round_down, sim_fpu_round_up,
+      sim_fpu_round_default, sim_fpu_round_default,
+      sim_fpu_round_default
+  };
+
+  int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
+  int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
+  int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
+  int rs3 = (iw >> OP_SH_RS3) & OP_MASK_RS3;
+  const char *frd_name = riscv_fpr_names_abi[rd];
+  const char *frs1_name = riscv_fpr_names_abi[rs1];
+  const char *frs2_name = riscv_fpr_names_abi[rs2];
+  const char *frs3_name = riscv_fpr_names_abi[rs3];
+  const char *rd_name = riscv_gpr_names_abi[rd];
+  const char *rs1_name = riscv_gpr_names_abi[rs1];
+  unsigned_word i_imm = EXTRACT_ITYPE_IMM (iw);
+  unsigned_word s_imm = EXTRACT_STYPE_IMM (iw);
+  uint32_t u32;
+  int32_t i32;
+  int64_t i64;
+  uint64_t u64;
+  sim_cia pc = cpu->pc + 4;
+
+  /* Rounding mode.  */
+  int rm = (iw >> OP_SH_RM) & OP_MASK_RM;
+  int rounding = round_modes[rm];
+
+  sim_fpu sft, sft2;
+  sim_fpu sfa, sfb, sfc;
+  sim_fpu_32to (&sfa, cpu->fpregs[rs1].w[0]);
+  sim_fpu_32to (&sfb, cpu->fpregs[rs2].w[0]);
+
+  switch (op->match & mask_mul_add)
+    {
+    case MATCH_FMADD_S:
+      TRACE_INSN (cpu, "fmadd.s %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_32to (&sfc, cpu->fpregs[rs3].w[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_add (&sft, &sfc, &sft2);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FMSUB_S:
+      TRACE_INSN (cpu, "fmsub.s %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_32to (&sfc, cpu->fpregs[rs3].w[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_sub (&sft, &sft2, &sfc);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FNMADD_S:
+      TRACE_INSN (cpu, "fnmadd.s %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_32to (&sfc, cpu->fpregs[rs3].w[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_add (&sft, &sfc, &sft2);
+      sim_fpu_neg (&sft, &sft);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FNMSUB_S:
+      TRACE_INSN (cpu, "fnmsub.s %s, %s, %s, %s",
+		  frd_name, frs1_name, frs2_name, frs3_name);
+      sim_fpu_32to (&sfc, cpu->fpregs[rs3].w[0]);
+      sim_fpu_mul (&sft2, &sfa, &sfb);
+      sim_fpu_sub (&sft, &sft2, &sfc);
+      sim_fpu_neg (&sft, &sft);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    }
+
+  switch (op->match & mask_arithmetic)
+    {
+    case MATCH_FADD_S:
+      TRACE_INSN (cpu, "fadd.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_add (&sft, &sfa, &sfb);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FSUB_S:
+      TRACE_INSN (cpu, "fsub.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_sub (&sft, &sfa, &sfb);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FMUL_S:
+      TRACE_INSN (cpu, "fmul.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_mul (&sft, &sfa, &sfb);
+      sim_fpu_round_64 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FDIV_S:
+      TRACE_INSN (cpu, "fdiv.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_div (&sft, &sfa, &sfb);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    case MATCH_FSQRT_S:
+      TRACE_INSN (cpu, "fsqrt.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      sim_fpu_sqrt (&sft, &sfa);
+      sim_fpu_to32 (&cpu->fpregs[rd].w[0], &sft);
+      goto done;
+    }
+
+  switch (op->match & mask_convert)
+    {
+    case MATCH_FCVT_W_S:
+      TRACE_INSN (cpu, "fcvt.w.s %s, %s",
+		  rd_name, frs1_name);
+      sim_fpu_to32i (&i32, &sfa, rounding);
+      cpu->regs[rd] = i32;
+      goto done;
+    case MATCH_FCVT_WU_S:
+      TRACE_INSN (cpu, "fcvt.wu.s %s, %s",
+		  rd_name, frs1_name);
+      sim_fpu_to32u (&u32, &sfa, rounding);
+      i32 = u32;
+      cpu->regs[rd] = i32;
+      goto done;
+    case MATCH_FCVT_S_W:
+      TRACE_INSN (cpu, "fcvt.s.w %s, %s",
+		  frd_name, rs1_name);
+      sim_fpu_i32to (&sft, cpu->regs[rs1], rounding);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 ((unsigned32 *) (cpu->fpregs + rd), &sft);
+      goto done;
+    case MATCH_FCVT_S_WU:
+      TRACE_INSN (cpu, "fcvt.s.wu %s, %s",
+		  frd_name, rs1_name);
+      sim_fpu_u32to (&sft, cpu->regs[rs1], rounding);
+      sim_fpu_round_32 (&sft, rounding, sim_fpu_denorm_default);
+      sim_fpu_to32 ((unsigned32 *) (cpu->fpregs + rd), &sft);
+      goto done;
+    case MATCH_FCVT_L_S:
+      TRACE_INSN (cpu, "fcvt.l.s %s, %s",
+		  rd_name, frs1_name);
+      cpu->regs[rd] = (int64_t) cpu->fpregs[rs1].S[0];
+      goto done;
+    case MATCH_FCVT_LU_S:
+      TRACE_INSN (cpu, "fcvt.lu.s %s, %s",
+		  rd_name, frs1_name);
+      cpu->regs[rd] = (uint64_t) cpu->fpregs[rs1].S[0];
+      goto done;
+    case MATCH_FCVT_S_L:
+      TRACE_INSN (cpu, "fcvt.s.l %s, %s",
+		  frd_name, rs1_name);
+      cpu->fpregs[rd].S[0] = (float) ((int64_t) cpu->regs[rs1]);
+      goto done;
+    case MATCH_FCVT_S_LU:
+      TRACE_INSN (cpu, "fcvt.s.lu %s, %s",
+		  frd_name, rs1_name);
+      cpu->fpregs[rd].S[0] = (float) cpu->regs[rs1];
+      goto done;
+    }
+
+  switch (op->match)
+    {
+    case MATCH_FLW:
+      TRACE_INSN (cpu, "flw %s, %" PRIiTW "(%s)",
+		  frd_name, i_imm, rs1_name);
+      store_frd (cpu, rd, EXTEND32 (
+	sim_core_read_unaligned_4 (cpu, cpu->pc, read_map,
+				   cpu->regs[rs1] + i_imm)));
+      break;
+    case MATCH_FSW:
+      TRACE_INSN (cpu, "fsw %s, %" PRIiTW "(%s)",
+		  frs2_name, s_imm, rs1_name);
+      sim_core_write_unaligned_4 (cpu, cpu->pc, write_map,
+				  cpu->regs[rs1] + s_imm, cpu->fpregs[rs2].w[0]);
+      break;
+    case MATCH_FSGNJ_S:
+      TRACE_INSN (cpu, "fsgnj.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      u32 = cpu->fpregs[rs1].w[0] & 0x7fffffff;
+      u32 |= cpu->fpregs[rs2].w[0] & 0x80000000;
+      cpu->fpregs[rd].w[0] = u32;
+      break;
+    case MATCH_FSGNJN_S:
+      TRACE_INSN (cpu, "fsgnjn.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      u32 = cpu->fpregs[rs1].w[0] & 0x7fffffff;
+      u32 |= (cpu->fpregs[rs2].w[0] & 0x80000000) ^ 0x80000000;
+      cpu->fpregs[rd].w[0] = u32;
+      break;
+    case MATCH_FSGNJX_S:
+      TRACE_INSN (cpu, "fsgnx.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      u32 = cpu->fpregs[rs1].w[0] & 0x7fffffff;
+      u32 |= (cpu->fpregs[rs1].w[0] & 0x80000000) ^ (cpu->fpregs[rs2].w[0] & 0x80000000);
+      cpu->fpregs[rd].w[0] = u32;
+      break;
+    case MATCH_FMIN_S:
+      TRACE_INSN (cpu, "fmin.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      if (cpu->fpregs[rs1].S[0] < cpu->fpregs[rs2].S[0])
+	cpu->fpregs[rd].S[0] = cpu->fpregs[rs1].S[0];
+      else
+	cpu->fpregs[rd].S[0] = cpu->fpregs[rs2].S[0];
+      break;
+    case MATCH_FMAX_S:
+      TRACE_INSN (cpu, "fmax.s %s, %s, %s",
+		  frd_name, frs1_name, frs2_name);
+      if (cpu->fpregs[rs1].S[0] > cpu->fpregs[rs2].S[0])
+	cpu->fpregs[rd].S[0] = cpu->fpregs[rs1].S[0];
+      else
+	cpu->fpregs[rd].S[0] = cpu->fpregs[rs2].S[0];
+      break;
+    case MATCH_FMV_X_S:
+      TRACE_INSN (cpu, "fmv.x.s %s, %s",
+		  rd_name, frs1_name);
+      cpu->regs[rd] = cpu->fpregs[rs1].W[0];
+      break;
+    case MATCH_FMV_S_X:
+      TRACE_INSN (cpu, "fmv.s.x %s, %s",
+		  frd_name, rs1_name);
+      cpu->fpregs[rd].w[0] = cpu->regs[rs1];
+      break;
+    case MATCH_FEQ_S:
+      TRACE_INSN (cpu, "feq.s %s, %s, %s",
+		  rd_name, frs1_name, frs2_name);
+      cpu->regs[rd] = sim_fpu_is_eq (&sfa, &sfb);
+      break;
+    case MATCH_FLE_S:
+      TRACE_INSN (cpu, "fle.s %s, %s, %s",
+		  rd_name, frs1_name, frs2_name);
+      cpu->regs[rd] = sim_fpu_is_le (&sfa, &sfb);
+      break;
+    case MATCH_FLT_S:
+      TRACE_INSN (cpu, "flt.s %s, %s, %s",
+		  rd_name, frs1_name, frs2_name);
+      cpu->regs[rd] = sim_fpu_is_lt (&sfa, &sfb);
+      break;
+    case MATCH_FCLASS_S:
+      TRACE_INSN (cpu, "fclass.s %s, %s",
+		  rd_name, frs1_name);
+      switch (sim_fpu_is (&sfa))
+	{
+	case SIM_FPU_IS_NINF:
+	  cpu->regs[rd] = 1;
+	  break;
+	case SIM_FPU_IS_NNUMBER:
+	  cpu->regs[rd] = 1 << 1;
+	  break;
+	case SIM_FPU_IS_NDENORM:
+	  cpu->regs[rd] = 1 << 2;
+	  break;
+	case SIM_FPU_IS_NZERO:
+	  cpu->regs[rd] = 1 << 3;
+	  break;
+	case SIM_FPU_IS_PZERO:
+	  cpu->regs[rd] = 1 << 4;
+	  break;
+	case SIM_FPU_IS_PDENORM:
+	  cpu->regs[rd] = 1 << 5;
+	  break;
+	case SIM_FPU_IS_PNUMBER:
+	  cpu->regs[rd] = 1 << 6;
+	  break;
+	case SIM_FPU_IS_PINF:
+	  cpu->regs[rd] = 1 << 7;
+	  break;
+	case SIM_FPU_IS_SNAN:
+	  cpu->regs[rd] = 1 << 8;
+	  break;
+	case SIM_FPU_IS_QNAN:
+	  cpu->regs[rd] = 1 << 9;
+	  break;
+	}
+      break;
+    case MATCH_FRCSR:
+      TRACE_INSN (cpu, "frcsr %s",
+		  rd_name);
+      store_rd (cpu, rd, fetch_csr (cpu, "fcsr", CSR_FCSR, &cpu->csr.fcsr));
+      break;
+    case MATCH_FSCSR:
+      TRACE_INSN (cpu, "fscsr %s, %sf",
+		  rd_name, rs1_name);
+      store_rd (cpu, rd, fetch_csr (cpu, "fcsr", CSR_FCSR, &cpu->csr.fcsr));
+      store_csr (cpu, "fcsr", CSR_FCSR, &cpu->csr.fcsr, cpu->regs[rs1]);
+      break;
+    case MATCH_FRRM:
+      TRACE_INSN (cpu, "frrm %s",
+		  rd_name);
+      store_rd (cpu, rd, fetch_csr (cpu, "frm", CSR_FRM, &cpu->csr.frm));
+      break;
+    case MATCH_FSRM:
+      TRACE_INSN (cpu, "fsrm %s, %s",
+		  rd_name, rs1_name);
+      store_rd (cpu, rd, fetch_csr (cpu, "frm", CSR_FCSR, &cpu->csr.frm));
+      store_csr (cpu, "frm", CSR_FCSR, &cpu->csr.frm, cpu->regs[rs1]);
+      break;
+    case MATCH_FRFLAGS:
+      TRACE_INSN (cpu, "frflags %s",
+		  rd_name);
+      store_rd (cpu, rd, fetch_csr (cpu, "fflags", CSR_FFLAGS, &cpu->csr.fflags));
+      break;
+    case MATCH_FSFLAGS:
+      TRACE_INSN (cpu, "fsflags %s, %s",
+		  rd_name, frs1_name);
+      store_rd (cpu, rd, fetch_csr (cpu, "fflags", CSR_FFLAGS, &cpu->csr.fflags));
+      store_csr (cpu, "fflags", CSR_FFLAGS, &cpu->csr.fflags, cpu->regs[rs1]);
+      break;
+    default:
+      TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
+      sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
+    }
+
+ done:
+  return pc;
+}
+
+static sim_cia
 execute_i (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
 {
   SIM_DESC sd = CPU_STATE (cpu);
@@ -960,6 +1618,10 @@ execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
       return execute_i (cpu, iw, op);
     case INSN_CLASS_M:
       return execute_m (cpu, iw, op);
+    case INSN_CLASS_D:
+      return execute_d (cpu, iw, op);
+    case INSN_CLASS_F:
+      return execute_f (cpu, iw, op);
     case INSN_CLASS_ZIFENCEI:
       return execute_zifencei (cpu, iw, op);
     default:
diff --git a/sim/riscv/sim-main.h b/sim/riscv/sim-main.h
index 4a1b31e..e53794f 100644
--- a/sim/riscv/sim-main.h
+++ b/sim/riscv/sim-main.h
@@ -25,6 +25,19 @@
 #include "machs.h"
 #include "sim-base.h"
 
+typedef union FRegisterValue
+{
+  uint64_t     v[2];
+  uint32_t     w[4];
+
+  int64_t      V[2];
+  int32_t      W[4];
+
+  float        S[4];
+  double       D[2];
+
+} FRegister;
+
 struct _sim_cpu {
   union {
     unsigned_word regs[32];
@@ -39,7 +52,7 @@ struct _sim_cpu {
     };
   };
   union {
-    unsigned_word fpregs[32];
+    FRegister fpregs[32];
     struct {
       /* These are the ABI names.  */
       unsigned_word ft0, ft1, ft2, ft3, ft4, ft5, ft6, ft7;
-- 
2.7.4


  parent reply	other threads:[~2021-04-17 17:59 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-17 17:58 [PATCH 00/24] RISC-V sim: Update from riscv-gnu-toolchain Jim Wilson
2021-04-17 17:58 ` [PATCH 01/24] RISC-V sim: Fix fence.i Jim Wilson
2021-04-17 20:36   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 02/24] RISC-V sim: Fix for jalr Jim Wilson
2021-04-19  3:41   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 03/24] RISC-V sim: Atomic fixes Jim Wilson
2021-04-19  3:56   ` Mike Frysinger via Gdb-patches
2021-04-21 23:00     ` Jim Wilson
2021-04-22  0:09       ` Mike Frysinger via Gdb-patches
2021-04-22  3:12         ` Jim Wilson
2021-04-17 17:58 ` [PATCH 04/24] RISC-V sim: More atomic fixes Jim Wilson
2021-04-19  3:57   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 05/24] RISC-V sim: Fix stack pointer alignment Jim Wilson
2021-04-19  3:58   ` Mike Frysinger via Gdb-patches
2021-04-21 22:39     ` Jim Wilson
2021-04-17 17:58 ` Jim Wilson [this message]
2021-04-19  4:08   ` [PATCH 06/24] RISC-V: Add fp support Mike Frysinger via Gdb-patches
2021-04-21 23:34     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 07/24] RISC-V sim: Add link syscall support Jim Wilson
2021-04-19  4:09   ` Mike Frysinger via Gdb-patches
2021-04-21 23:36     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 08/24] RISC-V sim: Add brk syscall Jim Wilson
2021-04-19  5:24   ` Mike Frysinger via Gdb-patches
2021-04-21 23:51     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 09/24] RISC-V sim: Fix syscall fallback Jim Wilson
2021-04-21 23:38   ` Jim Wilson
2021-04-22  3:23     ` Mike Frysinger via Gdb-patches
2021-04-23 20:35       ` Jim Wilson
2021-04-17 17:58 ` [PATCH 10/24] RISC-V sim: Fix ebreak Jim Wilson
2021-04-19  4:20   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 11/24] RISC-V sim: Fix ebreak, part 2 Jim Wilson
2021-04-19  4:20   ` Mike Frysinger via Gdb-patches
2021-04-21 23:41     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 12/24] RISC-V sim: Add compressed support Jim Wilson
2021-04-19  4:13   ` Mike Frysinger via Gdb-patches
2021-04-21 23:42     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 13/24] RISC-V sim: Add gettimeofday Jim Wilson
2021-04-19  4:19   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 14/24] RISC-V sim: Add csrr*i instructions Jim Wilson
2021-04-19  4:26   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 15/24] RISC-V sim: Improve cycle and instret counts Jim Wilson
2021-04-19  4:25   ` Mike Frysinger via Gdb-patches
2021-04-22  2:26     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 16/24] RISC-V sim: Check sbrk argument Jim Wilson
2021-04-19  5:33   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 17/24] RISC-V sim: Fix tracing typo Jim Wilson
2021-04-19  4:26   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 18/24] RISC-V sim: Improve branch tracing Jim Wilson
2021-04-19  4:27   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 19/24] RISC-V sim: Improve tracing for slt* instructions Jim Wilson
2021-04-19  4:27   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 20/24] RISC-V sim: Set brk to _end if possible Jim Wilson
2021-04-19  5:41   ` Mike Frysinger via Gdb-patches
2021-04-22  2:45     ` Jim Wilson
2021-04-17 17:58 ` [PATCH 21/24] RISC-V sim: Fix mingw builds Jim Wilson
2021-04-19  4:12   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 22/24] RISC-V sim: Support compressed FP instructions Jim Wilson
2021-04-19  4:27   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 23/24] RISC-V sim: Add zicsr support Jim Wilson
2021-04-19  5:13   ` Mike Frysinger via Gdb-patches
2021-04-17 17:58 ` [PATCH 24/24] RISC-V sim: Fix divw and remw Jim Wilson
2021-04-19  5:10   ` Mike Frysinger via Gdb-patches
2021-04-17 20:38 ` [PATCH 00/24] RISC-V sim: Update from riscv-gnu-toolchain Mike Frysinger via Gdb-patches
2021-04-19  2:33   ` Jim Wilson
2021-04-19  3:23     ` Mike Frysinger via Gdb-patches
2021-04-19  4:32       ` Jim Wilson
2021-04-19  3:42 ` Mike Frysinger via Gdb-patches
2021-04-19  4:37   ` Jim Wilson
2021-04-21 15:47 ` Andrew Burgess
2021-04-21 17:49   ` Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210417175831.16413-7-jimw@sifive.com \
    --to=jimw@sifive.com \
    --cc=gdb-patches@sourceware.org \
    --cc=monk@andestech.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox