| // -*- mode:c++ -*- |
| |
| // Copyright (c) 2015 RISC-V Foundation |
| // 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 |
| |
| //////////////////////////////////////////////////////////////////// |
| // |
| // The RISC-V ISA decoder |
| // |
| |
| decode OPCODE default Unknown::unknown() { |
| 0x03: decode FUNCT3 { |
| format Load { |
| 0x0: lb({{ |
| Rd_sd = Mem_sb; |
| }}); |
| 0x1: lh({{ |
| Rd_sd = Mem_sh; |
| }}); |
| 0x2: lw({{ |
| Rd_sd = Mem_sw; |
| }}); |
| 0x3: ld({{ |
| Rd_sd = Mem_sd; |
| }}); |
| 0x4: lbu({{ |
| Rd = Mem_ub; |
| }}); |
| 0x5: lhu({{ |
| Rd = Mem_uh; |
| }}); |
| 0x6: lwu({{ |
| Rd = Mem_uw; |
| }}); |
| } |
| } |
| |
| 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({{ |
| }}, IsNonSpeculative, IsMemBarrier, No_OpClass); |
| 0x1: fence_i({{ |
| }}, IsNonSpeculative, IsSerializeAfter, No_OpClass); |
| } |
| } |
| |
| 0x13: decode FUNCT3 { |
| format IOp { |
| 0x0: addi({{ |
| Rd_sd = Rs1_sd + imm; |
| }}); |
| 0x1: slli({{ |
| Rd = Rs1 << SHAMT6; |
| }}); |
| 0x2: slti({{ |
| Rd = (Rs1_sd < imm) ? 1 : 0; |
| }}); |
| 0x3: sltiu({{ |
| Rd = (Rs1 < (uint64_t)imm) ? 1 : 0; |
| }}); |
| 0x4: xori({{ |
| Rd = Rs1 ^ (uint64_t)imm; |
| }}); |
| 0x5: decode SRTYPE { |
| 0x0: srli({{ |
| Rd = Rs1 >> SHAMT6; |
| }}); |
| 0x1: srai({{ |
| Rd_sd = Rs1_sd >> SHAMT6; |
| }}); |
| } |
| 0x6: ori({{ |
| Rd = Rs1 | (uint64_t)imm; |
| }}); |
| 0x7: andi({{ |
| Rd = Rs1 & (uint64_t)imm; |
| }}); |
| } |
| } |
| |
| 0x17: UOp::auipc({{ |
| Rd = PC + imm; |
| }}); |
| |
| 0x1b: decode FUNCT3 { |
| format IOp { |
| 0x0: addiw({{ |
| Rd_sd = (int32_t)Rs1 + (int32_t)imm; |
| }}); |
| 0x1: slliw({{ |
| Rd_sd = Rs1_sw << SHAMT5; |
| }}); |
| 0x5: decode SRTYPE { |
| 0x0: srliw({{ |
| Rd = Rs1_uw >> SHAMT5; |
| }}); |
| 0x1: sraiw({{ |
| Rd_sd = Rs1_sw >> SHAMT5; |
| }}); |
| } |
| } |
| } |
| |
| 0x23: decode FUNCT3 { |
| format Store { |
| 0x0: sb({{ |
| Mem_ub = Rs2_ub; |
| }}); |
| 0x1: sh({{ |
| Mem_uh = Rs2_uh; |
| }}); |
| 0x2: sw({{ |
| Mem_uw = Rs2_uw; |
| }}); |
| 0x3: sd({{ |
| Mem_ud = Rs2_ud; |
| }}); |
| } |
| } |
| |
| 0x27: decode FUNCT3 { |
| format Store { |
| 0x2: fsw({{ |
| Mem_uw = (uint32_t)Fs2_bits; |
| }}); |
| 0x3: fsd({{ |
| Mem_ud = Fs2_bits; |
| }}); |
| } |
| } |
| |
| 0x2f: decode FUNCT3 { |
| 0x2: decode AMOFUNCT { |
| 0x2: LoadReserved::lr_w({{ |
| Rd_sd = Mem_sw; |
| }}, mem_flags=LLSC); |
| 0x3: StoreCond::sc_w({{ |
| Mem_uw = Rs2_uw; |
| }}, {{ |
| Rd = result; |
| }}, inst_flags=IsStoreConditional, mem_flags=LLSC); |
| format AtomicMemOp { |
| 0x0: amoadd_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = Rs2_sw + Rt_sd; |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x1: amoswap_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = Rs2_uw; |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x4: amoxor_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = Rs2_uw^Rt_sd; |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x8: amoor_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = Rs2_uw | Rt_sd; |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0xc: amoand_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = Rs2_uw&Rt_sd; |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x10: amomin_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = std::min<int32_t>(Rs2_sw, Rt_sd); |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x14: amomax_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = std::max<int32_t>(Rs2_sw, Rt_sd); |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x18: amominu_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = std::min<uint32_t>(Rs2_uw, Rt_sd); |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x1c: amomaxu_w({{Rt_sd = Mem_sw;}}, {{ |
| Mem_sw = std::max<uint32_t>(Rs2_uw, Rt_sd); |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| } |
| } |
| 0x3: decode AMOFUNCT { |
| 0x2: LoadReserved::lr_d({{ |
| Rd_sd = Mem_sd; |
| }}, mem_flags=LLSC); |
| 0x3: StoreCond::sc_d({{ |
| Mem = Rs2; |
| }}, {{ |
| Rd = result; |
| }}, mem_flags=LLSC, inst_flags=IsStoreConditional); |
| format AtomicMemOp { |
| 0x0: amoadd_d({{Rt_sd = Mem_sd;}}, {{ |
| Mem_sd = Rs2_sd + Rt_sd; |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x1: amoswap_d({{Rt = Mem;}}, {{ |
| Mem = Rs2; |
| Rd = Rt; |
| }}, {{EA = Rs1;}}); |
| 0x4: amoxor_d({{Rt = Mem;}}, {{ |
| Mem = Rs2^Rt; |
| Rd = Rt; |
| }}, {{EA = Rs1;}}); |
| 0x8: amoor_d({{Rt = Mem;}}, {{ |
| Mem = Rs2 | Rt; |
| Rd = Rt; |
| }}, {{EA = Rs1;}}); |
| 0xc: amoand_d({{Rt = Mem;}}, {{ |
| Mem = Rs2&Rt; |
| Rd = Rt; |
| }}, {{EA = Rs1;}}); |
| 0x10: amomin_d({{Rt_sd = Mem_sd;}}, {{ |
| Mem_sd = std::min(Rs2_sd, Rt_sd); |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x14: amomax_d({{Rt_sd = Mem_sd;}}, {{ |
| Mem_sd = std::max(Rs2_sd, Rt_sd); |
| Rd_sd = Rt_sd; |
| }}, {{EA = Rs1;}}); |
| 0x18: amominu_d({{Rt = Mem;}}, {{ |
| Mem = std::min(Rs2, Rt); |
| Rd = Rt; |
| }}, {{EA = Rs1;}}); |
| 0x1c: amomaxu_d({{Rt = Mem;}}, {{ |
| Mem = std::max(Rs2, Rt); |
| Rd = Rt; |
| }}, {{EA = Rs1;}}); |
| } |
| } |
| } |
| 0x33: decode FUNCT3 { |
| format ROp { |
| 0x0: decode FUNCT7 { |
| 0x0: add({{ |
| Rd = Rs1_sd + Rs2_sd; |
| }}); |
| 0x1: mul({{ |
| Rd = Rs1_sd*Rs2_sd; |
| }}, IntMultOp); |
| 0x20: sub({{ |
| Rd = Rs1_sd - Rs2_sd; |
| }}); |
| } |
| 0x1: decode FUNCT7 { |
| 0x0: sll({{ |
| Rd = Rs1 << Rs2<5:0>; |
| }}); |
| 0x1: mulh({{ |
| bool negate = (Rs1_sd < 0) != (Rs2_sd < 0); |
| |
| uint64_t Rs1_lo = (uint32_t)std::abs(Rs1_sd); |
| uint64_t Rs1_hi = (uint64_t)std::abs(Rs1_sd) >> 32; |
| uint64_t Rs2_lo = (uint32_t)std::abs(Rs2_sd); |
| uint64_t Rs2_hi = (uint64_t)std::abs(Rs2_sd) >> 32; |
| |
| uint64_t hi = Rs1_hi*Rs2_hi; |
| uint64_t mid1 = Rs1_hi*Rs2_lo; |
| uint64_t mid2 = Rs1_lo*Rs2_hi; |
| uint64_t lo = Rs2_lo*Rs1_lo; |
| uint64_t carry = ((uint64_t)(uint32_t)mid1 |
| + (uint64_t)(uint32_t)mid2 + (lo >> 32)) >> 32; |
| |
| uint64_t res = hi + (mid1 >> 32) + (mid2 >> 32) + carry; |
| Rd = negate ? ~res + (Rs1_sd*Rs2_sd == 0 ? 1 : 0) : res; |
| }}, IntMultOp); |
| } |
| 0x2: decode FUNCT7 { |
| 0x0: slt({{ |
| Rd = (Rs1_sd < Rs2_sd) ? 1 : 0; |
| }}); |
| 0x1: mulhsu({{ |
| bool negate = Rs1_sd < 0; |
| uint64_t Rs1_lo = (uint32_t)std::abs(Rs1_sd); |
| uint64_t Rs1_hi = (uint64_t)std::abs(Rs1_sd) >> 32; |
| uint64_t Rs2_lo = (uint32_t)Rs2; |
| uint64_t Rs2_hi = Rs2 >> 32; |
| |
| uint64_t hi = Rs1_hi*Rs2_hi; |
| uint64_t mid1 = Rs1_hi*Rs2_lo; |
| uint64_t mid2 = Rs1_lo*Rs2_hi; |
| uint64_t lo = Rs1_lo*Rs2_lo; |
| uint64_t carry = ((uint64_t)(uint32_t)mid1 |
| + (uint64_t)(uint32_t)mid2 + (lo >> 32)) >> 32; |
| |
| uint64_t res = hi + (mid1 >> 32) + (mid2 >> 32) + carry; |
| Rd = negate ? ~res + (Rs1_sd*Rs2 == 0 ? 1 : 0) : res; |
| }}, IntMultOp); |
| } |
| 0x3: decode FUNCT7 { |
| 0x0: sltu({{ |
| Rd = (Rs1 < Rs2) ? 1 : 0; |
| }}); |
| 0x1: mulhu({{ |
| uint64_t Rs1_lo = (uint32_t)Rs1; |
| uint64_t Rs1_hi = Rs1 >> 32; |
| uint64_t Rs2_lo = (uint32_t)Rs2; |
| uint64_t Rs2_hi = Rs2 >> 32; |
| |
| uint64_t hi = Rs1_hi*Rs2_hi; |
| uint64_t mid1 = Rs1_hi*Rs2_lo; |
| uint64_t mid2 = Rs1_lo*Rs2_hi; |
| uint64_t lo = Rs1_lo*Rs2_lo; |
| uint64_t carry = ((uint64_t)(uint32_t)mid1 |
| + (uint64_t)(uint32_t)mid2 + (lo >> 32)) >> 32; |
| |
| Rd = hi + (mid1 >> 32) + (mid2 >> 32) + carry; |
| }}, IntMultOp); |
| } |
| 0x4: decode FUNCT7 { |
| 0x0: xor({{ |
| Rd = Rs1 ^ Rs2; |
| }}); |
| 0x1: div({{ |
| if (Rs2_sd == 0) { |
| Rd_sd = -1; |
| } else if (Rs1_sd == std::numeric_limits<int64_t>::min() |
| && Rs2_sd == -1) { |
| Rd_sd = std::numeric_limits<int64_t>::min(); |
| } else { |
| Rd_sd = Rs1_sd/Rs2_sd; |
| } |
| }}, IntDivOp); |
| } |
| 0x5: decode FUNCT7 { |
| 0x0: srl({{ |
| Rd = Rs1 >> Rs2<5:0>; |
| }}); |
| 0x1: divu({{ |
| if (Rs2 == 0) { |
| Rd = std::numeric_limits<uint64_t>::max(); |
| } else { |
| Rd = Rs1/Rs2; |
| } |
| }}, IntDivOp); |
| 0x20: sra({{ |
| Rd_sd = Rs1_sd >> Rs2<5:0>; |
| }}); |
| } |
| 0x6: decode FUNCT7 { |
| 0x0: or({{ |
| Rd = Rs1 | Rs2; |
| }}); |
| 0x1: rem({{ |
| if (Rs2_sd == 0) { |
| Rd = Rs1_sd; |
| } else if (Rs1_sd == std::numeric_limits<int64_t>::min() |
| && Rs2_sd == -1) { |
| Rd = 0; |
| } else { |
| Rd = Rs1_sd%Rs2_sd; |
| } |
| }}, IntDivOp); |
| } |
| 0x7: decode FUNCT7 { |
| 0x0: and({{ |
| Rd = Rs1 & Rs2; |
| }}); |
| 0x1: remu({{ |
| if (Rs2 == 0) { |
| Rd = Rs1; |
| } else { |
| Rd = Rs1%Rs2; |
| } |
| }}, IntDivOp); |
| } |
| } |
| } |
| |
| 0x37: UOp::lui({{ |
| Rd = (uint64_t)imm; |
| }}); |
| |
| 0x3b: decode FUNCT3 { |
| format ROp { |
| 0x0: decode FUNCT7 { |
| 0x0: addw({{ |
| Rd_sd = Rs1_sw + Rs2_sw; |
| }}); |
| 0x1: mulw({{ |
| Rd_sd = (int32_t)(Rs1_sw*Rs2_sw); |
| }}, IntMultOp); |
| 0x20: subw({{ |
| Rd_sd = Rs1_sw - Rs2_sw; |
| }}); |
| } |
| 0x1: sllw({{ |
| Rd_sd = Rs1_sw << Rs2<4:0>; |
| }}); |
| 0x4: divw({{ |
| if (Rs2_sw == 0) { |
| Rd_sd = -1; |
| } else if (Rs1_sw == std::numeric_limits<int32_t>::min() |
| && Rs2_sw == -1) { |
| Rd_sd = std::numeric_limits<int32_t>::min(); |
| } else { |
| Rd_sd = Rs1_sw/Rs2_sw; |
| } |
| }}, IntDivOp); |
| 0x5: decode FUNCT7 { |
| 0x0: srlw({{ |
| Rd_uw = Rs1_uw >> Rs2<4:0>; |
| }}); |
| 0x1: divuw({{ |
| if (Rs2_uw == 0) { |
| Rd_sd = std::numeric_limits<IntReg>::max(); |
| } else { |
| Rd_sd = (int32_t)(Rs1_uw/Rs2_uw); |
| } |
| }}, IntDivOp); |
| 0x20: sraw({{ |
| Rd_sd = Rs1_sw >> Rs2<4:0>; |
| }}); |
| } |
| 0x6: remw({{ |
| if (Rs2_sw == 0) { |
| Rd_sd = Rs1_sw; |
| } else if (Rs1_sw == std::numeric_limits<int32_t>::min() |
| && Rs2_sw == -1) { |
| Rd_sd = 0; |
| } else { |
| Rd_sd = Rs1_sw%Rs2_sw; |
| } |
| }}, IntDivOp); |
| 0x7: remuw({{ |
| if (Rs2_uw == 0) { |
| Rd_sd = (int32_t)Rs1_uw; |
| } else { |
| Rd_sd = (int32_t)(Rs1_uw%Rs2_uw); |
| } |
| }}, IntDivOp); |
| } |
| } |
| |
| 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({{ |
| if (Rs1 == Rs2) { |
| NPC = PC + imm; |
| } else { |
| NPC = NPC; |
| } |
| }}, IsDirectControl, IsCondControl); |
| 0x1: bne({{ |
| if (Rs1 != Rs2) { |
| NPC = PC + imm; |
| } else { |
| NPC = NPC; |
| } |
| }}, IsDirectControl, IsCondControl); |
| 0x4: blt({{ |
| if (Rs1_sd < Rs2_sd) { |
| NPC = PC + imm; |
| } else { |
| NPC = NPC; |
| } |
| }}, IsDirectControl, IsCondControl); |
| 0x5: bge({{ |
| if (Rs1_sd >= Rs2_sd) { |
| NPC = PC + imm; |
| } else { |
| NPC = NPC; |
| } |
| }}, IsDirectControl, IsCondControl); |
| 0x6: bltu({{ |
| if (Rs1 < Rs2) { |
| NPC = PC + imm; |
| } else { |
| NPC = NPC; |
| } |
| }}, IsDirectControl, IsCondControl); |
| 0x7: bgeu({{ |
| if (Rs1 >= Rs2) { |
| NPC = PC + imm; |
| } else { |
| NPC = NPC; |
| } |
| }}, IsDirectControl, IsCondControl); |
| } |
| } |
| |
| 0x67: decode FUNCT3 { |
| 0x0: Jump::jalr({{ |
| Rd = NPC; |
| NPC = (imm + Rs1) & (~0x1); |
| }}, IsIndirectControl, IsUncondControl, IsCall); |
| } |
| |
| 0x6f: UJOp::jal({{ |
| Rd = NPC; |
| NPC = PC + imm; |
| }}, IsDirectControl, IsUncondControl, IsCall); |
| |
| 0x73: decode FUNCT3 { |
| format IOp { |
| 0x0: decode FUNCT12 { |
| 0x0: ecall({{ |
| fault = std::make_shared<SyscallFault>(); |
| }}, IsSerializeAfter, IsNonSpeculative, IsSyscall, No_OpClass); |
| 0x1: ebreak({{ |
| fault = std::make_shared<BreakpointFault>(); |
| }}, IsSerializeAfter, IsNonSpeculative, No_OpClass); |
| 0x100: eret({{ |
| fault = std::make_shared<UnimplementedFault>("eret"); |
| }}, No_OpClass); |
| } |
| 0x1: csrrw({{ |
| Rd = xc->readMiscReg(FUNCT12); |
| xc->setMiscReg(FUNCT12, Rs1); |
| }}, IsNonSpeculative, No_OpClass); |
| 0x2: csrrs({{ |
| Rd = xc->readMiscReg(FUNCT12); |
| if (Rs1 != 0) { |
| xc->setMiscReg(FUNCT12, Rd | Rs1); |
| } |
| }}, IsNonSpeculative, No_OpClass); |
| 0x3: csrrc({{ |
| Rd = xc->readMiscReg(FUNCT12); |
| if (Rs1 != 0) { |
| xc->setMiscReg(FUNCT12, Rd & ~Rs1); |
| } |
| }}, IsNonSpeculative, No_OpClass); |
| 0x5: csrrwi({{ |
| Rd = xc->readMiscReg(FUNCT12); |
| xc->setMiscReg(FUNCT12, ZIMM); |
| }}, IsNonSpeculative, No_OpClass); |
| 0x6: csrrsi({{ |
| Rd = xc->readMiscReg(FUNCT12); |
| if (ZIMM != 0) { |
| xc->setMiscReg(FUNCT12, Rd | ZIMM); |
| } |
| }}, IsNonSpeculative, No_OpClass); |
| 0x7: csrrci({{ |
| Rd = xc->readMiscReg(FUNCT12); |
| if (ZIMM != 0) { |
| xc->setMiscReg(FUNCT12, Rd & ~ZIMM); |
| } |
| }}, IsNonSpeculative, No_OpClass); |
| } |
| } |
| } |