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
next prev 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