Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Q extension #129

Merged
merged 2 commits into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions riscv/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,24 +219,45 @@ class regfile_t
#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; \
Expand Down
2 changes: 1 addition & 1 deletion riscv/insns/c_fsd.h
Original file line number Diff line number Diff line change
@@ -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]);
2 changes: 1 addition & 1 deletion riscv/insns/c_fsdsp.h
Original file line number Diff line number Diff line change
@@ -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]);
2 changes: 1 addition & 1 deletion riscv/insns/c_fsw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
2 changes: 1 addition & 1 deletion riscv/insns/c_fswsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
5 changes: 5 additions & 0 deletions riscv/insns/fadd_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_add(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
3 changes: 3 additions & 0 deletions riscv/insns/fclass_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_extension('Q');
require_fp;
WRITE_RD(f128_classify(f128(FRS1)));
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_d_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_to_f64(f128(FRS1)));
set_fp_exceptions;
6 changes: 6 additions & 0 deletions riscv/insns/fcvt_l_q.h
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 6 additions & 0 deletions riscv/insns/fcvt_lu_q.h
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_q_d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_to_f128(f64(FRS1)));
set_fp_exceptions;
6 changes: 6 additions & 0 deletions riscv/insns/fcvt_q_l.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require_extension('Q');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(i64_to_f128(RS1));
set_fp_exceptions;
6 changes: 6 additions & 0 deletions riscv/insns/fcvt_q_lu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require_extension('Q');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(ui64_to_f128(RS1));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_q_s.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_to_f128(f32(FRS1)));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_q_w.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(i32_to_f128((int32_t)RS1));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_q_wu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(ui32_to_f128((uint32_t)RS1));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_s_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_to_f32(f128(FRS1)));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_w_q.h
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions riscv/insns/fcvt_wu_q.h
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions riscv/insns/fdiv_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_div(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
4 changes: 4 additions & 0 deletions riscv/insns/feq_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require_extension('Q');
require_fp;
WRITE_RD(f128_eq(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
4 changes: 4 additions & 0 deletions riscv/insns/fle_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require_extension('Q');
require_fp;
WRITE_RD(f128_le(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
3 changes: 3 additions & 0 deletions riscv/insns/flq.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_extension('Q');
require_fp;
WRITE_FRD(MMU.load_float128(RS1 + insn.i_imm()));
4 changes: 4 additions & 0 deletions riscv/insns/flt_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require_extension('Q');
require_fp;
WRITE_RD(f128_lt(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fmadd_q.h
Original file line number Diff line number Diff line change
@@ -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;
8 changes: 8 additions & 0 deletions riscv/insns/fmax_q.h
Original file line number Diff line number Diff line change
@@ -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;
8 changes: 8 additions & 0 deletions riscv/insns/fmin_q.h
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions riscv/insns/fmsub_q.h
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions riscv/insns/fmul_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_mul(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
2 changes: 1 addition & 1 deletion riscv/insns/fmv_x_d.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require_extension('D');
require_rv64;
require_fp;
WRITE_RD(FRS1.v);
WRITE_RD(FRS1.v[0]);
2 changes: 1 addition & 1 deletion riscv/insns/fmv_x_w.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
require_extension('F');
require_fp;
WRITE_RD(sext32(FRS1.v));
WRITE_RD(sext32(FRS1.v[0]));
5 changes: 5 additions & 0 deletions riscv/insns/fnmadd_q.h
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 5 additions & 0 deletions riscv/insns/fnmsub_q.h
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion riscv/insns/fsd.h
Original file line number Diff line number Diff line change
@@ -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]);
3 changes: 3 additions & 0 deletions riscv/insns/fsgnj_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_extension('Q');
require_fp;
WRITE_FRD(fsgnj128(FRS1, FRS2, false, false));
3 changes: 3 additions & 0 deletions riscv/insns/fsgnjn_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_extension('Q');
require_fp;
WRITE_FRD(fsgnj128(FRS1, FRS2, true, false));
3 changes: 3 additions & 0 deletions riscv/insns/fsgnjx_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_extension('Q');
require_fp;
WRITE_FRD(fsgnj128(FRS1, FRS2, false, true));
3 changes: 3 additions & 0 deletions riscv/insns/fsq.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_extension('Q');
require_fp;
MMU.store_float128(RS1 + insn.s_imm(), FRS2);
5 changes: 5 additions & 0 deletions riscv/insns/fsqrt_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_sqrt(f128(FRS1)));
set_fp_exceptions;
5 changes: 5 additions & 0 deletions riscv/insns/fsub_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require_extension('Q');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f128_sub(f128(FRS1), f128(FRS2)));
set_fp_exceptions;
2 changes: 1 addition & 1 deletion riscv/insns/fsw.h
Original file line number Diff line number Diff line change
@@ -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]);
7 changes: 4 additions & 3 deletions riscv/interactive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,22 @@ union fpr

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);
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<std::string>& 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<std::string>& 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<std::string>& args)
Expand Down
19 changes: 19 additions & 0 deletions riscv/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,25 @@ class mmu_t
} \
}

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)
Expand Down
10 changes: 8 additions & 2 deletions riscv/processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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');
Expand Down
Loading