From 85c40db208db3e26f507dc6a74a5dc540b504b5c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 24 Sep 2017 20:34:04 -0700 Subject: [PATCH] Implement Q extension --- riscv/decode.h | 43 ++++++++++++++++++++++++++++++----------- riscv/insns/c_fsd.h | 2 +- riscv/insns/c_fsdsp.h | 2 +- riscv/insns/c_fsw.h | 2 +- riscv/insns/c_fswsp.h | 2 +- riscv/insns/fadd_q.h | 5 +++++ riscv/insns/fclass_q.h | 3 +++ riscv/insns/fcvt_d_q.h | 5 +++++ riscv/insns/fcvt_l_q.h | 6 ++++++ riscv/insns/fcvt_lu_q.h | 6 ++++++ riscv/insns/fcvt_q_d.h | 5 +++++ riscv/insns/fcvt_q_l.h | 6 ++++++ riscv/insns/fcvt_q_lu.h | 6 ++++++ riscv/insns/fcvt_q_s.h | 5 +++++ riscv/insns/fcvt_q_w.h | 5 +++++ riscv/insns/fcvt_q_wu.h | 5 +++++ riscv/insns/fcvt_s_q.h | 5 +++++ riscv/insns/fcvt_w_q.h | 5 +++++ riscv/insns/fcvt_wu_q.h | 5 +++++ riscv/insns/fdiv_q.h | 5 +++++ riscv/insns/feq_q.h | 4 ++++ riscv/insns/fle_q.h | 4 ++++ riscv/insns/flq.h | 3 +++ riscv/insns/flt_q.h | 4 ++++ riscv/insns/fmadd_q.h | 5 +++++ riscv/insns/fmax_q.h | 8 ++++++++ riscv/insns/fmin_q.h | 8 ++++++++ riscv/insns/fmsub_q.h | 5 +++++ riscv/insns/fmul_q.h | 5 +++++ riscv/insns/fmv_x_d.h | 2 +- riscv/insns/fmv_x_w.h | 2 +- riscv/insns/fnmadd_q.h | 5 +++++ riscv/insns/fnmsub_q.h | 5 +++++ riscv/insns/fsd.h | 2 +- riscv/insns/fsgnj_q.h | 3 +++ riscv/insns/fsgnjn_q.h | 3 +++ riscv/insns/fsgnjx_q.h | 3 +++ riscv/insns/fsq.h | 3 +++ riscv/insns/fsqrt_q.h | 5 +++++ riscv/insns/fsub_q.h | 5 +++++ riscv/insns/fsw.h | 2 +- riscv/interactive.cc | 7 ++++--- riscv/mmu.h | 19 ++++++++++++++++++ riscv/processor.cc | 10 ++++++++-- riscv/riscv.mk.in | 32 ++++++++++++++++++++++++++++++ 45 files changed, 258 insertions(+), 24 deletions(-) create mode 100644 riscv/insns/fadd_q.h create mode 100644 riscv/insns/fclass_q.h create mode 100644 riscv/insns/fcvt_d_q.h create mode 100644 riscv/insns/fcvt_l_q.h create mode 100644 riscv/insns/fcvt_lu_q.h create mode 100644 riscv/insns/fcvt_q_d.h create mode 100644 riscv/insns/fcvt_q_l.h create mode 100644 riscv/insns/fcvt_q_lu.h create mode 100644 riscv/insns/fcvt_q_s.h create mode 100644 riscv/insns/fcvt_q_w.h create mode 100644 riscv/insns/fcvt_q_wu.h create mode 100644 riscv/insns/fcvt_s_q.h create mode 100644 riscv/insns/fcvt_w_q.h create mode 100644 riscv/insns/fcvt_wu_q.h create mode 100644 riscv/insns/fdiv_q.h create mode 100644 riscv/insns/feq_q.h create mode 100644 riscv/insns/fle_q.h create mode 100644 riscv/insns/flq.h create mode 100644 riscv/insns/flt_q.h create mode 100644 riscv/insns/fmadd_q.h create mode 100644 riscv/insns/fmax_q.h create mode 100644 riscv/insns/fmin_q.h create mode 100644 riscv/insns/fmsub_q.h create mode 100644 riscv/insns/fmul_q.h create mode 100644 riscv/insns/fnmadd_q.h create mode 100644 riscv/insns/fnmsub_q.h create mode 100644 riscv/insns/fsgnj_q.h create mode 100644 riscv/insns/fsgnjn_q.h create mode 100644 riscv/insns/fsgnjx_q.h create mode 100644 riscv/insns/fsq.h create mode 100644 riscv/insns/fsqrt_q.h create mode 100644 riscv/insns/fsub_q.h diff --git a/riscv/decode.h b/riscv/decode.h index 9dcd809..45dd3c4 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -219,24 +219,45 @@ private: #define invalid_pc(pc) ((pc) & 1) /* Convenience wrappers to simplify softfloat code sequences */ -#define isBoxedF32(r) (((r) & 0xffffffff00000000) == 0xffffffff00000000) -#define unboxF32(r) (isBoxedF32(r) ? (r) : defaultNaNF32UI) -#define unboxF64(r) (r) -struct freg_t { uint64_t v; }; +#define isBoxedF32(r) (isBoxedF64(r) && ((uint32_t)((r.v[0] >> 32) + 1) == 0)) +#define unboxF32(r) (isBoxedF32(r) ? (uint32_t)r.v[0] : defaultNaNF32UI) +#define isBoxedF64(r) ((r.v[1] + 1) == 0) +#define unboxF64(r) (isBoxedF64(r) ? r.v[0] : defaultNaNF64UI) +typedef float128_t freg_t; 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) +inline float32_t f32(freg_t r) { return f32(unboxF32(r)); } +inline float64_t f64(freg_t r) { return f64(unboxF64(r)); } +inline float128_t f128(freg_t r) { return r; } +inline freg_t freg(float32_t f) { return { ((uint64_t)-1 << 32) | f.v, (uint64_t)-1 }; } +inline freg_t freg(float64_t f) { return { f.v, (uint64_t)-1 }; } +inline freg_t freg(float128_t f) { return f; } +#define F32_SIGN ((uint32_t)1 << 31) +#define F64_SIGN ((uint64_t)1 << 63) #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 isNaNF128(x) isNaNF128UI(x.v[1], x.v[0]) +inline float128_t defaultNaNF128() +{ + float128_t nan; + nan.v[1] = defaultNaNF128UI64; + nan.v[0] = defaultNaNF128UI0; + return nan; +} +inline freg_t fsgnj128(freg_t a, freg_t b, bool n, bool x) +{ + a.v[1] = (a.v[1] & ~F64_SIGN) | (((x ? a.v[1] : n ? F64_SIGN : 0) ^ b.v[1]) & F64_SIGN); + return a; +} +inline freg_t f128_negate(freg_t a) +{ + a.v[1] ^= F64_SIGN; + return a; +} + #define validate_csr(which, write) ({ \ if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \ STATE.serialized = false; \ diff --git a/riscv/insns/c_fsd.h b/riscv/insns/c_fsd.h index 8743266..6f2c8f4 100644 --- a/riscv/insns/c_fsd.h +++ b/riscv/insns/c_fsd.h @@ -1,4 +1,4 @@ require_extension('C'); require_extension('D'); require_fp; -MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v); +MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v[0]); diff --git a/riscv/insns/c_fsdsp.h b/riscv/insns/c_fsdsp.h index f62f8ff..27b9331 100644 --- a/riscv/insns/c_fsdsp.h +++ b/riscv/insns/c_fsdsp.h @@ -1,4 +1,4 @@ require_extension('C'); require_extension('D'); require_fp; -MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v); +MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v[0]); diff --git a/riscv/insns/c_fsw.h b/riscv/insns/c_fsw.h index b924a46..7085822 100644 --- a/riscv/insns/c_fsw.h +++ b/riscv/insns/c_fsw.h @@ -2,7 +2,7 @@ require_extension('C'); if (xlen == 32) { require_extension('F'); require_fp; - MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v); + MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v[0]); } else { // c.sd MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); } diff --git a/riscv/insns/c_fswsp.h b/riscv/insns/c_fswsp.h index 011de55..c5a003f 100644 --- a/riscv/insns/c_fswsp.h +++ b/riscv/insns/c_fswsp.h @@ -2,7 +2,7 @@ require_extension('C'); if (xlen == 32) { require_extension('F'); require_fp; - MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v); + MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v[0]); } else { // c.sdsp MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); } diff --git a/riscv/insns/fadd_q.h b/riscv/insns/fadd_q.h new file mode 100644 index 0000000..1139a74 --- /dev/null +++ b/riscv/insns/fadd_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_add(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/fclass_q.h b/riscv/insns/fclass_q.h new file mode 100644 index 0000000..5330758 --- /dev/null +++ b/riscv/insns/fclass_q.h @@ -0,0 +1,3 @@ +require_extension('Q'); +require_fp; +WRITE_RD(f128_classify(f128(FRS1))); diff --git a/riscv/insns/fcvt_d_q.h b/riscv/insns/fcvt_d_q.h new file mode 100644 index 0000000..b50a43d --- /dev/null +++ b/riscv/insns/fcvt_d_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_to_f64(f128(FRS1))); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_l_q.h b/riscv/insns/fcvt_l_q.h new file mode 100644 index 0000000..b28bca2 --- /dev/null +++ b/riscv/insns/fcvt_l_q.h @@ -0,0 +1,6 @@ +require_extension('Q'); +require_rv64; +require_fp; +softfloat_roundingMode = RM; +WRITE_RD(f128_to_i64(f128(FRS1), RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_lu_q.h b/riscv/insns/fcvt_lu_q.h new file mode 100644 index 0000000..8c5be7c --- /dev/null +++ b/riscv/insns/fcvt_lu_q.h @@ -0,0 +1,6 @@ +require_extension('Q'); +require_rv64; +require_fp; +softfloat_roundingMode = RM; +WRITE_RD(f128_to_ui64(f128(FRS1), RM, true)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_q_d.h b/riscv/insns/fcvt_q_d.h new file mode 100644 index 0000000..c2437b1 --- /dev/null +++ b/riscv/insns/fcvt_q_d.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f64_to_f128(f64(FRS1))); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_q_l.h b/riscv/insns/fcvt_q_l.h new file mode 100644 index 0000000..f1f45ca --- /dev/null +++ b/riscv/insns/fcvt_q_l.h @@ -0,0 +1,6 @@ +require_extension('Q'); +require_rv64; +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(i64_to_f128(RS1)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_q_lu.h b/riscv/insns/fcvt_q_lu.h new file mode 100644 index 0000000..850212e --- /dev/null +++ b/riscv/insns/fcvt_q_lu.h @@ -0,0 +1,6 @@ +require_extension('Q'); +require_rv64; +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(ui64_to_f128(RS1)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_q_s.h b/riscv/insns/fcvt_q_s.h new file mode 100644 index 0000000..79e6bb6 --- /dev/null +++ b/riscv/insns/fcvt_q_s.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f32_to_f128(f32(FRS1))); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_q_w.h b/riscv/insns/fcvt_q_w.h new file mode 100644 index 0000000..fb83f15 --- /dev/null +++ b/riscv/insns/fcvt_q_w.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(i32_to_f128((int32_t)RS1)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_q_wu.h b/riscv/insns/fcvt_q_wu.h new file mode 100644 index 0000000..7c2ae97 --- /dev/null +++ b/riscv/insns/fcvt_q_wu.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(ui32_to_f128((uint32_t)RS1)); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_q.h b/riscv/insns/fcvt_s_q.h new file mode 100644 index 0000000..b0f118e --- /dev/null +++ b/riscv/insns/fcvt_s_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_to_f32(f128(FRS1))); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_w_q.h b/riscv/insns/fcvt_w_q.h new file mode 100644 index 0000000..e10bafc --- /dev/null +++ b/riscv/insns/fcvt_w_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_RD(sext32(f128_to_i32(f128(FRS1), RM, true))); +set_fp_exceptions; diff --git a/riscv/insns/fcvt_wu_q.h b/riscv/insns/fcvt_wu_q.h new file mode 100644 index 0000000..c391dc8 --- /dev/null +++ b/riscv/insns/fcvt_wu_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_RD(sext32(f128_to_ui32(f128(FRS1), RM, true))); +set_fp_exceptions; diff --git a/riscv/insns/fdiv_q.h b/riscv/insns/fdiv_q.h new file mode 100644 index 0000000..2204831 --- /dev/null +++ b/riscv/insns/fdiv_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_div(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/feq_q.h b/riscv/insns/feq_q.h new file mode 100644 index 0000000..cee2da9 --- /dev/null +++ b/riscv/insns/feq_q.h @@ -0,0 +1,4 @@ +require_extension('Q'); +require_fp; +WRITE_RD(f128_eq(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/fle_q.h b/riscv/insns/fle_q.h new file mode 100644 index 0000000..8368af9 --- /dev/null +++ b/riscv/insns/fle_q.h @@ -0,0 +1,4 @@ +require_extension('Q'); +require_fp; +WRITE_RD(f128_le(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/flq.h b/riscv/insns/flq.h new file mode 100644 index 0000000..81d225c --- /dev/null +++ b/riscv/insns/flq.h @@ -0,0 +1,3 @@ +require_extension('Q'); +require_fp; +WRITE_FRD(MMU.load_float128(RS1 + insn.i_imm())); diff --git a/riscv/insns/flt_q.h b/riscv/insns/flt_q.h new file mode 100644 index 0000000..c452141 --- /dev/null +++ b/riscv/insns/flt_q.h @@ -0,0 +1,4 @@ +require_extension('Q'); +require_fp; +WRITE_RD(f128_lt(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/fmadd_q.h b/riscv/insns/fmadd_q.h new file mode 100644 index 0000000..882dfc1 --- /dev/null +++ b/riscv/insns/fmadd_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_mulAdd(f128(FRS1), f128(FRS2), f128(FRS3))); +set_fp_exceptions; diff --git a/riscv/insns/fmax_q.h b/riscv/insns/fmax_q.h new file mode 100644 index 0000000..719e6d0 --- /dev/null +++ b/riscv/insns/fmax_q.h @@ -0,0 +1,8 @@ +require_extension('Q'); +require_fp; +bool greater = f128_lt_quiet(f128(FRS2), f128(FRS1)) || + (f128_eq(f128(FRS2), f128(FRS1)) && (f128(FRS2).v[1] & F64_SIGN)); +WRITE_FRD(greater || isNaNF128(f128(FRS2)) ? FRS1 : FRS2); +if (isNaNF128(f128(FRS1)) && isNaNF128(f128(FRS2))) + WRITE_FRD(f128(defaultNaNF128())); +set_fp_exceptions; diff --git a/riscv/insns/fmin_q.h b/riscv/insns/fmin_q.h new file mode 100644 index 0000000..675c7fd --- /dev/null +++ b/riscv/insns/fmin_q.h @@ -0,0 +1,8 @@ +require_extension('Q'); +require_fp; +bool less = f128_lt_quiet(f128(FRS1), f128(FRS2)) || + (f128_eq(f128(FRS1), f128(FRS2)) && (f128(FRS1).v[1] & F64_SIGN)); +WRITE_FRD(less || isNaNF128(f128(FRS2)) ? FRS1 : FRS2); +if (isNaNF128(f128(FRS1)) && isNaNF128(f128(FRS2))) + WRITE_FRD(f128(defaultNaNF128())); +set_fp_exceptions; diff --git a/riscv/insns/fmsub_q.h b/riscv/insns/fmsub_q.h new file mode 100644 index 0000000..1bb96c2 --- /dev/null +++ b/riscv/insns/fmsub_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_mulAdd(f128(FRS1), f128(FRS2), f128_negate(f128(FRS3)))); +set_fp_exceptions; diff --git a/riscv/insns/fmul_q.h b/riscv/insns/fmul_q.h new file mode 100644 index 0000000..66f5a05 --- /dev/null +++ b/riscv/insns/fmul_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_mul(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/fmv_x_d.h b/riscv/insns/fmv_x_d.h index da8e72a..e1a23f4 100644 --- a/riscv/insns/fmv_x_d.h +++ b/riscv/insns/fmv_x_d.h @@ -1,4 +1,4 @@ require_extension('D'); require_rv64; require_fp; -WRITE_RD(FRS1.v); +WRITE_RD(FRS1.v[0]); diff --git a/riscv/insns/fmv_x_w.h b/riscv/insns/fmv_x_w.h index b722479..6754f86 100644 --- a/riscv/insns/fmv_x_w.h +++ b/riscv/insns/fmv_x_w.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_RD(sext32(FRS1.v)); +WRITE_RD(sext32(FRS1.v[0])); diff --git a/riscv/insns/fnmadd_q.h b/riscv/insns/fnmadd_q.h new file mode 100644 index 0000000..a36ce18 --- /dev/null +++ b/riscv/insns/fnmadd_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_mulAdd(f128_negate(f128(FRS1)), f128(FRS2), f128_negate(f128(FRS3)))); +set_fp_exceptions; diff --git a/riscv/insns/fnmsub_q.h b/riscv/insns/fnmsub_q.h new file mode 100644 index 0000000..130b4ce --- /dev/null +++ b/riscv/insns/fnmsub_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_mulAdd(f128_negate(f128(FRS1)), f128(FRS2), f128(FRS3))); +set_fp_exceptions; diff --git a/riscv/insns/fsd.h b/riscv/insns/fsd.h index 679cc95..38c702b 100644 --- a/riscv/insns/fsd.h +++ b/riscv/insns/fsd.h @@ -1,3 +1,3 @@ require_extension('D'); require_fp; -MMU.store_uint64(RS1 + insn.s_imm(), FRS2.v); +MMU.store_uint64(RS1 + insn.s_imm(), FRS2.v[0]); diff --git a/riscv/insns/fsgnj_q.h b/riscv/insns/fsgnj_q.h new file mode 100644 index 0000000..0b9a270 --- /dev/null +++ b/riscv/insns/fsgnj_q.h @@ -0,0 +1,3 @@ +require_extension('Q'); +require_fp; +WRITE_FRD(fsgnj128(FRS1, FRS2, false, false)); diff --git a/riscv/insns/fsgnjn_q.h b/riscv/insns/fsgnjn_q.h new file mode 100644 index 0000000..38c7bbf --- /dev/null +++ b/riscv/insns/fsgnjn_q.h @@ -0,0 +1,3 @@ +require_extension('Q'); +require_fp; +WRITE_FRD(fsgnj128(FRS1, FRS2, true, false)); diff --git a/riscv/insns/fsgnjx_q.h b/riscv/insns/fsgnjx_q.h new file mode 100644 index 0000000..fc86d26 --- /dev/null +++ b/riscv/insns/fsgnjx_q.h @@ -0,0 +1,3 @@ +require_extension('Q'); +require_fp; +WRITE_FRD(fsgnj128(FRS1, FRS2, false, true)); diff --git a/riscv/insns/fsq.h b/riscv/insns/fsq.h new file mode 100644 index 0000000..610960e --- /dev/null +++ b/riscv/insns/fsq.h @@ -0,0 +1,3 @@ +require_extension('Q'); +require_fp; +MMU.store_float128(RS1 + insn.s_imm(), FRS2); diff --git a/riscv/insns/fsqrt_q.h b/riscv/insns/fsqrt_q.h new file mode 100644 index 0000000..6cb6ba3 --- /dev/null +++ b/riscv/insns/fsqrt_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_sqrt(f128(FRS1))); +set_fp_exceptions; diff --git a/riscv/insns/fsub_q.h b/riscv/insns/fsub_q.h new file mode 100644 index 0000000..e050e3a --- /dev/null +++ b/riscv/insns/fsub_q.h @@ -0,0 +1,5 @@ +require_extension('Q'); +require_fp; +softfloat_roundingMode = RM; +WRITE_FRD(f128_sub(f128(FRS1), f128(FRS2))); +set_fp_exceptions; diff --git a/riscv/insns/fsw.h b/riscv/insns/fsw.h index 42fc683..8af5184 100644 --- a/riscv/insns/fsw.h +++ b/riscv/insns/fsw.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -MMU.store_uint32(RS1 + insn.s_imm(), FRS2.v); +MMU.store_uint32(RS1 + insn.s_imm(), FRS2.v[0]); diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 31b9162..e6e8616 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -239,21 +239,22 @@ union fpr void sim_t::interactive_freg(const std::string& cmd, const std::vector& args) { - fprintf(stderr, "0x%016" PRIx64 "\n", get_freg(args).v); + freg_t r = get_freg(args); + fprintf(stderr, "0x%016" PRIx64 "%016" PRIx64 "\n", r.v[1], r.v[0]); } void sim_t::interactive_fregs(const std::string& cmd, const std::vector& args) { fpr f; f.r = get_freg(args); - fprintf(stderr, "%g\n",f.s); + fprintf(stderr, "%g\n", isBoxedF32(f.r) ? (double)f.s : NAN); } void sim_t::interactive_fregd(const std::string& cmd, const std::vector& args) { fpr f; f.r = get_freg(args); - fprintf(stderr, "%g\n",f.d); + fprintf(stderr, "%g\n", isBoxedF64(f.r) ? f.d : NAN); } reg_t sim_t::get_mem(const std::vector& args) diff --git a/riscv/mmu.h b/riscv/mmu.h index f70a969..7d6ea88 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -151,6 +151,25 @@ public: } \ } + void store_float128(reg_t addr, float128_t val) + { +#ifndef RISCV_ENABLE_MISALIGNED + if (unlikely(addr & (sizeof(float128_t)-1))) + throw trap_store_address_misaligned(addr); +#endif + store_uint64(addr, val.v[0]); + store_uint64(addr + 8, val.v[1]); + } + + float128_t load_float128(reg_t addr) + { +#ifndef RISCV_ENABLE_MISALIGNED + if (unlikely(addr & (sizeof(float128_t)-1))) + throw trap_load_address_misaligned(addr); +#endif + return (float128_t){load_uint64(addr), load_uint64(addr + 8)}; + } + // store value to memory at aligned address store_func(uint8) store_func(uint16) diff --git a/riscv/processor.cc b/riscv/processor.cc index 6804ba7..ae02165 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -61,7 +61,7 @@ void processor_t::parse_isa_string(const char* str) lowercase += std::tolower(*r); const char* p = lowercase.c_str(); - const char* all_subsets = "imafdc"; + const char* all_subsets = "imafdqc"; max_xlen = 64; isa = reg_t(2) << 62; @@ -74,7 +74,7 @@ void processor_t::parse_isa_string(const char* str) p += 2; if (!*p) { - p = all_subsets; + p = "imafdc"; } else if (*p == 'g') { // treat "G" as "IMAFD" tmp = std::string("imafd") + (p+1); p = &tmp[0]; @@ -106,6 +106,12 @@ void processor_t::parse_isa_string(const char* str) if (supports_extension('D') && !supports_extension('F')) bad_isa_string(str); + if (supports_extension('Q') && !supports_extension('D')) + bad_isa_string(str); + + if (supports_extension('Q') && max_xlen < 64) + bad_isa_string(str); + // advertise support for supervisor and user modes isa |= 1L << ('s' - 'a'); isa |= 1L << ('u' - 'a'); diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 05e316a..f8abb1b 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -138,67 +138,99 @@ riscv_insn_list = \ ebreak \ ecall \ fadd_d \ + fadd_q \ fadd_s \ fclass_d \ + fclass_q \ fclass_s \ fcvt_d_l \ fcvt_d_lu \ + fcvt_d_q \ fcvt_d_s \ fcvt_d_w \ fcvt_d_wu \ fcvt_l_d \ + fcvt_l_q \ fcvt_l_s \ fcvt_lu_d \ + fcvt_lu_q \ fcvt_lu_s \ + fcvt_q_d \ + fcvt_q_l \ + fcvt_q_lu \ + fcvt_q_s \ + fcvt_q_w \ + fcvt_q_wu \ fcvt_s_d \ fcvt_s_l \ fcvt_s_lu \ + fcvt_s_q \ fcvt_s_w \ fcvt_s_wu \ fcvt_w_d \ + fcvt_w_q \ fcvt_w_s \ fcvt_wu_d \ + fcvt_wu_q \ fcvt_wu_s \ fdiv_d \ + fdiv_q \ fdiv_s \ fence \ fence_i \ feq_d \ + feq_q \ feq_s \ fld \ fle_d \ + fle_q \ fle_s \ + flq \ flt_d \ + flt_q \ flt_s \ flw \ fmadd_d \ + fmadd_q \ fmadd_s \ fmax_d \ + fmax_q \ fmax_s \ fmin_d \ + fmin_q \ fmin_s \ fmsub_d \ + fmsub_q \ fmsub_s \ fmul_d \ + fmul_q \ fmul_s \ fmv_d_x \ fmv_w_x \ fmv_x_d \ fmv_x_w \ fnmadd_d \ + fnmadd_q \ fnmadd_s \ fnmsub_d \ + fnmsub_q \ fnmsub_s \ fsd \ fsgnj_d \ + fsgnj_q \ fsgnjn_d \ + fsgnjn_q \ fsgnjn_s \ fsgnj_s \ fsgnjx_d \ + fsgnjx_q \ fsgnjx_s \ + fsq \ fsqrt_d \ + fsqrt_q \ fsqrt_s \ fsub_d \ + fsub_q \ fsub_s \ fsw \ jal \ -- 2.30.2