Added RV32D extension

This commit is contained in:
Eyck Jentzsch 2018-04-24 15:33:21 +02:00
parent 48ad30dcae
commit ce98e2ad31
13 changed files with 2452 additions and 276 deletions

View File

@ -0,0 +1,298 @@
import "RV32IBase.core_desc"
InsructionSet RV32D extends RV32IBase{
constants {
FLEN, FFLAG_MASK
}
registers {
[31:0] F[FLEN], FCSR[32]
}
instructions{
FLD {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111;
args_disass:"f%rd$d, %imm%(x%rs1$d)";
val offs[XLEN] <= X[rs1]+imm;
val res[64] <= MEM[offs]{64};
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FSD {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111;
args_disass:"f%rs2$d, %imm%(x%rs1$d)";
val offs[XLEN] <= X[rs1]+imm;
MEM[offs]{64}<=F[rs2]{64};
}
FMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FADD.D {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f + F[rs2]f;
val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSUB.D {
encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f - F[rs2]f;
val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMUL.D {
encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f * F[rs2]f;
val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FDIV.D {
encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f / F[rs2]f;
val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSQRT.D {
encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
//F[rd]f<=sqrt(F[rs1]f);
val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSGNJ.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000);
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FSGNJN.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000);
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FSGNJX.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000);
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FMIN.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMAX.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.S.D {
encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d";
val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8});
// NaN boxing
val upper[FLEN] <= -1;
F[rd] <= upper<<32 | zext(res, FLEN);
}
FCVT.D.S {
encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d";
val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8});
if(FLEN==64){
F[rd] <= res;
} else {
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FEQ.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLT.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLE.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCLASS.D {
encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<=fdispatch_fclass_d(F[rs1]{64});
}
FCVT.W.D {
encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.WU.D {
encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.D.W {
encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d";
val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FCVT.D.WU {
encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d";
val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
}
}

View File

@ -15,9 +15,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= MEM[offs]{32}; val res[32] <= MEM[offs]{32};
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= (-1<<31); val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
} }
FSW { FSW {
@ -33,9 +33,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= (-1<<31); val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
@ -47,9 +47,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= (-1<<31); val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
@ -61,9 +61,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= (-1<<31); val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
@ -75,79 +75,79 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= (-1<<31); val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FADD.S { FADD.S {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f + F[rs2]f; // F[rd]f <= F[rs1]f + F[rs2]f;
val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= (-1<<31); val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FSUB.S { FSUB.S {
encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f - F[rs2]f; // F[rd]f <= F[rs1]f - F[rs2]f;
val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FMUL.S { FMUL.S {
encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f * F[rs2]f; // F[rd]f <= F[rs1]f * F[rs2]f;
val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FDIV.S { FDIV.S {
encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f / F[rs2]f; // F[rd]f <= F[rs1]f / F[rs2]f;
val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FSQRT.S { FSQRT.S {
encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"f%rd$d, f%rs1$d";
//F[rd]f<=sqrt(F[rs1]f); //F[rd]f<=sqrt(F[rs1]f);
val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
@ -158,9 +158,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000); val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000);
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
} }
FSGNJN.S { FSGNJN.S {
@ -169,9 +169,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000); val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000);
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
} }
FSGNJX.S { FSGNJX.S {
@ -180,9 +180,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000); val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000);
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
} }
FMIN.S { FMIN.S {
@ -192,9 +192,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32)); val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
@ -206,9 +206,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32));
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
@ -259,9 +259,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8});
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
} }
FCVT.S.WU { FCVT.S.WU {
@ -270,9 +270,9 @@ InsructionSet RV32F extends RV32IBase{
val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8});
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | res; F[rd] <= (upper<<32) | zext(res, FLEN);
} }
} }
FMV.X.W { FMV.X.W {
@ -285,9 +285,9 @@ InsructionSet RV32F extends RV32IBase{
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f%rd$d, x%rs1$d";
if(FLEN==32) if(FLEN==32)
F[rd] <= X[rs1]; F[rd] <= X[rs1];
else { else { // NaN boxing
val upper[FLEN] <= -1<<31; val upper[FLEN] <= -1;
F[rd] <= upper*2 | X[rs1]; F[rd] <= (upper<<32) | zext(X[rs1], FLEN);
} }
} }
} }

View File

@ -3,6 +3,7 @@ import "RV32M.core_desc"
import "RV32A.core_desc" import "RV32A.core_desc"
import "RV32C.core_desc" import "RV32C.core_desc"
import "RV32F.core_desc" import "RV32F.core_desc"
import "RV32D.core_desc"
import "RV64IBase.core_desc" import "RV64IBase.core_desc"
//import "RV64M.core_desc" //import "RV64M.core_desc"
import "RV64A.core_desc" import "RV64A.core_desc"
@ -26,10 +27,10 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC {
} }
} }
Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC { Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D {
constants { constants {
XLEN:=32; XLEN:=32;
FLEN:=32; FLEN:=64;
XLEN2:=64; XLEN2:=64;
XLEN_BIT_MASK:=0x1f; XLEN_BIT_MASK:=0x1f;
PCLEN:=32; PCLEN:=32;

View File

@ -56,6 +56,8 @@ struct traits<${coreDef.name.toLowerCase()}> {
enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}};
constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0};
enum reg_e {<% enum reg_e {<%
allRegs.each { reg -> allRegs.each { reg ->
if( reg instanceof RegisterFile) { if( reg instanceof RegisterFile) {
@ -99,9 +101,6 @@ struct traits<${coreDef.name.toLowerCase()}> {
enum sreg_flag_e {FLAGS}; enum sreg_flag_e {FLAGS};
enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}}; enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}};
constexpr static bool has_fp_regs = ${allRegs.find {it.name=='FCSR'}!= null ?'true':'false'};
}; };
struct ${coreDef.name.toLowerCase()}: public arch_if { struct ${coreDef.name.toLowerCase()}: public arch_if {

View File

@ -50,7 +50,7 @@
namespace iss { namespace iss {
namespace vm { namespace vm {
namespace fp_impl{ namespace fp_impl{
void add_fp_functions_2_module(llvm::Module *mod); void add_fp_functions_2_module(llvm::Module *, unsigned);
} }
} }
@ -89,7 +89,7 @@ protected:
void setup_module(llvm::Module* m) override { void setup_module(llvm::Module* m) override {
super::setup_module(m); super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m); vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
} }
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal,

View File

@ -48,7 +48,9 @@ struct traits<rv32gc> {
constexpr static char const* const core_type = "RV32GC"; constexpr static char const* const core_type = "RV32GC";
enum constants {XLEN=32, FLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095, FFLAG_MASK=31}; enum constants {XLEN=32, FLEN=64, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095, FFLAG_MASK=31};
constexpr static unsigned FP_REGS_SIZE = 64;
enum reg_e { enum reg_e {
X0, X0,
@ -136,12 +138,12 @@ struct traits<rv32gc> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { constexpr static unsigned reg_bit_width(unsigned r) {
constexpr std::array<const uint32_t, 71> RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}}; constexpr std::array<const uint32_t, 71> RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,64}};
return RV32GC_reg_size[r]; return RV32GC_reg_size[r];
} }
constexpr static unsigned reg_byte_offset(unsigned r) { constexpr static unsigned reg_byte_offset(unsigned r) {
constexpr std::array<const uint32_t, 72> RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,288}}; constexpr std::array<const uint32_t, 72> RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,416,424}};
return RV32GC_reg_byte_offset[r]; return RV32GC_reg_byte_offset[r];
} }
@ -150,9 +152,6 @@ struct traits<rv32gc> {
enum sreg_flag_e {FLAGS}; enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM, CSR, FENCE, RES}; enum mem_type_e {MEM, CSR, FENCE, RES};
constexpr static bool has_fp_regs = true;
}; };
struct rv32gc: public arch_if { struct rv32gc: public arch_if {
@ -227,38 +226,38 @@ protected:
uint32_t X30 = 0; uint32_t X30 = 0;
uint32_t X31 = 0; uint32_t X31 = 0;
uint32_t PC = 0; uint32_t PC = 0;
uint32_t F0 = 0; uint64_t F0 = 0;
uint32_t F1 = 0; uint64_t F1 = 0;
uint32_t F2 = 0; uint64_t F2 = 0;
uint32_t F3 = 0; uint64_t F3 = 0;
uint32_t F4 = 0; uint64_t F4 = 0;
uint32_t F5 = 0; uint64_t F5 = 0;
uint32_t F6 = 0; uint64_t F6 = 0;
uint32_t F7 = 0; uint64_t F7 = 0;
uint32_t F8 = 0; uint64_t F8 = 0;
uint32_t F9 = 0; uint64_t F9 = 0;
uint32_t F10 = 0; uint64_t F10 = 0;
uint32_t F11 = 0; uint64_t F11 = 0;
uint32_t F12 = 0; uint64_t F12 = 0;
uint32_t F13 = 0; uint64_t F13 = 0;
uint32_t F14 = 0; uint64_t F14 = 0;
uint32_t F15 = 0; uint64_t F15 = 0;
uint32_t F16 = 0; uint64_t F16 = 0;
uint32_t F17 = 0; uint64_t F17 = 0;
uint32_t F18 = 0; uint64_t F18 = 0;
uint32_t F19 = 0; uint64_t F19 = 0;
uint32_t F20 = 0; uint64_t F20 = 0;
uint32_t F21 = 0; uint64_t F21 = 0;
uint32_t F22 = 0; uint64_t F22 = 0;
uint32_t F23 = 0; uint64_t F23 = 0;
uint32_t F24 = 0; uint64_t F24 = 0;
uint32_t F25 = 0; uint64_t F25 = 0;
uint32_t F26 = 0; uint64_t F26 = 0;
uint32_t F27 = 0; uint64_t F27 = 0;
uint32_t F28 = 0; uint64_t F28 = 0;
uint32_t F29 = 0; uint64_t F29 = 0;
uint32_t F30 = 0; uint64_t F30 = 0;
uint32_t F31 = 0; uint64_t F31 = 0;
uint32_t FCSR = 0; uint32_t FCSR = 0;
uint32_t NEXT_PC = 0; uint32_t NEXT_PC = 0;
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0; uint32_t trap_state = 0, pending_trap = 0, machine_state = 0;

View File

@ -50,6 +50,8 @@ struct traits<rv32imac> {
enum constants {XLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095}; enum constants {XLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095};
constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e { enum reg_e {
X0, X0,
X1, X1,
@ -117,9 +119,6 @@ struct traits<rv32imac> {
enum sreg_flag_e {FLAGS}; enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM, CSR, FENCE, RES}; enum mem_type_e {MEM, CSR, FENCE, RES};
constexpr static bool has_fp_regs = false;
}; };
struct rv32imac: public arch_if { struct rv32imac: public arch_if {

View File

@ -50,6 +50,8 @@ struct traits<rv64ia> {
enum constants {XLEN=64, XLEN2=128, XLEN_BIT_MASK=63, PCLEN=64, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=2147746049, PGSIZE=4096, PGMASK=4095}; enum constants {XLEN=64, XLEN2=128, XLEN_BIT_MASK=63, PCLEN=64, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=2147746049, PGSIZE=4096, PGMASK=4095};
constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e { enum reg_e {
X0, X0,
X1, X1,
@ -117,9 +119,6 @@ struct traits<rv64ia> {
enum sreg_flag_e {FLAGS}; enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM, CSR, FENCE, RES}; enum mem_type_e {MEM, CSR, FENCE, RES};
constexpr static bool has_fp_regs = false;
}; };
struct rv64ia: public arch_if { struct rv64ia: public arch_if {

View File

@ -41,6 +41,8 @@ extern "C" {
#include "specialize.h" #include "specialize.h"
} }
#include <limits>
namespace iss { namespace iss {
namespace vm { namespace vm {
namespace fp_impl { namespace fp_impl {
@ -68,7 +70,8 @@ using namespace std;
using namespace llvm; using namespace llvm;
void add_fp_functions_2_module(Module *mod) { void add_fp_functions_2_module(Module *mod, uint32_t flen) {
if(flen){
FDECL(fget_flags, INT_TYPE(32)); FDECL(fget_flags, INT_TYPE(32));
FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
@ -77,9 +80,24 @@ void add_fp_functions_2_module(Module *mod) {
FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32)); FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32));
if(flen>32){
FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fmul_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fdiv_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fsqrt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
FDECL(fcmp_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
FDECL(fcvt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
}
}
} }
} }
@ -202,14 +220,14 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod
softfloat_roundingMode=rmm_map[mode&0x7]; softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0; softfloat_exceptionFlags=0;
float32_t res = softfloat_mulAddF32(v1, v2, v3, op&0x1); float32_t res = softfloat_mulAddF32(v1, v2, v3, op&0x1);
if(op>1) res.v ^= 0x80000000UL; if(op>1) res.v ^= 1ULL<<31;
return res.v; return res.v;
} }
uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) { uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) {
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
bool v1_nan = (v1 & defaultNaNF32UI) == quiet_nan32; bool v1_nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI;
bool v2_nan = (v2 & defaultNaNF32UI) == quiet_nan32; bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI;
bool v1_snan = softfloat_isSigNaNF32UI(v1); bool v1_snan = softfloat_isSigNaNF32UI(v1);
bool v2_snan = softfloat_isSigNaNF32UI(v2); bool v2_snan = softfloat_isSigNaNF32UI(v2);
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid);
@ -257,6 +275,156 @@ uint32_t fclass_s( uint32_t v1 ){
( isNaN && !isSNaN ) << 9; ( isNaN && !isSNaN ) << 9;
} }
uint32_t fconv_d2f(uint64_t v1, uint8_t mode){
softfloat_roundingMode=rmm_map[mode&0x7];
bool nan = (v1 & defaultNaNF64UI)==defaultNaNF64UI;
if(nan){
return defaultNaNF32UI;
} else {
float32_t res = f64_to_f32(float64_t{v1});
return res.v;
}
}
uint64_t fconv_f2d(uint32_t v1, uint8_t mode){
bool nan = (v1 & defaultNaNF32UI)==defaultNaNF32UI;
if(nan){
return defaultNaNF64UI;
} else {
softfloat_roundingMode=rmm_map[mode&0x7];
float64_t res = f32_to_f64(float32_t{v1});
return res.v;
}
}
uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) {
bool nan = (v1&defaultNaNF32UI)==quiet_nan32;
bool snan = softfloat_isSigNaNF32UI(v1);
float64_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float64_t r =f64_add(v1f, v2f);
return r.v;
}
uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float64_t r=f64_sub(v1f, v2f);
return r.v;
}
uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float64_t r=f64_mul(v1f, v2f);
return r.v;
}
uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float64_t r=f64_div(v1f, v2f);
return r.v;
}
uint64_t fsqrt_d(uint64_t v1, uint8_t mode) {
float64_t v1f{v1};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float64_t r=f64_sqrt(v1f);
return r.v;
}
uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
float64_t v1f{v1},v2f{v2};
softfloat_exceptionFlags=0;
bool nan = (v1&defaultNaNF64UI)==quiet_nan32 || (v2&defaultNaNF64UI)==quiet_nan32;
bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2);
switch(op){
case 0:
if(nan | snan){
if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f64_eq(v1f,v2f )?1:0;
case 1:
if(nan | snan){
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f64_le(v1f,v2f )?1:0;
case 2:
if(nan | snan){
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f64_lt(v1f,v2f )?1:0;
default:
break;
}
return -1;
}
uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
float64_t v1f{v1};
softfloat_exceptionFlags=0;
float64_t r;
int32_t res;
switch(op){
case 0: //w->s, fp to int32
res = f64_to_i64(v1f,rmm_map[mode&0x7],true);
return (uint64_t)res;
case 1: //wu->s
return f64_to_ui64(v1f,rmm_map[mode&0x7],true);
case 2: //s->w
r=i64_to_f64(v1);
return r.v;
case 3: //s->wu
r=ui64_to_f64(v1);
return r.v;
}
return 0;
}
uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) {
// op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)}
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float64_t res = softfloat_mulAddF64(v1, v2, v3, op&0x1);
if(op>1) res.v ^= 1ULL<<63;
return res.v;
}
uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) {
softfloat_exceptionFlags = 0;
bool v1_nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI;
bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI;
bool v1_snan = softfloat_isSigNaNF64UI(v1);
bool v2_snan = softfloat_isSigNaNF64UI(v2);
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid);
if (v1_nan || v1_snan)
return (v2_nan || v2_snan) ? defaultNaNF64UI : v2;
else
if (v2_nan || v2_snan)
return v1;
else {
if ((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) {
return op == 0 ?
((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2) :
((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1);
} else {
float64_t v1f{ v1 }, v2f{ v2 };
return op == 0 ?
(f64_lt(v1f, v2f) ? v1 : v2) :
(f64_lt(v1f, v2f) ? v2 : v1);
}
}
}
uint64_t fclass_d(uint64_t v1 ){ uint64_t fclass_d(uint64_t v1 ){
float64_t a{v1}; float64_t a{v1};

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@
namespace iss { namespace iss {
namespace vm { namespace vm {
namespace fp_impl{ namespace fp_impl{
void add_fp_functions_2_module(llvm::Module *mod); void add_fp_functions_2_module(llvm::Module *, unsigned);
} }
} }
@ -89,7 +89,7 @@ protected:
void setup_module(llvm::Module* m) override { void setup_module(llvm::Module* m) override {
super::setup_module(m); super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m); vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
} }
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal,

View File

@ -50,7 +50,7 @@
namespace iss { namespace iss {
namespace vm { namespace vm {
namespace fp_impl{ namespace fp_impl{
void add_fp_functions_2_module(llvm::Module *mod); void add_fp_functions_2_module(llvm::Module *, unsigned);
} }
} }
@ -89,7 +89,7 @@ protected:
void setup_module(llvm::Module* m) override { void setup_module(llvm::Module* m) override {
super::setup_module(m); super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m); vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
} }
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal,

View File

@ -51,23 +51,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| The values to return on conversions to 32-bit integer formats that raise an | The values to return on conversions to 32-bit integer formats that raise an
| invalid exception. | invalid exception.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromPosOverflow UINT32_C(0xFFFFFFFF)
#define ui32_fromNegOverflow 0x0 #define ui32_fromNegOverflow UINT32_C(0x0)
#define ui32_fromNaN 0xFFFFFFFF #define ui32_fromNaN UINT32_C(0xFFFFFFFF)
#define i32_fromPosOverflow (0x7FFFFFFF) #define i32_fromPosOverflow INT64_C(0x7FFFFFFF)
#define i32_fromNegOverflow (-0x7FFFFFFF - 1) #define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF)-1)
#define i32_fromNaN (0x7FFFFFFF) #define i32_fromNaN INT64_C(0x7FFFFFFF)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The values to return on conversions to 64-bit integer formats that raise an | The values to return on conversions to 64-bit integer formats that raise an
| invalid exception. | invalid exception.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) #define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) #define ui64_fromNegOverflow UINT64_C( 0x0 )
#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF) #define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF)
#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) #define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF)
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF)-1) #define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF)-1)
#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) #define i64_fromNaN INT64_C( 0x7FFFFFFFFFFFFFFF)
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| "Common NaN" structure, used to transfer NaN representations from one format | "Common NaN" structure, used to transfer NaN representations from one format
@ -155,7 +155,7 @@ uint_fast32_t
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN. | The bit pattern for a default generated 64-bit floating-point NaN.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) #define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a