addition bug fixes
This commit is contained in:
@@ -33,7 +33,7 @@ jobs:
|
|||||||
script: cp -r $PWD ../build_coverage && cd ../build_coverage && ./ci/travis_run.py ./ci/regression.sh -coverage
|
script: cp -r $PWD ../build_coverage && cd ../build_coverage && ./ci/travis_run.py ./ci/regression.sh -coverage
|
||||||
- stage: test
|
- stage: test
|
||||||
name: coverage64
|
name: coverage64
|
||||||
script: cp -r $PWD ../build_coverage && cd ../build_coverage && ./ci/travis_run.py ./ci/regression64.sh -coverage
|
script: cp -r $PWD ../build_coverage64 && cd ../build_coverage64 && ./ci/travis_run.py ./ci/regression64.sh -coverage
|
||||||
- stage: test
|
- stage: test
|
||||||
name: tex
|
name: tex
|
||||||
script: cp -r $PWD ../build_tex && cd ../build_tex && ./ci/travis_run.py ./ci/regression.sh -tex
|
script: cp -r $PWD ../build_tex && cd ../build_tex && ./ci/travis_run.py ./ci/regression.sh -tex
|
||||||
|
|||||||
@@ -48,16 +48,49 @@ inline uint32_t get_fpu_rm(uint32_t func3, Core* core, uint32_t tid, uint32_t wi
|
|||||||
return (func3 == 0x7) ? core->get_csr(CSR_FRM, tid, wid) : func3;
|
return (func3 == 0x7) ? core->get_csr(CSR_FRM, tid, wid) : func3;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void update_fcrs(uint32_t fflags, Core* core, uint32_t tid, uint32_t wid) {
|
static void update_fcrs(uint32_t fflags, Core* core, uint32_t tid, uint32_t wid) {
|
||||||
if (fflags) {
|
if (fflags) {
|
||||||
core->set_csr(CSR_FCSR, core->get_csr(CSR_FCSR, tid, wid) | fflags, tid, wid);
|
core->set_csr(CSR_FCSR, core->get_csr(CSR_FCSR, tid, wid) | fflags, tid, wid);
|
||||||
core->set_csr(CSR_FFLAGS, core->get_csr(CSR_FFLAGS, tid, wid) | fflags, tid, wid);
|
core->set_csr(CSR_FFLAGS, core->get_csr(CSR_FFLAGS, tid, wid) | fflags, tid, wid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t nan_box(uint32_t word) {
|
inline uint64_t nan_box(uint32_t value) {
|
||||||
uint64_t mask = 0xffffffff00000000;
|
uint64_t mask = 0xffffffff00000000;
|
||||||
return word | mask;
|
return value | mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_nan_boxed(uint64_t value) {
|
||||||
|
return (uint32_t(value >> 32) == 0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkBoxedArgs(FWord* out, FWord a, FWord b, uint32_t* fflags) {
|
||||||
|
bool xa = is_nan_boxed(a);
|
||||||
|
bool xb = is_nan_boxed(b);
|
||||||
|
if (xa && xb)
|
||||||
|
return true;
|
||||||
|
if (xa) {
|
||||||
|
// a is NaN boxed but b isn't
|
||||||
|
*out = nan_box((uint32_t)a);
|
||||||
|
} else if (xb) {
|
||||||
|
// b is NaN boxed but a isn't
|
||||||
|
*out = nan_box(0xffc00000);
|
||||||
|
} else {
|
||||||
|
// Both a and b aren't NaN boxed
|
||||||
|
*out = nan_box(0x7fc00000);
|
||||||
|
}
|
||||||
|
*fflags = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkBoxedCmpArgs(Word* out, FWord a, FWord b, uint32_t* fflags) {
|
||||||
|
bool xa = is_nan_boxed(a);
|
||||||
|
bool xb = is_nan_boxed(b);
|
||||||
|
if (xa && xb)
|
||||||
|
return true;
|
||||||
|
*out = 0;
|
||||||
|
*fflags = 0;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
||||||
@@ -845,108 +878,87 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
continue;
|
continue;
|
||||||
uint32_t frm = get_fpu_rm(func3, core_, t, id_);
|
uint32_t frm = get_fpu_rm(func3, core_, t, id_);
|
||||||
uint32_t fflags = 0;
|
uint32_t fflags = 0;
|
||||||
bool fvalid = true;
|
|
||||||
switch (func7) {
|
switch (func7) {
|
||||||
case 0x00: // RV32F: FADD.S
|
case 0x00: { // RV32F: FADD.S
|
||||||
case 0x04: // RV32F: FSUB.S
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
case 0x08: // RV32F: FMUL.S
|
|
||||||
case 0x0c: // RV32F: FDIV.S
|
|
||||||
case 0x2c: // RV32F: FSQRT.S
|
|
||||||
case 0x10: // RV32F: FSGNJ.S / FSGNJN.S / FSGNJX.S
|
|
||||||
case 0x14: // RV32F: FMAX.S / FMIN.S
|
|
||||||
case 0x50: {
|
|
||||||
// RV32F: FLE.S / FLT.S / FEQ.S
|
|
||||||
uint64_t a = rsdata[t][0].f;
|
|
||||||
uint64_t b = rsdata[t][1].f;
|
|
||||||
// Both a and b aren't NaN boxed
|
|
||||||
if ((a >> 32 != 0xffffffff) && (b >> 32 != 0xffffffff)) {
|
|
||||||
rddata[t].f = nan_box(0x7fc00000);
|
|
||||||
fvalid = false;
|
|
||||||
}
|
|
||||||
// a is NaN boxed but b isn't
|
|
||||||
else if (b >> 32 != 0xffffffff) {
|
|
||||||
rddata[t].f = nan_box((uint32_t)a);
|
|
||||||
fvalid = false;
|
|
||||||
}
|
|
||||||
// b is NaN boxed but a isn't
|
|
||||||
else if (a >> 32 != 0xffffffff) {
|
|
||||||
rddata[t].f = nan_box(0xffc00000);
|
|
||||||
fvalid = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fvalid){
|
|
||||||
switch (func7) {
|
|
||||||
case 0x00: { // RV32F: FADD.S
|
|
||||||
rddata[t].f = nan_box(rv_fadd_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
rddata[t].f = nan_box(rv_fadd_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
||||||
trace->fpu.type = FpuType::FMA;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0x01: { // RV32D: FADD.D
|
trace->fpu.type = FpuType::FMA;
|
||||||
rddata[t].f = rv_fadd_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
trace->used_fregs.set(rsrc0);
|
||||||
trace->fpu.type = FpuType::FMA;
|
trace->used_fregs.set(rsrc1);
|
||||||
trace->used_fregs.set(rsrc0);
|
break;
|
||||||
trace->used_fregs.set(rsrc1);
|
}
|
||||||
break;
|
case 0x01: { // RV32D: FADD.D
|
||||||
}
|
rddata[t].f = rv_fadd_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
||||||
case 0x04: { // RV32F: FSUB.S
|
trace->fpu.type = FpuType::FMA;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x04: { // RV32F: FSUB.S
|
||||||
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
rddata[t].f = nan_box(rv_fsub_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
rddata[t].f = nan_box(rv_fsub_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
||||||
trace->fpu.type = FpuType::FMA;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0x05: { // RV32D: FSUB.D
|
trace->fpu.type = FpuType::FMA;
|
||||||
rddata[t].f = rv_fsub_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
trace->used_fregs.set(rsrc0);
|
||||||
trace->fpu.type = FpuType::FMA;
|
trace->used_fregs.set(rsrc1);
|
||||||
trace->used_fregs.set(rsrc0);
|
break;
|
||||||
trace->used_fregs.set(rsrc1);
|
}
|
||||||
break;
|
case 0x05: { // RV32D: FSUB.D
|
||||||
}
|
rddata[t].f = rv_fsub_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
||||||
case 0x08: { // RV32F: FMUL.S
|
trace->fpu.type = FpuType::FMA;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x08: { // RV32F: FMUL.S
|
||||||
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
rddata[t].f = nan_box(rv_fmul_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
rddata[t].f = nan_box(rv_fmul_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
||||||
trace->fpu.type = FpuType::FMA;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0x09: { // RV32D: FMUL.D
|
trace->fpu.type = FpuType::FMA;
|
||||||
rddata[t].f = rv_fmul_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
trace->used_fregs.set(rsrc0);
|
||||||
trace->fpu.type = FpuType::FMA;
|
trace->used_fregs.set(rsrc1);
|
||||||
trace->used_fregs.set(rsrc0);
|
break;
|
||||||
trace->used_fregs.set(rsrc1);
|
}
|
||||||
break;
|
case 0x09: { // RV32D: FMUL.D
|
||||||
}
|
rddata[t].f = rv_fmul_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
||||||
case 0x0c: { // RV32F: FDIV.S
|
trace->fpu.type = FpuType::FMA;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x0c: { // RV32F: FDIV.S
|
||||||
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
rddata[t].f = nan_box(rv_fdiv_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
rddata[t].f = nan_box(rv_fdiv_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
|
||||||
trace->fpu.type = FpuType::FDIV;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0x0d: { // RV32D: FDIV.D
|
trace->fpu.type = FpuType::FDIV;
|
||||||
rddata[t].f = rv_fdiv_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
trace->used_fregs.set(rsrc0);
|
||||||
trace->fpu.type = FpuType::FDIV;
|
trace->used_fregs.set(rsrc1);
|
||||||
trace->used_fregs.set(rsrc0);
|
break;
|
||||||
trace->used_fregs.set(rsrc1);
|
}
|
||||||
break;
|
case 0x0d: { // RV32D: FDIV.D
|
||||||
}
|
rddata[t].f = rv_fdiv_d(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags);
|
||||||
case 0x2c: { // RV32F: FSQRT.S
|
trace->fpu.type = FpuType::FDIV;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2c: { // RV32F: FSQRT.S
|
||||||
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
rddata[t].f = nan_box(rv_fsqrt_s(rsdata[t][0].f, frm, &fflags));
|
rddata[t].f = nan_box(rv_fsqrt_s(rsdata[t][0].f, frm, &fflags));
|
||||||
trace->fpu.type = FpuType::FSQRT;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0x2d: { // RV32D: FSQRT.D
|
trace->fpu.type = FpuType::FSQRT;
|
||||||
rddata[t].f = rv_fsqrt_d(rsdata[t][0].f, frm, &fflags);
|
trace->used_fregs.set(rsrc0);
|
||||||
trace->fpu.type = FpuType::FSQRT;
|
break;
|
||||||
trace->used_fregs.set(rsrc0);
|
}
|
||||||
break;
|
case 0x2d: { // RV32D: FSQRT.D
|
||||||
}
|
rddata[t].f = rv_fsqrt_d(rsdata[t][0].f, frm, &fflags);
|
||||||
case 0x10: {
|
trace->fpu.type = FpuType::FSQRT;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x10: {
|
||||||
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
switch (func3) {
|
switch (func3) {
|
||||||
case 0: // RV32F: FSGNJ.S
|
case 0: // RV32F: FSGNJ.S
|
||||||
rddata[t].f = nan_box(rv_fsgnj_s(rsdata[t][0].f, rsdata[t][1].f));
|
rddata[t].f = nan_box(rv_fsgnj_s(rsdata[t][0].f, rsdata[t][1].f));
|
||||||
@@ -958,29 +970,31 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
rddata[t].f = nan_box(rv_fsgnjx_s(rsdata[t][0].f, rsdata[t][1].f));
|
rddata[t].f = nan_box(rv_fsgnjx_s(rsdata[t][0].f, rsdata[t][1].f));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trace->fpu.type = FpuType::FNCP;
|
}
|
||||||
trace->used_fregs.set(rsrc0);
|
trace->fpu.type = FpuType::FNCP;
|
||||||
trace->used_fregs.set(rsrc1);
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x11: {
|
||||||
|
switch (func3) {
|
||||||
|
case 0: // RV32D: FSGNJ.D
|
||||||
|
rddata[t].f = rv_fsgnj_d(rsdata[t][0].f, rsdata[t][1].f);
|
||||||
|
break;
|
||||||
|
case 1: // RV32D: FSGNJN.D
|
||||||
|
rddata[t].f = rv_fsgnjn_d(rsdata[t][0].f, rsdata[t][1].f);
|
||||||
|
break;
|
||||||
|
case 2: // RV32D: FSGNJX.D
|
||||||
|
rddata[t].f = rv_fsgnjx_d(rsdata[t][0].f, rsdata[t][1].f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x11: {
|
trace->fpu.type = FpuType::FNCP;
|
||||||
switch (func3) {
|
trace->used_fregs.set(rsrc0);
|
||||||
case 0: // RV32D: FSGNJ.D
|
trace->used_fregs.set(rsrc1);
|
||||||
rddata[t].f = rv_fsgnj_d(rsdata[t][0].f, rsdata[t][1].f);
|
break;
|
||||||
break;
|
}
|
||||||
case 1: // RV32D: FSGNJN.D
|
case 0x14: {
|
||||||
rddata[t].f = rv_fsgnjn_d(rsdata[t][0].f, rsdata[t][1].f);
|
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
break;
|
|
||||||
case 2: // RV32D: FSGNJX.D
|
|
||||||
rddata[t].f = rv_fsgnjx_d(rsdata[t][0].f, rsdata[t][1].f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x14: {
|
|
||||||
if (func3) {
|
if (func3) {
|
||||||
// RV32F: FMAX.S
|
// RV32F: FMAX.S
|
||||||
rddata[t].f = nan_box(rv_fmax_s(rsdata[t][0].f, rsdata[t][1].f, &fflags));
|
rddata[t].f = nan_box(rv_fmax_s(rsdata[t][0].f, rsdata[t][1].f, &fflags));
|
||||||
@@ -988,112 +1002,114 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
// RV32F: FMIN.S
|
// RV32F: FMIN.S
|
||||||
rddata[t].f = nan_box(rv_fmin_s(rsdata[t][0].f, rsdata[t][1].f, &fflags));
|
rddata[t].f = nan_box(rv_fmin_s(rsdata[t][0].f, rsdata[t][1].f, &fflags));
|
||||||
}
|
}
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0x15: {
|
trace->fpu.type = FpuType::FNCP;
|
||||||
if (func3) {
|
trace->used_fregs.set(rsrc0);
|
||||||
// RV32D: FMAX.D
|
trace->used_fregs.set(rsrc1);
|
||||||
rddata[t].f = rv_fmax_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
break;
|
||||||
} else {
|
}
|
||||||
// RV32D: FMIN.D
|
case 0x15: {
|
||||||
rddata[t].f = rv_fmin_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
if (func3) {
|
||||||
}
|
// RV32D: FMAX.D
|
||||||
trace->fpu.type = FpuType::FNCP;
|
rddata[t].f = rv_fmax_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
||||||
trace->used_fregs.set(rsrc0);
|
} else {
|
||||||
trace->used_fregs.set(rsrc1);
|
// RV32D: FMIN.D
|
||||||
break;
|
rddata[t].f = rv_fmin_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
||||||
}
|
}
|
||||||
case 0x20: {
|
trace->fpu.type = FpuType::FNCP;
|
||||||
// RV32D: FCVT.S.D
|
trace->used_fregs.set(rsrc0);
|
||||||
rddata[t].f = nan_box(rv_dtof(rsdata[t][0].f));
|
trace->used_fregs.set(rsrc1);
|
||||||
trace->fpu.type = FpuType::FNCP;
|
break;
|
||||||
trace->used_fregs.set(rsrc0);
|
}
|
||||||
trace->used_fregs.set(rsrc1);
|
case 0x20: {
|
||||||
break;
|
// RV32D: FCVT.S.D
|
||||||
|
rddata[t].f = nan_box(rv_dtof(rsdata[t][0].f));
|
||||||
|
trace->fpu.type = FpuType::FNCP;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x21: {
|
||||||
|
// RV32D: FCVT.D.S
|
||||||
|
rddata[t].f = rv_ftod(rsdata[t][0].f);
|
||||||
|
trace->fpu.type = FpuType::FNCP;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x60: {
|
||||||
|
switch (rsrc1) {
|
||||||
|
case 0:
|
||||||
|
// RV32F: FCVT.W.S
|
||||||
|
rddata[t].i = sext((uint64_t)rv_ftoi_s(rsdata[t][0].f, frm, &fflags), 32);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// RV32F: FCVT.WU.S
|
||||||
|
rddata[t].i = sext((uint64_t)rv_ftou_s(rsdata[t][0].f, frm, &fflags), 32);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// RV64F: FCVT.L.S
|
||||||
|
rddata[t].i = rv_ftol_s(rsdata[t][0].f, frm, &fflags);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// RV64F: FCVT.LU.S
|
||||||
|
rddata[t].i = rv_ftolu_s(rsdata[t][0].f, frm, &fflags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case 0x21: {
|
trace->fpu.type = FpuType::FCVT;
|
||||||
// RV32D: FCVT.D.S
|
trace->used_fregs.set(rsrc0);
|
||||||
rddata[t].f = rv_ftod(rsdata[t][0].f);
|
break;
|
||||||
trace->fpu.type = FpuType::FNCP;
|
}
|
||||||
trace->used_fregs.set(rsrc0);
|
case 0x61: {
|
||||||
trace->used_fregs.set(rsrc1);
|
switch (rsrc1) {
|
||||||
break;
|
case 0:
|
||||||
|
// RV32D: FCVT.W.D
|
||||||
|
rddata[t].i = sext((uint64_t)rv_ftoi_d(rsdata[t][0].f, frm, &fflags), 32);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// RV32D: FCVT.WU.D
|
||||||
|
rddata[t].i = sext((uint64_t)rv_ftou_d(rsdata[t][0].f, frm, &fflags), 32);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// RV64D: FCVT.L.D
|
||||||
|
rddata[t].i = rv_ftol_d(rsdata[t][0].f, frm, &fflags);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// RV64D: FCVT.LU.D
|
||||||
|
rddata[t].i = rv_ftolu_d(rsdata[t][0].f, frm, &fflags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case 0x60: {
|
|
||||||
switch (rsrc1) {
|
|
||||||
case 0:
|
|
||||||
// RV32F: FCVT.W.S
|
|
||||||
rddata[t].i = sext((uint64_t)rv_ftoi_s(rsdata[t][0].f, frm, &fflags), 32);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// RV32F: FCVT.WU.S
|
|
||||||
rddata[t].i = sext((uint64_t)rv_ftou_s(rsdata[t][0].f, frm, &fflags), 32);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// RV64F: FCVT.L.S
|
|
||||||
rddata[t].i = rv_ftol_s(rsdata[t][0].f, frm, &fflags);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// RV64F: FCVT.LU.S
|
|
||||||
rddata[t].i = rv_ftolu_s(rsdata[t][0].f, frm, &fflags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FCVT;
|
trace->fpu.type = FpuType::FCVT;
|
||||||
trace->used_fregs.set(rsrc0);
|
trace->used_fregs.set(rsrc0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x61: {
|
case 0x70: {
|
||||||
switch (rsrc1) {
|
if (func3) {
|
||||||
case 0:
|
// RV32F: FCLASS.S
|
||||||
// RV32D: FCVT.W.D
|
rddata[t].i = rv_fclss_s(rsdata[t][0].f);
|
||||||
rddata[t].i = sext(rv_ftoi_d(rsdata[t][0].f, frm, &fflags), 32);
|
} else {
|
||||||
break;
|
// RV32F: FMV.X.W
|
||||||
case 1:
|
uint32_t result = (uint32_t)rsdata[t][0].f;
|
||||||
// RV32D: FCVT.WU.D
|
rddata[t].i = sext((uint64_t)result, 32);
|
||||||
rddata[t].i = sext(rv_ftou_d(rsdata[t][0].f, frm, &fflags), 32);
|
}
|
||||||
break;
|
trace->fpu.type = FpuType::FNCP;
|
||||||
case 2:
|
trace->used_fregs.set(rsrc0);
|
||||||
// RV64D: FCVT.L.D
|
break;
|
||||||
rddata[t].i = rv_ftol_d(rsdata[t][0].f, frm, &fflags);
|
}
|
||||||
break;
|
case 0x71: {
|
||||||
case 3:
|
if (func3) {
|
||||||
// RV64D: FCVT.LU.D
|
// RV32D: FCLASS.D
|
||||||
rddata[t].i = rv_ftolu_d(rsdata[t][0].f, frm, &fflags);
|
rddata[t].i = rv_fclss_d(rsdata[t][0].f);
|
||||||
break;
|
} else {
|
||||||
}
|
// RV64D: FMV.X.D
|
||||||
trace->fpu.type = FpuType::FCVT;
|
rddata[t].i = rsdata[t][0].f;
|
||||||
trace->used_fregs.set(rsrc0);
|
}
|
||||||
break;
|
trace->fpu.type = FpuType::FNCP;
|
||||||
}
|
trace->used_fregs.set(rsrc0);
|
||||||
case 0x70: {
|
break;
|
||||||
if (func3) {
|
}
|
||||||
// RV32F: FCLASS.S
|
case 0x50: {
|
||||||
rddata[t].i = rv_fclss_s(rsdata[t][0].f);
|
if (checkBoxedCmpArgs(&rddata[t].i, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
|
||||||
} else {
|
|
||||||
// RV32F: FMV.X.W
|
|
||||||
uint32_t result = (uint32_t)rsdata[t][0].f;
|
|
||||||
rddata[t].i = sext((uint64_t)result, 32);
|
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x71: {
|
|
||||||
if (func3) {
|
|
||||||
// RV32D: FCLASS.D
|
|
||||||
rddata[t].i = rv_fclss_d(rsdata[t][0].f);
|
|
||||||
} else {
|
|
||||||
// RV64D: FMV.X.D
|
|
||||||
rddata[t].i = rsdata[t][0].f;
|
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x50: {
|
|
||||||
switch (func3) {
|
switch (func3) {
|
||||||
case 0:
|
case 0:
|
||||||
// RV32F: FLE.S
|
// RV32F: FLE.S
|
||||||
@@ -1107,91 +1123,91 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
// RV32F: FEQ.S
|
// RV32F: FEQ.S
|
||||||
rddata[t].i = rv_feq_s(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
rddata[t].i = rv_feq_s(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trace->fpu.type = FpuType::FNCP;
|
}
|
||||||
trace->used_fregs.set(rsrc0);
|
trace->fpu.type = FpuType::FNCP;
|
||||||
trace->used_fregs.set(rsrc1);
|
trace->used_fregs.set(rsrc0);
|
||||||
break;
|
trace->used_fregs.set(rsrc1);
|
||||||
}
|
break;
|
||||||
case 0x51: {
|
}
|
||||||
switch (func3) {
|
case 0x51: {
|
||||||
case 0:
|
switch (func3) {
|
||||||
// RV32D: FLE.D
|
case 0:
|
||||||
rddata[t].i = rv_fle_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
// RV32D: FLE.D
|
||||||
break;
|
rddata[t].i = rv_fle_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
||||||
case 1:
|
break;
|
||||||
// RV32D: FLT.D
|
case 1:
|
||||||
rddata[t].i = rv_flt_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
// RV32D: FLT.D
|
||||||
break;
|
rddata[t].i = rv_flt_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
||||||
case 2:
|
break;
|
||||||
// RV32D: FEQ.D
|
case 2:
|
||||||
rddata[t].i = rv_feq_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
// RV32D: FEQ.D
|
||||||
|
rddata[t].i = rv_feq_d(rsdata[t][0].f, rsdata[t][1].f, &fflags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
trace->fpu.type = FpuType::FNCP;
|
||||||
|
trace->used_fregs.set(rsrc0);
|
||||||
|
trace->used_fregs.set(rsrc1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x68: {
|
||||||
|
switch (rsrc1) {
|
||||||
|
case 0:
|
||||||
|
// RV32F: FCVT.S.W
|
||||||
|
rddata[t].f = nan_box(rv_itof_s(rsdata[t][0].i, frm, &fflags));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// RV32F: FCVT.S.WU
|
||||||
|
rddata[t].f = nan_box(rv_utof_s(rsdata[t][0].i, frm, &fflags));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// RV64F: FCVT.S.L
|
||||||
|
rddata[t].f = nan_box(rv_ltof_s(rsdata[t][0].i, frm, &fflags));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// RV64F: FCVT.S.LU
|
||||||
|
rddata[t].f = nan_box(rv_lutof_s(rsdata[t][0].i, frm, &fflags));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_fregs.set(rsrc0);
|
|
||||||
trace->used_fregs.set(rsrc1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x68: {
|
|
||||||
switch (rsrc1) {
|
|
||||||
case 0:
|
|
||||||
// RV32F: FCVT.S.W
|
|
||||||
rddata[t].f = nan_box(rv_itof_s(rsdata[t][0].i, frm, &fflags));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// RV32F: FCVT.S.WU
|
|
||||||
rddata[t].f = nan_box(rv_utof_s(rsdata[t][0].i, frm, &fflags));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// RV64F: FCVT.S.L
|
|
||||||
rddata[t].f = nan_box(rv_ltof_s(rsdata[t][0].i, frm, &fflags));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// RV64F: FCVT.S.LU
|
|
||||||
rddata[t].f = nan_box(rv_lutof_s(rsdata[t][0].i, frm, &fflags));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FCVT;
|
|
||||||
trace->used_iregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x69: {
|
|
||||||
switch (rsrc1) {
|
|
||||||
case 0:
|
|
||||||
// RV32D: FCVT.D.W
|
|
||||||
rddata[t].f = rv_itof_d(rsdata[t][0].i, frm, &fflags);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// RV32D: FCVT.D.WU
|
|
||||||
rddata[t].f = rv_utof_d(rsdata[t][0].i, frm, &fflags);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// RV64D: FCVT.D.L
|
|
||||||
rddata[t].f = rv_ltof_d(rsdata[t][0].i, frm, &fflags);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// RV64D: FCVT.D.LU
|
|
||||||
rddata[t].f = rv_lutof_d(rsdata[t][0].i, frm, &fflags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
trace->fpu.type = FpuType::FCVT;
|
|
||||||
trace->used_iregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x78: { // RV32F: FMV.W.X
|
|
||||||
rddata[t].f = nan_box((uint32_t)rsdata[t][0].i);
|
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_iregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x79: { // RV64D: FMV.D.X
|
|
||||||
rddata[t].f = rsdata[t][0].i;
|
|
||||||
trace->fpu.type = FpuType::FNCP;
|
|
||||||
trace->used_iregs.set(rsrc0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
trace->fpu.type = FpuType::FCVT;
|
||||||
|
trace->used_iregs.set(rsrc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x69: {
|
||||||
|
switch (rsrc1) {
|
||||||
|
case 0:
|
||||||
|
// RV32D: FCVT.D.W
|
||||||
|
rddata[t].f = rv_itof_d(rsdata[t][0].i, frm, &fflags);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// RV32D: FCVT.D.WU
|
||||||
|
rddata[t].f = rv_utof_d(rsdata[t][0].i, frm, &fflags);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// RV64D: FCVT.D.L
|
||||||
|
rddata[t].f = rv_ltof_d(rsdata[t][0].i, frm, &fflags);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// RV64D: FCVT.D.LU
|
||||||
|
rddata[t].f = rv_lutof_d(rsdata[t][0].i, frm, &fflags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
trace->fpu.type = FpuType::FCVT;
|
||||||
|
trace->used_iregs.set(rsrc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x78: { // RV32F: FMV.W.X
|
||||||
|
rddata[t].f = nan_box((uint32_t)rsdata[t][0].i);
|
||||||
|
trace->fpu.type = FpuType::FNCP;
|
||||||
|
trace->used_iregs.set(rsrc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x79: { // RV64D: FMV.D.X
|
||||||
|
rddata[t].f = rsdata[t][0].i;
|
||||||
|
trace->fpu.type = FpuType::FNCP;
|
||||||
|
trace->used_iregs.set(rsrc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
update_fcrs(fflags, core_, t, id_);
|
update_fcrs(fflags, core_, t, id_);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ run-simx-64imfd:
|
|||||||
|
|
||||||
run-simx-32: run-simx-32imfd
|
run-simx-32: run-simx-32imfd
|
||||||
|
|
||||||
run-simx-64: run-simx-64imfd
|
run-simx-64: run-simx-32imfd run-simx-64imfd
|
||||||
|
|
||||||
run-simx: run-simx-$(XLEN)
|
run-simx: run-simx-$(XLEN)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user