https://groups.google.com/a/groups.riscv.org/d/msg/isa-dev/_r7hBlzsEd8/cWPyJKMzCQAJ
#include "encoding.h"
#include "config.h"
#include "common.h"
+#include "softfloat_types.h"
+#include "specialize.h"
#include <cinttypes>
typedef int64_t sreg_t;
typedef uint64_t reg_t;
-typedef uint64_t freg_t;
const int NXPR = 32;
const int NFPR = 32;
#ifndef RISCV_ENABLE_COMMITLOG
# define WRITE_REG(reg, value) STATE.XPR.write(reg, value)
-# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, value)
+# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, freg(value))
#else
# define WRITE_REG(reg, value) ({ \
reg_t wdata = (value); /* value may have side effects */ \
STATE.XPR.write(reg, wdata); \
})
# define WRITE_FREG(reg, value) ({ \
- freg_t wdata = (value); /* value may have side effects */ \
+ freg_t wdata = freg(value); /* value may have side effects */ \
STATE.log_reg_write = (commit_log_reg_t){((reg) << 1) | 1, wdata}; \
DO_WRITE_FREG(reg, wdata); \
})
#define invalid_pc(pc) ((pc) & 1)
/* Convenience wrappers to simplify softfloat code sequences */
-#define f32(x) ((float32_t){(uint32_t)x})
-#define f64(x) ((float64_t){(uint64_t)x})
+#define isBoxedF32(r) (((r) & 0xffffffff00000000) == 0xffffffff00000000)
+#define unboxF32(r) (isBoxedF32(r) ? (r) : defaultNaNF32UI)
+#define unboxF64(r) (r)
+struct freg_t { uint64_t v; };
+inline float32_t f32(uint32_t v) { return { v }; }
+inline float64_t f64(uint64_t v) { return { v }; }
+inline float32_t f32(freg_t r) { return f32(unboxF32(r.v)); }
+inline float64_t f64(freg_t r) { return f64(unboxF64(r.v)); }
+inline freg_t freg(float32_t f) { return { ((decltype(freg_t::v))-1 << 32) | f.v }; }
+inline freg_t freg(float64_t f) { return { f.v }; }
+inline freg_t freg(freg_t f) { return f; }
+#define F64_SIGN ((decltype(freg_t::v))1 << 63)
+#define F32_SIGN ((decltype(freg_t::v))1 << 31)
+#define fsgnj32(a, b, n, x) \
+ f32((f32(a).v & ~F32_SIGN) | ((((x) ? f32(a).v : (n) ? F32_SIGN : 0) ^ f32(b).v) & F32_SIGN))
+#define fsgnj64(a, b, n, x) \
+ f64((f64(a).v & ~F64_SIGN) | ((((x) ? f64(a).v : (n) ? F64_SIGN : 0) ^ f64(b).v) & F64_SIGN))
#define validate_csr(which, write) ({ \
if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \
require_extension('C');
require_extension('D');
require_fp;
-WRITE_RVC_FRS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
+WRITE_RVC_FRS2S(f64(MMU.load_uint64(RVC_RS1S + insn.rvc_ld_imm())));
require_extension('C');
require_extension('D');
require_fp;
-WRITE_FRD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
+WRITE_FRD(f64(MMU.load_uint64(RVC_SP + insn.rvc_ldsp_imm())));
if (xlen == 32) {
require_extension('F');
require_fp;
- WRITE_RVC_FRS2S(MMU.load_int32(RVC_RS1S + insn.rvc_lw_imm()));
+ WRITE_RVC_FRS2S(f32(MMU.load_uint32(RVC_RS1S + insn.rvc_lw_imm())));
} else { // c.ld
WRITE_RVC_RS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
}
if (xlen == 32) {
require_extension('F');
require_fp;
- WRITE_FRD(MMU.load_int32(RVC_SP + insn.rvc_lwsp_imm()));
+ WRITE_FRD(f32(MMU.load_uint32(RVC_SP + insn.rvc_lwsp_imm())));
} else { // c.ldsp
require(insn.rvc_rd() != 0);
WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
require_extension('C');
require_extension('D');
require_fp;
-MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S);
+MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v);
require_extension('C');
require_extension('D');
require_fp;
-MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2);
+MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v);
if (xlen == 32) {
require_extension('F');
require_fp;
- MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S);
+ MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v);
} else { // c.sd
MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
}
if (xlen == 32) {
require_extension('F');
require_fp;
- MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2);
+ MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v);
} else { // c.sdsp
MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2);
}
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_add(f64(FRS1), f64(FRS2)).v);
+WRITE_FRD(f64_add(f64(FRS1), f64(FRS2)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_add(f32(FRS1), f32(FRS2)).v);
+WRITE_FRD(f32_add(f32(FRS1), f32(FRS2)));
set_fp_exceptions;
require_rv64;
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(i64_to_f64(RS1).v);
+WRITE_FRD(i64_to_f64(RS1));
set_fp_exceptions;
require_rv64;
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(ui64_to_f64(RS1).v);
+WRITE_FRD(ui64_to_f64(RS1));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_to_f64(f32(FRS1)).v);
+WRITE_FRD(f32_to_f64(f32(FRS1)));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(i32_to_f64((int32_t)RS1).v);
+WRITE_FRD(i32_to_f64((int32_t)RS1));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(ui32_to_f64((uint32_t)RS1).v);
+WRITE_FRD(ui32_to_f64((uint32_t)RS1));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_to_f32(f64(FRS1)).v);
+WRITE_FRD(f64_to_f32(f64(FRS1)));
set_fp_exceptions;
require_rv64;
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(i64_to_f32(RS1).v);
+WRITE_FRD(i64_to_f32(RS1));
set_fp_exceptions;
require_rv64;
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(ui64_to_f32(RS1).v);
+WRITE_FRD(ui64_to_f32(RS1));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(i32_to_f32((int32_t)RS1).v);
+WRITE_FRD(i32_to_f32((int32_t)RS1));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(ui32_to_f32((uint32_t)RS1).v);
+WRITE_FRD(ui32_to_f32((uint32_t)RS1));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_div(f64(FRS1), f64(FRS2)).v);
+WRITE_FRD(f64_div(f64(FRS1), f64(FRS2)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_div(f32(FRS1), f32(FRS2)).v);
+WRITE_FRD(f32_div(f32(FRS1), f32(FRS2)));
set_fp_exceptions;
require_extension('D');
require_fp;
-WRITE_FRD(MMU.load_int64(RS1 + insn.i_imm()));
+WRITE_FRD(f64(MMU.load_uint64(RS1 + insn.i_imm())));
require_extension('F');
require_fp;
-WRITE_FRD(MMU.load_uint32(RS1 + insn.i_imm()));
+WRITE_FRD(f32(MMU.load_uint32(RS1 + insn.i_imm())));
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3)).v);
+WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3)).v);
+WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3)));
set_fp_exceptions;
require_extension('D');
require_fp;
-WRITE_FRD(f64_le_quiet(f64(FRS2), f64(FRS1)) || isNaNF64UI(FRS2) ? FRS1 : FRS2);
-if ((isNaNF64UI(FRS1) && isNaNF64UI(FRS2)) || softfloat_exceptionFlags)
- WRITE_FRD(defaultNaNF64UI);
+WRITE_FRD(f64_le_quiet(f64(FRS2), f64(FRS1)) || isNaNF64UI(f64(FRS2).v) ? FRS1 : FRS2);
+if ((isNaNF64UI(f64(FRS1).v) && isNaNF64UI(f64(FRS2).v)) || softfloat_exceptionFlags)
+ WRITE_FRD(f64(defaultNaNF64UI));
set_fp_exceptions;
require_extension('F');
require_fp;
-WRITE_FRD(f32_le_quiet(f32(FRS2), f32(FRS1)) || isNaNF32UI(FRS2) ? FRS1 : FRS2);
-if ((isNaNF32UI(FRS1) && isNaNF32UI(FRS2)) || softfloat_exceptionFlags)
- WRITE_FRD(defaultNaNF32UI);
+WRITE_FRD(f32_le_quiet(f32(FRS2), f32(FRS1)) || isNaNF32UI(f32(FRS2).v) ? FRS1 : FRS2);
+if ((isNaNF32UI(f32(FRS1).v) && isNaNF32UI(f32(FRS2).v)) || softfloat_exceptionFlags)
+ WRITE_FRD(f32(defaultNaNF32UI));
set_fp_exceptions;
require_extension('D');
require_fp;
-WRITE_FRD(f64_lt_quiet(f64(FRS1), f64(FRS2)) || isNaNF64UI(FRS2) ? FRS1 : FRS2);
-if ((isNaNF64UI(FRS1) && isNaNF64UI(FRS2)) || softfloat_exceptionFlags)
- WRITE_FRD(defaultNaNF64UI);
+WRITE_FRD(f64_lt_quiet(f64(FRS1), f64(FRS2)) || isNaNF64UI(f64(FRS2).v) ? FRS1 : FRS2);
+if ((isNaNF64UI(f64(FRS1).v) && isNaNF64UI(f64(FRS2).v)) || softfloat_exceptionFlags)
+ WRITE_FRD(f64(defaultNaNF64UI));
set_fp_exceptions;
require_extension('F');
require_fp;
-WRITE_FRD(f32_lt_quiet(f32(FRS1), f32(FRS2)) || isNaNF32UI(FRS2) ? FRS1 : FRS2);
-if ((isNaNF32UI(FRS1) && isNaNF32UI(FRS2)) || softfloat_exceptionFlags)
- WRITE_FRD(defaultNaNF32UI);
+WRITE_FRD(f32_lt_quiet(f32(FRS1), f32(FRS2)) || isNaNF32UI(f32(FRS2).v) ? FRS1 : FRS2);
+if ((isNaNF32UI(f32(FRS1).v) && isNaNF32UI(f32(FRS2).v)) || softfloat_exceptionFlags)
+ WRITE_FRD(f32(defaultNaNF32UI));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3 ^ (uint64_t)INT64_MIN)).v);
+WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(f64(FRS3).v ^ F64_SIGN)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3 ^ (uint32_t)INT32_MIN)).v);
+WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(f32(FRS3).v ^ F32_SIGN)));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_mul(f64(FRS1), f64(FRS2)).v);
+WRITE_FRD(f64_mul(f64(FRS1), f64(FRS2)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_mul(f32(FRS1), f32(FRS2)).v);
+WRITE_FRD(f32_mul(f32(FRS1), f32(FRS2)));
set_fp_exceptions;
require_extension('D');
require_rv64;
require_fp;
-WRITE_FRD(RS1);
+WRITE_FRD(f64(RS1));
require_extension('F');
require_fp;
-WRITE_FRD(zext32(RS1));
+WRITE_FRD(f32(RS1));
require_extension('D');
require_rv64;
require_fp;
-WRITE_RD(FRS1);
+WRITE_RD(FRS1.v);
require_extension('F');
require_fp;
-WRITE_RD(sext32(FRS1));
+WRITE_RD(sext32(FRS1.v));
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_mulAdd(f64(FRS1 ^ (uint64_t)INT64_MIN), f64(FRS2), f64(FRS3 ^ (uint64_t)INT64_MIN)).v);
+WRITE_FRD(f64_mulAdd(f64(f64(FRS1).v ^ F64_SIGN), f64(FRS2), f64(f64(FRS3).v ^ F64_SIGN)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_mulAdd(f32(FRS1 ^ (uint32_t)INT32_MIN), f32(FRS2), f32(FRS3 ^ (uint32_t)INT32_MIN)).v);
+WRITE_FRD(f32_mulAdd(f32(f32(FRS1).v ^ F32_SIGN), f32(FRS2), f32(f32(FRS3).v ^ F32_SIGN)));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_mulAdd(f64(FRS1 ^ (uint64_t)INT64_MIN), f64(FRS2), f64(FRS3)).v);
+WRITE_FRD(f64_mulAdd(f64(f64(FRS1).v ^ F64_SIGN), f64(FRS2), f64(FRS3)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_mulAdd(f32(FRS1 ^ (uint32_t)INT32_MIN), f32(FRS2), f32(FRS3)).v);
+WRITE_FRD(f32_mulAdd(f32(f32(FRS1).v ^ F32_SIGN), f32(FRS2), f32(FRS3)));
set_fp_exceptions;
require_extension('D');
require_fp;
-MMU.store_uint64(RS1 + insn.s_imm(), FRS2);
+MMU.store_uint64(RS1 + insn.s_imm(), FRS2.v);
require_extension('D');
require_fp;
-WRITE_FRD((FRS1 &~ INT64_MIN) | (FRS2 & INT64_MIN));
+WRITE_FRD(fsgnj64(FRS1, FRS2, false, false));
require_extension('F');
require_fp;
-WRITE_FRD((FRS1 &~ (uint32_t)INT32_MIN) | (FRS2 & (uint32_t)INT32_MIN));
+WRITE_FRD(fsgnj32(FRS1, FRS2, false, false));
require_extension('D');
require_fp;
-WRITE_FRD((FRS1 &~ INT64_MIN) | ((~FRS2) & INT64_MIN));
+WRITE_FRD(fsgnj64(FRS1, FRS2, true, false));
require_extension('F');
require_fp;
-WRITE_FRD((FRS1 &~ (uint32_t)INT32_MIN) | ((~FRS2) & (uint32_t)INT32_MIN));
+WRITE_FRD(fsgnj32(FRS1, FRS2, true, false));
require_extension('D');
require_fp;
-WRITE_FRD(FRS1 ^ (FRS2 & INT64_MIN));
+WRITE_FRD(fsgnj64(FRS1, FRS2, false, true));
require_extension('F');
require_fp;
-WRITE_FRD(FRS1 ^ (FRS2 & (uint32_t)INT32_MIN));
+WRITE_FRD(fsgnj32(FRS1, FRS2, false, true));
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_sqrt(f64(FRS1)).v);
+WRITE_FRD(f64_sqrt(f64(FRS1)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_sqrt(f32(FRS1)).v);
+WRITE_FRD(f32_sqrt(f32(FRS1)));
set_fp_exceptions;
require_extension('D');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f64_sub(f64(FRS1), f64(FRS2)).v);
+WRITE_FRD(f64_sub(f64(FRS1), f64(FRS2)));
set_fp_exceptions;
require_extension('F');
require_fp;
softfloat_roundingMode = RM;
-WRITE_FRD(f32_sub(f32(FRS1), f32(FRS2)).v);
+WRITE_FRD(f32_sub(f32(FRS1), f32(FRS2)));
set_fp_exceptions;
require_extension('F');
require_fp;
-MMU.store_uint32(RS1 + insn.s_imm(), FRS2);
+MMU.store_uint32(RS1 + insn.s_imm(), FRS2.v);
funcs["r"] = funcs["run"];
funcs["rs"] = &sim_t::interactive_run_silent;
funcs["reg"] = &sim_t::interactive_reg;
+ funcs["freg"] = &sim_t::interactive_freg;
funcs["fregs"] = &sim_t::interactive_fregs;
funcs["fregd"] = &sim_t::interactive_fregd;
funcs["pc"] = &sim_t::interactive_pc;
return p->state.XPR[r];
}
-reg_t sim_t::get_freg(const std::vector<std::string>& args)
+freg_t sim_t::get_freg(const std::vector<std::string>& args)
{
if(args.size() != 2)
throw trap_interactive();
union fpr
{
- reg_t r;
+ freg_t r;
float s;
double d;
};
+void sim_t::interactive_freg(const std::string& cmd, const std::vector<std::string>& args)
+{
+ fprintf(stderr, "0x%016" PRIx64 "\n", get_freg(args).v);
+}
+
void sim_t::interactive_fregs(const std::string& cmd, const std::vector<std::string>& args)
{
fpr f;
void interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args);
void interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args);
void interactive_reg(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_freg(const std::string& cmd, const std::vector<std::string>& args);
void interactive_fregs(const std::string& cmd, const std::vector<std::string>& args);
void interactive_fregd(const std::string& cmd, const std::vector<std::string>& args);
void interactive_pc(const std::string& cmd, const std::vector<std::string>& args);
void interactive_str(const std::string& cmd, const std::vector<std::string>& args);
void interactive_until(const std::string& cmd, const std::vector<std::string>& args);
reg_t get_reg(const std::vector<std::string>& args);
- reg_t get_freg(const std::vector<std::string>& args);
+ freg_t get_freg(const std::vector<std::string>& args);
reg_t get_mem(const std::vector<std::string>& args);
reg_t get_pc(const std::vector<std::string>& args);