Skip to content

Commit

Permalink
Merge pull request #129 from riscv/q-extension
Browse files Browse the repository at this point in the history
Implement Q extension
  • Loading branch information
aswaterman authored Oct 11, 2017
2 parents 58b6c18 + 85c40db commit 3177a7c
Show file tree
Hide file tree
Showing 263 changed files with 11,453 additions and 1,092 deletions.
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

0 comments on commit 3177a7c

Please sign in to comment.