riscv: [Patch 3/5] Added RISCV floating point extensions RV64FD
Third of five patches adding RISC-V to GEM5. This patch adds the RV64FD extensions, which include single- and double-precision floating point instructions. Patch 1 introduced RISC-V and implemented the base instruction set, RV64I and patch 2 implemented the integer multiply extension, RV64M. Patch 4 will implement the atomic memory instructions, RV64A, and patch 5 will add support for timing, minor, and detailed CPU models that is missing from the first four patches. [Fixed exception handling in floating-point instructions to conform better to IEEE-754 2008 standard and behavior of the Chisel-generated RISC-V simulator.] [Fixed style errors in decoder.isa.] [Fixed some fuzz caused by modifying a previous patch.] Signed-off by: Alec Roelke Signed-off by: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
parent
070da98493
commit
1229b3b623
10 changed files with 1057 additions and 1 deletions
|
@ -71,6 +71,13 @@ UnimplementedFault::invoke_se(ThreadContext *tc,
|
|||
tc->pcState().pc());
|
||||
}
|
||||
|
||||
void
|
||||
IllegalFrmFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
{
|
||||
panic("Illegal floating-point rounding mode 0x%x at pc 0x%016llx.",
|
||||
frm, tc->pcState().pc());
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,12 @@
|
|||
namespace RiscvISA
|
||||
{
|
||||
|
||||
const uint32_t FloatInexact = 1 << 0;
|
||||
const uint32_t FloatUnderflow = 1 << 1;
|
||||
const uint32_t FloatOverflow = 1 << 2;
|
||||
const uint32_t FloatDivZero = 1 << 3;
|
||||
const uint32_t FloatInvalid = 1 << 4;
|
||||
|
||||
enum ExceptionCode {
|
||||
INST_ADDR_MISALIGNED = 0,
|
||||
INST_ACCESS = 1,
|
||||
|
@ -124,6 +130,20 @@ class UnimplementedFault : public RiscvFault
|
|||
invoke_se(ThreadContext *tc, const StaticInstPtr &inst);
|
||||
};
|
||||
|
||||
class IllegalFrmFault: public RiscvFault
|
||||
{
|
||||
private:
|
||||
const uint8_t frm;
|
||||
public:
|
||||
IllegalFrmFault(uint8_t r)
|
||||
: RiscvFault("Illegal floating-point rounding mode", INST_ILLEGAL,
|
||||
SOFTWARE),
|
||||
frm(r)
|
||||
{}
|
||||
|
||||
void invoke_se(ThreadContext *tc, const StaticInstPtr &inst);
|
||||
};
|
||||
|
||||
class BreakpointFault : public RiscvFault
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -75,3 +75,13 @@ def bitfield UJIMMBITS19TO12 <19:12>;
|
|||
// System
|
||||
def bitfield FUNCT12 <31:20>;
|
||||
def bitfield ZIMM <19:15>;
|
||||
|
||||
// Floating point
|
||||
def bitfield FD <11:7>;
|
||||
def bitfield FS1 <19:15>;
|
||||
def bitfield FS2 <24:20>;
|
||||
def bitfield FS3 <31:27>;
|
||||
|
||||
def bitfield ROUND_MODE <14:12>;
|
||||
def bitfield CONV_SGN <24:20>;
|
||||
def bitfield FUNCT2 <26:25>;
|
||||
|
|
|
@ -61,6 +61,17 @@ decode OPCODE default Unknown::unknown() {
|
|||
}
|
||||
}
|
||||
|
||||
0x07: decode FUNCT3 {
|
||||
format Load {
|
||||
0x2: flw({{
|
||||
Fd_bits = (uint64_t)Mem_uw;
|
||||
}});
|
||||
0x3: fld({{
|
||||
Fd_bits = Mem;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
0x0f: decode FUNCT3 {
|
||||
format IOp {
|
||||
0x0: fence({{
|
||||
|
@ -144,6 +155,17 @@ decode OPCODE default Unknown::unknown() {
|
|||
}
|
||||
}
|
||||
|
||||
0x27: decode FUNCT3 {
|
||||
format Store {
|
||||
0x2: fsw({{
|
||||
Mem_uw = (uint32_t)Fs2_bits;
|
||||
}});
|
||||
0x3: fsd({{
|
||||
Mem_ud = Fs2_bits;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
0x33: decode FUNCT3 {
|
||||
format ROp {
|
||||
0x0: decode FUNCT7 {
|
||||
|
@ -347,6 +369,813 @@ decode OPCODE default Unknown::unknown() {
|
|||
}
|
||||
}
|
||||
|
||||
format FPR4Op {
|
||||
0x43: decode FUNCT2 {
|
||||
0x0: fmadd_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fs3 = reinterpret_cast<float&>(temp = Fs3_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)
|
||||
|| issignalingnan(fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else if (std::isinf(fs1) || std::isinf(fs2) ||
|
||||
std::isinf(fs3)) {
|
||||
if (std::signbit(fs1) == std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = std::numeric_limits<float>::infinity();
|
||||
} else if (std::signbit(fs1) != std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = -std::numeric_limits<float>::infinity();
|
||||
} else { // Fs3_sf is infinity
|
||||
fd = fs3;
|
||||
}
|
||||
} else {
|
||||
fd = fs1*fs2 + fs3;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatMultOp);
|
||||
0x1: fmadd_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)
|
||||
|| issignalingnan(Fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else if (std::isinf(Fs1) || std::isinf(Fs2) ||
|
||||
std::isinf(Fs3)) {
|
||||
if (std::signbit(Fs1) == std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = std::numeric_limits<double>::infinity();
|
||||
} else if (std::signbit(Fs1) != std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = -std::numeric_limits<double>::infinity();
|
||||
} else {
|
||||
Fd = Fs3;
|
||||
}
|
||||
} else {
|
||||
Fd = Fs1*Fs2 + Fs3;
|
||||
}
|
||||
}}, FloatMultOp);
|
||||
}
|
||||
0x47: decode FUNCT2 {
|
||||
0x0: fmsub_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fs3 = reinterpret_cast<float&>(temp = Fs3_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)
|
||||
|| issignalingnan(fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else if (std::isinf(fs1) || std::isinf(fs2) ||
|
||||
std::isinf(fs3)) {
|
||||
if (std::signbit(fs1) == std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = std::numeric_limits<float>::infinity();
|
||||
} else if (std::signbit(fs1) != std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = -std::numeric_limits<float>::infinity();
|
||||
} else { // Fs3_sf is infinity
|
||||
fd = -fs3;
|
||||
}
|
||||
} else {
|
||||
fd = fs1*fs2 - fs3;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatMultOp);
|
||||
0x1: fmsub_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)
|
||||
|| issignalingnan(Fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else if (std::isinf(Fs1) || std::isinf(Fs2) ||
|
||||
std::isinf(Fs3)) {
|
||||
if (std::signbit(Fs1) == std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = std::numeric_limits<double>::infinity();
|
||||
} else if (std::signbit(Fs1) != std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = -std::numeric_limits<double>::infinity();
|
||||
} else {
|
||||
Fd = -Fs3;
|
||||
}
|
||||
} else {
|
||||
Fd = Fs1*Fs2 - Fs3;
|
||||
}
|
||||
}}, FloatMultOp);
|
||||
}
|
||||
0x4b: decode FUNCT2 {
|
||||
0x0: fnmsub_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fs3 = reinterpret_cast<float&>(temp = Fs3_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)
|
||||
|| issignalingnan(fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else if (std::isinf(fs1) || std::isinf(fs2) ||
|
||||
std::isinf(fs3)) {
|
||||
if (std::signbit(fs1) == std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = -std::numeric_limits<float>::infinity();
|
||||
} else if (std::signbit(fs1) != std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = std::numeric_limits<float>::infinity();
|
||||
} else { // Fs3_sf is infinity
|
||||
fd = fs3;
|
||||
}
|
||||
} else {
|
||||
fd = -(fs1*fs2 - fs3);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatMultOp);
|
||||
0x1: fnmsub_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)
|
||||
|| issignalingnan(Fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else if (std::isinf(Fs1) || std::isinf(Fs2)
|
||||
|| std::isinf(Fs3)) {
|
||||
if (std::signbit(Fs1) == std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = -std::numeric_limits<double>::infinity();
|
||||
} else if (std::signbit(Fs1) != std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = std::numeric_limits<double>::infinity();
|
||||
} else {
|
||||
Fd = Fs3;
|
||||
}
|
||||
} else {
|
||||
Fd = -(Fs1*Fs2 - Fs3);
|
||||
}
|
||||
}}, FloatMultOp);
|
||||
}
|
||||
0x4f: decode FUNCT2 {
|
||||
0x0: fnmadd_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fs3 = reinterpret_cast<float&>(temp = Fs3_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)
|
||||
|| issignalingnan(fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else if (std::isinf(fs1) || std::isinf(fs2) ||
|
||||
std::isinf(fs3)) {
|
||||
if (std::signbit(fs1) == std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = -std::numeric_limits<float>::infinity();
|
||||
} else if (std::signbit(fs1) != std::signbit(fs2)
|
||||
&& !std::isinf(fs3)) {
|
||||
fd = std::numeric_limits<float>::infinity();
|
||||
} else { // Fs3_sf is infinity
|
||||
fd = -fs3;
|
||||
}
|
||||
} else {
|
||||
fd = -(fs1*fs2 + fs3);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatMultOp);
|
||||
0x1: fnmadd_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)
|
||||
|| issignalingnan(Fs3)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else if (std::isinf(Fs1) || std::isinf(Fs2) ||
|
||||
std::isinf(Fs3)) {
|
||||
if (std::signbit(Fs1) == std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = -std::numeric_limits<double>::infinity();
|
||||
} else if (std::signbit(Fs1) != std::signbit(Fs2)
|
||||
&& !std::isinf(Fs3)) {
|
||||
Fd = std::numeric_limits<double>::infinity();
|
||||
} else {
|
||||
Fd = -Fs3;
|
||||
}
|
||||
} else {
|
||||
Fd = -(Fs1*Fs2 + Fs3);
|
||||
}
|
||||
}}, FloatMultOp);
|
||||
}
|
||||
}
|
||||
|
||||
0x53: decode FUNCT7 {
|
||||
format FPROp {
|
||||
0x0: fadd_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else {
|
||||
fd = fs1 + fs2;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatAddOp);
|
||||
0x1: fadd_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
Fd = Fs1 + Fs2;
|
||||
}
|
||||
}}, FloatAddOp);
|
||||
0x4: fsub_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else {
|
||||
fd = fs1 - fs2;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatAddOp);
|
||||
0x5: fsub_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
Fd = Fs1 - Fs2;
|
||||
}
|
||||
}}, FloatAddOp);
|
||||
0x8: fmul_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else {
|
||||
fd = fs1*fs2;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatMultOp);
|
||||
0x9: fmul_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
Fd = Fs1*Fs2;
|
||||
}
|
||||
}}, FloatMultOp);
|
||||
0xc: fdiv_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2)) {
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
} else {
|
||||
fd = fs1/fs2;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatDivOp);
|
||||
0xd: fdiv_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2)) {
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
Fd = Fs1/Fs2;
|
||||
}
|
||||
}}, FloatDivOp);
|
||||
0x10: decode ROUND_MODE {
|
||||
0x0: fsgnj_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (issignalingnan(fs1)) {
|
||||
fd = std::numeric_limits<float>::signaling_NaN();
|
||||
std::feclearexcept(FE_INVALID);
|
||||
} else {
|
||||
fd = std::copysign(fs1, fs2);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}});
|
||||
0x1: fsgnjn_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (issignalingnan(fs1)) {
|
||||
fd = std::numeric_limits<float>::signaling_NaN();
|
||||
std::feclearexcept(FE_INVALID);
|
||||
} else {
|
||||
fd = std::copysign(fs1, -fs2);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}});
|
||||
0x2: fsgnjx_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (issignalingnan(fs1)) {
|
||||
fd = std::numeric_limits<float>::signaling_NaN();
|
||||
std::feclearexcept(FE_INVALID);
|
||||
} else {
|
||||
fd = fs1*(std::signbit(fs2) ? -1.0 : 1.0);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}});
|
||||
}
|
||||
0x11: decode ROUND_MODE {
|
||||
0x0: fsgnj_d({{
|
||||
if (issignalingnan(Fs1)) {
|
||||
Fd = std::numeric_limits<double>::signaling_NaN();
|
||||
std::feclearexcept(FE_INVALID);
|
||||
} else {
|
||||
Fd = std::copysign(Fs1, Fs2);
|
||||
}
|
||||
}});
|
||||
0x1: fsgnjn_d({{
|
||||
if (issignalingnan(Fs1)) {
|
||||
Fd = std::numeric_limits<double>::signaling_NaN();
|
||||
std::feclearexcept(FE_INVALID);
|
||||
} else {
|
||||
Fd = std::copysign(Fs1, -Fs2);
|
||||
}
|
||||
}});
|
||||
0x2: fsgnjx_d({{
|
||||
if (issignalingnan(Fs1)) {
|
||||
Fd = std::numeric_limits<double>::signaling_NaN();
|
||||
std::feclearexcept(FE_INVALID);
|
||||
} else {
|
||||
Fd = Fs1*(std::signbit(Fs2) ? -1.0 : 1.0);
|
||||
}
|
||||
}});
|
||||
}
|
||||
0x14: decode ROUND_MODE {
|
||||
0x0: fmin_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (issignalingnan(fs2)) {
|
||||
fd = fs1;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else if (issignalingnan(fs1)) {
|
||||
fd = fs2;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
fd = std::fmin(fs1, fs2);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatCmpOp);
|
||||
0x1: fmax_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
float fd;
|
||||
|
||||
if (issignalingnan(fs2)) {
|
||||
fd = fs1;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else if (issignalingnan(fs1)) {
|
||||
fd = fs2;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
fd = std::fmax(fs1, fs2);
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatCmpOp);
|
||||
}
|
||||
0x15: decode ROUND_MODE {
|
||||
0x0: fmin_d({{
|
||||
if (issignalingnan(Fs2)) {
|
||||
Fd = Fs1;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else if (issignalingnan(Fs1)) {
|
||||
Fd = Fs2;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Fd = std::fmin(Fs1, Fs2);
|
||||
}
|
||||
}}, FloatCmpOp);
|
||||
0x1: fmax_d({{
|
||||
if (issignalingnan(Fs2)) {
|
||||
Fd = Fs1;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else if (issignalingnan(Fs1)) {
|
||||
Fd = Fs2;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Fd = std::fmax(Fs1, Fs2);
|
||||
}
|
||||
}}, FloatCmpOp);
|
||||
}
|
||||
0x20: fcvt_s_d({{
|
||||
assert(CONV_SGN == 1);
|
||||
float fd;
|
||||
if (issignalingnan(Fs1)) {
|
||||
fd = std::numeric_limits<float>::quiet_NaN();
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
fd = (float)Fs1;
|
||||
}
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatCvtOp);
|
||||
0x21: fcvt_d_s({{
|
||||
assert(CONV_SGN == 0);
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
|
||||
if (issignalingnan(fs1)) {
|
||||
Fd = std::numeric_limits<double>::quiet_NaN();
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Fd = (double)fs1;
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x2c: fsqrt_s({{
|
||||
assert(RS2 == 0);
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fd;
|
||||
|
||||
if (issignalingnan(Fs1_sf)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
fd = std::sqrt(fs1);
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
|
||||
}}, FloatSqrtOp);
|
||||
0x2d: fsqrt_d({{
|
||||
assert(RS2 == 0);
|
||||
Fd = std::sqrt(Fs1);
|
||||
}}, FloatSqrtOp);
|
||||
0x50: decode ROUND_MODE {
|
||||
0x0: fle_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
Rd = 0;
|
||||
} else {
|
||||
Rd = fs1 <= fs2 ? 1 : 0;
|
||||
}
|
||||
}}, FloatCmpOp);
|
||||
0x1: flt_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
|
||||
if (std::isnan(fs1) || std::isnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
Rd = 0;
|
||||
} else {
|
||||
Rd = fs1 < fs2 ? 1 : 0;
|
||||
}
|
||||
}}, FloatCmpOp);
|
||||
0x2: feq_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
|
||||
|
||||
if (issignalingnan(fs1) || issignalingnan(fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Rd = fs1 == fs2 ? 1 : 0;
|
||||
}}, FloatCmpOp);
|
||||
}
|
||||
0x51: decode ROUND_MODE {
|
||||
0x0: fle_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
Rd = 0;
|
||||
} else {
|
||||
Rd = Fs1 <= Fs2 ? 1 : 0;
|
||||
}
|
||||
}}, FloatCmpOp);
|
||||
0x1: flt_d({{
|
||||
if (std::isnan(Fs1) || std::isnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
Rd = 0;
|
||||
} else {
|
||||
Rd = Fs1 < Fs2 ? 1 : 0;
|
||||
}
|
||||
}}, FloatCmpOp);
|
||||
0x2: feq_d({{
|
||||
if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
Rd = Fs1 == Fs2 ? 1 : 0;
|
||||
}}, FloatCmpOp);
|
||||
}
|
||||
0x60: decode CONV_SGN {
|
||||
0x0: fcvt_w_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
|
||||
if (std::isnan(fs1)) {
|
||||
Rd_sd = std::numeric_limits<int32_t>::max();
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Rd_sd = (int32_t)fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
if (std::signbit(fs1)) {
|
||||
Rd_sd = std::numeric_limits<int32_t>::min();
|
||||
} else {
|
||||
Rd_sd = std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x1: fcvt_wu_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
|
||||
if (fs1 < 0.0) {
|
||||
Rd = 0;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Rd = (uint32_t)fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
Rd = std::numeric_limits<uint64_t>::max();
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x2: fcvt_l_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
|
||||
if (std::isnan(fs1)) {
|
||||
Rd_sd = std::numeric_limits<int64_t>::max();
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Rd_sd = (int64_t)fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
if (std::signbit(fs1)) {
|
||||
Rd_sd = std::numeric_limits<int64_t>::min();
|
||||
} else {
|
||||
Rd_sd = std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x3: fcvt_lu_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
|
||||
if (fs1 < 0.0) {
|
||||
Rd = 0;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Rd = (uint64_t)fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
Rd = std::numeric_limits<uint64_t>::max();
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
}
|
||||
0x61: decode CONV_SGN {
|
||||
0x0: fcvt_w_d({{
|
||||
Rd_sd = (int32_t)Fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
if (Fs1 < 0.0) {
|
||||
Rd_sd = std::numeric_limits<int32_t>::min();
|
||||
} else {
|
||||
Rd_sd = std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x1: fcvt_wu_d({{
|
||||
if (Fs1 < 0.0) {
|
||||
Rd = 0;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Rd = (uint32_t)Fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
Rd = std::numeric_limits<uint64_t>::max();
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x2: fcvt_l_d({{
|
||||
Rd_sd = Fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
if (Fs1 < 0.0) {
|
||||
Rd_sd = std::numeric_limits<int64_t>::min();
|
||||
} else {
|
||||
Rd_sd = std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x3: fcvt_lu_d({{
|
||||
if (Fs1 < 0.0) {
|
||||
Rd = 0;
|
||||
FFLAGS |= FloatInvalid;
|
||||
} else {
|
||||
Rd = (uint64_t)Fs1;
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
Rd = std::numeric_limits<uint64_t>::max();
|
||||
std::feclearexcept(FE_INEXACT);
|
||||
}
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
}
|
||||
0x68: decode CONV_SGN {
|
||||
0x0: fcvt_s_w({{
|
||||
float temp = (float)Rs1_sw;
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(temp);
|
||||
}}, FloatCvtOp);
|
||||
0x1: fcvt_s_wu({{
|
||||
float temp = (float)Rs1_uw;
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(temp);
|
||||
}}, FloatCvtOp);
|
||||
0x2: fcvt_s_l({{
|
||||
float temp = (float)Rs1_sd;
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(temp);
|
||||
}}, FloatCvtOp);
|
||||
0x3: fcvt_s_lu({{
|
||||
float temp = (float)Rs1;
|
||||
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(temp);
|
||||
}}, FloatCvtOp);
|
||||
}
|
||||
0x69: decode CONV_SGN {
|
||||
0x0: fcvt_d_w({{
|
||||
Fd = (double)Rs1_sw;
|
||||
}}, FloatCvtOp);
|
||||
0x1: fcvt_d_wu({{
|
||||
Fd = (double)Rs1_uw;
|
||||
}}, FloatCvtOp);
|
||||
0x2: fcvt_d_l({{
|
||||
Fd = (double)Rs1_sd;
|
||||
}}, FloatCvtOp);
|
||||
0x3: fcvt_d_lu({{
|
||||
Fd = (double)Rs1;
|
||||
}}, FloatCvtOp);
|
||||
}
|
||||
0x70: decode ROUND_MODE {
|
||||
0x0: fmv_x_s({{
|
||||
Rd = (uint32_t)Fs1_bits;
|
||||
if ((Rd&0x80000000) != 0) {
|
||||
Rd |= (0xFFFFFFFFULL << 32);
|
||||
}
|
||||
}}, FloatCvtOp);
|
||||
0x1: fclass_s({{
|
||||
uint32_t temp;
|
||||
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
|
||||
switch (std::fpclassify(fs1)) {
|
||||
case FP_INFINITE:
|
||||
if (std::signbit(fs1)) {
|
||||
Rd = 1 << 0;
|
||||
} else {
|
||||
Rd = 1 << 7;
|
||||
}
|
||||
break;
|
||||
case FP_NAN:
|
||||
if (issignalingnan(fs1)) {
|
||||
Rd = 1 << 8;
|
||||
} else {
|
||||
Rd = 1 << 9;
|
||||
}
|
||||
break;
|
||||
case FP_ZERO:
|
||||
if (std::signbit(fs1)) {
|
||||
Rd = 1 << 3;
|
||||
} else {
|
||||
Rd = 1 << 4;
|
||||
}
|
||||
break;
|
||||
case FP_SUBNORMAL:
|
||||
if (std::signbit(fs1)) {
|
||||
Rd = 1 << 2;
|
||||
} else {
|
||||
Rd = 1 << 5;
|
||||
}
|
||||
break;
|
||||
case FP_NORMAL:
|
||||
if (std::signbit(fs1)) {
|
||||
Rd = 1 << 1;
|
||||
} else {
|
||||
Rd = 1 << 6;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("Unknown classification for operand.");
|
||||
break;
|
||||
}
|
||||
}});
|
||||
}
|
||||
0x71: decode ROUND_MODE {
|
||||
0x0: fmv_x_d({{
|
||||
Rd = Fs1_bits;
|
||||
}}, FloatCvtOp);
|
||||
0x1: fclass_d({{
|
||||
switch (std::fpclassify(Fs1)) {
|
||||
case FP_INFINITE:
|
||||
if (std::signbit(Fs1)) {
|
||||
Rd = 1 << 0;
|
||||
} else {
|
||||
Rd = 1 << 7;
|
||||
}
|
||||
break;
|
||||
case FP_NAN:
|
||||
if (issignalingnan(Fs1)) {
|
||||
Rd = 1 << 8;
|
||||
} else {
|
||||
Rd = 1 << 9;
|
||||
}
|
||||
break;
|
||||
case FP_ZERO:
|
||||
if (std::signbit(Fs1)) {
|
||||
Rd = 1 << 3;
|
||||
} else {
|
||||
Rd = 1 << 4;
|
||||
}
|
||||
break;
|
||||
case FP_SUBNORMAL:
|
||||
if (std::signbit(Fs1)) {
|
||||
Rd = 1 << 2;
|
||||
} else {
|
||||
Rd = 1 << 5;
|
||||
}
|
||||
break;
|
||||
case FP_NORMAL:
|
||||
if (std::signbit(Fs1)) {
|
||||
Rd = 1 << 1;
|
||||
} else {
|
||||
Rd = 1 << 6;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("Unknown classification for operand.");
|
||||
break;
|
||||
}
|
||||
}});
|
||||
}
|
||||
0x78: fmv_s_x({{
|
||||
Fd_bits = (uint64_t)Rs1_uw;
|
||||
}}, FloatCvtOp);
|
||||
0x79: fmv_d_x({{
|
||||
Fd_bits = Rs1;
|
||||
}}, FloatCvtOp);
|
||||
}
|
||||
}
|
||||
0x63: decode FUNCT3 {
|
||||
format SBOp {
|
||||
0x0: beq({{
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
//Include the type formats
|
||||
##include "type.isa"
|
||||
##include "mem.isa"
|
||||
##include "fp.isa"
|
||||
|
||||
// Include the unknown
|
||||
##include "unknown.isa"
|
||||
|
|
136
src/arch/riscv/isa/formats/fp.isa
Normal file
136
src/arch/riscv/isa/formats/fp.isa
Normal file
|
@ -0,0 +1,136 @@
|
|||
// -*- mode:c++ -*-
|
||||
|
||||
// Copyright (c) 2015 Riscv Developers
|
||||
// Copyright (c) 2016 The University of Virginia
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met: redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer;
|
||||
// redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution;
|
||||
// neither the name of the copyright holders nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Authors: Alec Roelke
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Floating point operation instructions
|
||||
//
|
||||
def template FloatExecute {{
|
||||
Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
if (fault == NoFault) {
|
||||
switch (ROUND_MODE) {
|
||||
case 0x0:
|
||||
std::fesetround(FE_TONEAREST);
|
||||
break;
|
||||
case 0x1:
|
||||
std::fesetround(FE_TOWARDZERO);
|
||||
break;
|
||||
case 0x2:
|
||||
std::fesetround(FE_DOWNWARD);
|
||||
break;
|
||||
case 0x3:
|
||||
std::fesetround(FE_UPWARD);
|
||||
break;
|
||||
case 0x4:
|
||||
panic("Round to nearest, "
|
||||
"ties to max magnitude not implemented.");
|
||||
break;
|
||||
case 0x7: {
|
||||
uint8_t frm = xc->readMiscReg(MISCREG_FRM);
|
||||
switch (frm) {
|
||||
case 0x0:
|
||||
std::fesetround(FE_TONEAREST);
|
||||
break;
|
||||
case 0x1:
|
||||
std::fesetround(FE_TOWARDZERO);
|
||||
break;
|
||||
case 0x2:
|
||||
std::fesetround(FE_DOWNWARD);
|
||||
break;
|
||||
case 0x3:
|
||||
std::fesetround(FE_UPWARD);
|
||||
break;
|
||||
case 0x4:
|
||||
panic("Round to nearest,"
|
||||
" ties to max magnitude not implemented.");
|
||||
break;
|
||||
default:
|
||||
fault = std::make_shared<IllegalFrmFault>(frm);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fault = std::make_shared<IllegalFrmFault>(ROUND_MODE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
MiscReg FFLAGS = xc->readMiscReg(MISCREG_FFLAGS);
|
||||
std::feclearexcept(FE_ALL_EXCEPT);
|
||||
%(code)s;
|
||||
if (std::fetestexcept(FE_INEXACT)) {
|
||||
FFLAGS |= FloatInexact;
|
||||
}
|
||||
if (std::fetestexcept(FE_UNDERFLOW)) {
|
||||
FFLAGS |= FloatUnderflow;
|
||||
}
|
||||
if (std::fetestexcept(FE_OVERFLOW)) {
|
||||
FFLAGS |= FloatOverflow;
|
||||
}
|
||||
if (std::fetestexcept(FE_DIVBYZERO)) {
|
||||
FFLAGS |= FloatDivZero;
|
||||
}
|
||||
if (std::fetestexcept(FE_INVALID)) {
|
||||
FFLAGS |= FloatInvalid;
|
||||
}
|
||||
xc->setMiscReg(MISCREG_FFLAGS, FFLAGS);
|
||||
}
|
||||
|
||||
if (fault == NoFault) {
|
||||
%(op_wb)s;
|
||||
}
|
||||
}
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
def format FPROp(code, *opt_flags) {{
|
||||
iop = InstObjParams(name, Name, 'ROp', code, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = FloatExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format FPR4Op(code, *opt_flags) {{
|
||||
iop = InstObjParams(name, Name, 'ROp', code, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = FloatExecute.subst(iop)
|
||||
}};
|
|
@ -68,12 +68,14 @@ using namespace RiscvISA;
|
|||
}};
|
||||
|
||||
output exec {{
|
||||
#include <cfenv>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include "arch/generic/memhelpers.hh"
|
||||
#include "arch/riscv/faults.hh"
|
||||
#include "arch/riscv/registers.hh"
|
||||
#include "arch/riscv/utility.hh"
|
||||
#include "base/condcodes.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/exetrace.hh"
|
||||
|
|
|
@ -39,6 +39,8 @@ def operand_types {{
|
|||
'uw' : 'uint32_t',
|
||||
'sd' : 'int64_t',
|
||||
'ud' : 'uint64_t',
|
||||
'sf' : 'float',
|
||||
'df' : 'double'
|
||||
}};
|
||||
|
||||
def operands {{
|
||||
|
@ -47,6 +49,15 @@ def operands {{
|
|||
'Rs1': ('IntReg', 'ud', 'RS1', 'IsInteger', 2),
|
||||
'Rs2': ('IntReg', 'ud', 'RS2', 'IsInteger', 3),
|
||||
|
||||
'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 1),
|
||||
'Fd_bits': ('FloatReg', 'ud', 'FD', 'IsFloating', 1),
|
||||
'Fs1': ('FloatReg', 'df', 'FS1', 'IsFloating', 2),
|
||||
'Fs1_bits': ('FloatReg', 'ud', 'FS1', 'IsFloating', 2),
|
||||
'Fs2': ('FloatReg', 'df', 'FS2', 'IsFloating', 3),
|
||||
'Fs2_bits': ('FloatReg', 'ud', 'FS2', 'IsFloating', 3),
|
||||
'Fs3': ('FloatReg', 'df', 'FS3', 'IsFloating', 4),
|
||||
'Fs3_bits': ('FloatReg', 'ud', 'FS3', 'IsFloating', 4),
|
||||
|
||||
#Memory Operand
|
||||
'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 5),
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ typedef uint64_t MiscReg;
|
|||
|
||||
const int NumIntArchRegs = 32;
|
||||
const int NumIntRegs = NumIntArchRegs;
|
||||
const int NumFloatRegs = 0;
|
||||
const int NumFloatRegs = 32;
|
||||
const int NumCCRegs = 0;
|
||||
const int NumMiscRegs = 4096;
|
||||
|
||||
|
|
|
@ -56,6 +56,46 @@
|
|||
namespace RiscvISA
|
||||
{
|
||||
|
||||
template<typename T> inline bool
|
||||
isquietnan(T val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> inline bool
|
||||
isquietnan<float>(float val)
|
||||
{
|
||||
return std::isnan(val)
|
||||
&& (reinterpret_cast<uint32_t&>(val)&0x00400000);
|
||||
}
|
||||
|
||||
template<> inline bool
|
||||
isquietnan<double>(double val)
|
||||
{
|
||||
return std::isnan(val)
|
||||
&& (reinterpret_cast<uint64_t&>(val)&0x0008000000000000ULL);
|
||||
}
|
||||
|
||||
template<typename T> inline bool
|
||||
issignalingnan(T val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> inline bool
|
||||
issignalingnan<float>(float val)
|
||||
{
|
||||
return std::isnan(val)
|
||||
&& (reinterpret_cast<uint32_t&>(val)&0x00200000);
|
||||
}
|
||||
|
||||
template<> inline bool
|
||||
issignalingnan<double>(double val)
|
||||
{
|
||||
return std::isnan(val)
|
||||
&& (reinterpret_cast<uint64_t&>(val)&0x0004000000000000ULL);
|
||||
}
|
||||
|
||||
inline PCState
|
||||
buildRetPC(const PCState &curPC, const PCState &callPC)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue