// -*- mode:c++ -*-
// Copyright (c) 2015 RISC-V Foundation
-// Copyright (c) 2016 The University of Virginia
+// Copyright (c) 2017 The University of Virginia
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// 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;
+decode QUADRANT default Unknown::unknown() {
+ 0x0: decode COPCODE {
+ 0x0: CUIOp::c_addi4spn({{
+ imm = CIMM8<1:1> << 2 |
+ CIMM8<0:0> << 3 |
+ CIMM8<7:6> << 4 |
+ CIMM8<5:2> << 6;
+ }}, {{
+ assert(imm != 0);
+ Rp2 = sp + imm;
+ }});
+ format CompressedLoad {
+ 0x1: c_fld({{
+ ldisp = CIMM3 << 3 | CIMM2 << 6;
+ }}, {{
+ Fp2_bits = Mem;
+ }}, {{
+ EA = Rp1 + ldisp;
}});
- 0x5: lhu({{
- Rd = Mem_uh;
+ 0x2: c_lw({{
+ ldisp = CIMM2<1:1> << 2 |
+ CIMM3 << 3 |
+ CIMM2<0:0> << 6;
+ }}, {{
+ Rp2_sd = Mem_sw;
+ }}, {{
+ EA = Rp1 + ldisp;
}});
- 0x6: lwu({{
- Rd = Mem_uw;
+ 0x3: c_ld({{
+ ldisp = CIMM3 << 3 | CIMM2 << 6;
+ }}, {{
+ Rp2_sd = Mem_sd;
+ }}, {{
+ EA = Rp1 + ldisp;
}});
}
- }
-
- 0x07: decode FUNCT3 {
- format Load {
- 0x2: flw({{
- Fd_bits = (uint64_t)Mem_uw;
+ format CompressedStore {
+ 0x5: c_fsd({{
+ sdisp = CIMM3 << 3 | CIMM2 << 6;
+ }}, {{
+ Mem = Fp2_bits;
+ }}, {{
+ EA = Rp1 + sdisp;
}});
- 0x3: fld({{
- Fd_bits = Mem;
+ 0x6: c_sw({{
+ sdisp = CIMM2<1:1> << 2 |
+ CIMM3 << 3 |
+ CIMM2<0:0> << 6;
+ }}, {{
+ Mem_uw = Rp2_uw;
+ }}, ea_code={{
+ EA = Rp1 + sdisp;
+ }});
+ 0x7: c_sd({{
+ sdisp = CIMM3 << 3 | CIMM2 << 6;
+ }}, {{
+ Mem_ud = Rp2_ud;
+ }}, {{
+ EA = Rp1 + sdisp;
}});
}
}
-
- 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;
+ 0x1: decode COPCODE {
+ format CIOp {
+ 0x0: c_addi({{
+ imm = CIMM5;
+ if (CIMM1 > 0)
+ imm |= ~((uint64_t)0x1F);
+ }}, {{
+ assert((RC1 == 0) == (imm == 0));
+ Rc1_sd = Rc1_sd + imm;
}});
- 0x3: sltiu({{
- Rd = (Rs1 < (uint64_t)imm) ? 1 : 0;
+ 0x1: c_addiw({{
+ imm = CIMM5;
+ if (CIMM1 > 0)
+ imm |= ~((uint64_t)0x1F);
+ }}, {{
+ assert(RC1 != 0);
+ Rc1_sd = (int32_t)Rc1_sd + imm;
}});
- 0x4: xori({{
- Rd = Rs1 ^ (uint64_t)imm;
+ 0x2: c_li({{
+ imm = CIMM5;
+ if (CIMM1 > 0)
+ imm |= ~((uint64_t)0x1F);
+ }}, {{
+ assert(RC1 != 0);
+ Rc1_sd = imm;
}});
- 0x5: decode SRTYPE {
- 0x0: srli({{
- Rd = Rs1 >> SHAMT6;
+ 0x3: decode RC1 {
+ 0x2: c_addi16sp({{
+ imm = CIMM5<4:4> << 4 |
+ CIMM5<0:0> << 5 |
+ CIMM5<3:3> << 6 |
+ CIMM5<2:1> << 7;
+ if (CIMM1 > 0)
+ imm |= ~((int64_t)0x1FF);
+ }}, {{
+ assert(imm != 0);
+ sp_sd = sp_sd + imm;
}});
- 0x1: srai({{
- Rd_sd = Rs1_sd >> SHAMT6;
+ default: c_lui({{
+ imm = CIMM5 << 12;
+ if (CIMM1 > 0)
+ imm |= ~((uint64_t)0x1FFFF);
+ }}, {{
+ assert(RC1 != 0 && RC1 != 2);
+ assert(imm != 0);
+ Rc1_sd = imm;
}});
}
- 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;
+ 0x4: decode CFUNCT2HIGH {
+ format CUIOp {
+ 0x0: c_srli({{
+ imm = CIMM5 | (CIMM1 << 5);
+ assert(imm != 0);
+ }}, {{
+ Rp1 = Rp1 >> imm;
}});
- 0x1: sraiw({{
- Rd_sd = Rs1_sw >> SHAMT5;
+ 0x1: c_srai({{
+ imm = CIMM5 | (CIMM1 << 5);
+ assert(imm != 0);
+ }}, {{
+ Rp1_sd = Rp1_sd >> imm;
}});
+ 0x2: c_andi({{
+ imm = CIMM5;
+ if (CIMM1 > 0)
+ imm |= ~((uint64_t)0x1F);
+ }}, {{
+ Rp1 = Rp1 & imm;
+ }});
+ }
+ format ROp {
+ 0x3: decode CFUNCT1 {
+ 0x0: decode CFUNCT2LOW {
+ 0x0: c_sub({{
+ Rp1 = Rp1 - Rp2;
+ }});
+ 0x1: c_xor({{
+ Rp1 = Rp1 ^ Rp2;
+ }});
+ 0x2: c_or({{
+ Rp1 = Rp1 | Rp2;
+ }});
+ 0x3: c_and({{
+ Rp1 = Rp1 & Rp2;
+ }});
+ }
+ 0x1: decode CFUNCT2LOW {
+ 0x0: c_subw({{
+ Rp1_sd = (int32_t)Rp1_sd - Rp2_sw;
+ }});
+ 0x1: c_addw({{
+ Rp1_sd = (int32_t)Rp1_sd + Rp2_sw;
+ }});
+ }
+ }
}
}
- }
+ 0x5: JOp::c_j({{
+ int64_t offset = CJUMPIMM<3:1> << 1 |
+ CJUMPIMM<9:9> << 4 |
+ CJUMPIMM<0:0> << 5 |
+ CJUMPIMM<5:5> << 6 |
+ CJUMPIMM<4:4> << 7 |
+ CJUMPIMM<8:7> << 8 |
+ CJUMPIMM<6:6> << 10;
+ if (CJUMPIMM<10:10> > 0)
+ offset |= ~((int64_t)0x7FF);
+ NPC = PC + offset;
+ }}, IsIndirectControl, IsUncondControl, IsCall);
+ format BOp {
+ 0x6: c_beqz({{
+ int64_t offset = CIMM5<2:1> << 1 |
+ CIMM3<1:0> << 3 |
+ CIMM5<0:0> << 5 |
+ CIMM5<4:3> << 6;
+ if (CIMM3<2:2> > 0)
+ offset |= ~((int64_t)0xFF);
- 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;
- }});
+ if (Rp1 == 0)
+ NPC = PC + offset;
+ else
+ NPC = NPC;
+ }}, IsDirectControl, IsCondControl);
+ 0x7: c_bnez({{
+ int64_t offset = CIMM5<2:1> << 1 |
+ CIMM3<1:0> << 3 |
+ CIMM5<0:0> << 5 |
+ CIMM5<4:3> << 6;
+ if (CIMM3<2:2> > 0)
+ offset |= ~((int64_t)0xFF);
+
+ if (Rp1 != 0)
+ NPC = PC + offset;
+ else
+ NPC = NPC;
+ }}, IsDirectControl, IsCondControl);
}
}
-
- 0x27: decode FUNCT3 {
- format Store {
- 0x2: fsw({{
- Mem_uw = (uint32_t)Fs2_bits;
+ 0x2: decode COPCODE {
+ 0x0: CUIOp::c_slli({{
+ imm = CIMM5 | (CIMM1 << 5);
+ assert(imm != 0);
+ }}, {{
+ assert(RC1 != 0);
+ Rc1 = Rc1 << imm;
+ }});
+ format CompressedLoad {
+ 0x1: c_fldsp({{
+ ldisp = CIMM5<4:3> << 3 |
+ CIMM1 << 5 |
+ CIMM5<2:0> << 6;
+ }}, {{
+ Fc1_bits = Mem;
+ }}, {{
+ EA = sp + ldisp;
}});
- 0x3: fsd({{
- Mem_ud = Fs2_bits;
+ 0x2: c_lwsp({{
+ ldisp = CIMM5<4:2> << 2 |
+ CIMM1 << 5 |
+ CIMM5<1:0> << 6;
+ }}, {{
+ assert(RC1 != 0);
+ Rc1_sd = Mem_sw;
+ }}, {{
+ EA = sp + ldisp;
}});
- }
- }
-
- 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;
+ 0x3: c_ldsp({{
+ ldisp = CIMM5<4:3> << 3 |
+ CIMM1 << 5 |
+ CIMM5<2:0> << 6;
+ }}, {{
+ assert(RC1 != 0);
+ Rc1_sd = Mem_sd;
}}, {{
- 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;}});
+ EA = sp + ldisp;
+ }});
+ }
+ 0x4: decode CFUNCT1 {
+ 0x0: decode RC2 {
+ 0x0: Jump::c_jr({{
+ assert(RC1 != 0);
+ NPC = Rc1;
+ }}, IsIndirectControl, IsUncondControl, IsCall);
+ default: CROp::c_mv({{
+ assert(RC1 != 0);
+ Rc1 = Rc2;
+ }});
+ }
+ 0x1: decode RC1 {
+ 0x0: SystemOp::c_ebreak({{
+ assert(RC2 == 0);
+ fault = make_shared<BreakpointFault>();
+ }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
+ default: decode RC2 {
+ 0x0: Jump::c_jalr({{
+ assert(RC1 != 0);
+ ra = NPC;
+ NPC = Rc1;
+ }}, IsIndirectControl, IsUncondControl, IsCall);
+ default: ROp::c_add({{
+ Rc1_sd = Rc1_sd + Rc2_sd;
+ }});
+ }
}
}
- 0x3: decode AMOFUNCT {
- 0x2: LoadReserved::lr_d({{
- Rd_sd = Mem_sd;
- }}, mem_flags=LLSC);
- 0x3: StoreCond::sc_d({{
- Mem = Rs2;
+ format CompressedStore {
+ 0x5: c_fsdsp({{
+ sdisp = CIMM6<5:3> << 3 |
+ CIMM6<2:0> << 6;
}}, {{
- 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;}});
- }
+ Mem_ud = Fc2_bits;
+ }}, {{
+ EA = sp + sdisp;
+ }});
+ 0x6: c_swsp({{
+ sdisp = CIMM6<5:2> << 2 |
+ CIMM6<1:0> << 6;
+ }}, {{
+ Mem_uw = Rc2_uw;
+ }}, {{
+ EA = sp + sdisp;
+ }});
+ 0x7: c_sdsp({{
+ sdisp = CIMM6<5:3> << 3 |
+ CIMM6<2:0> << 6;
+ }}, {{
+ Mem = Rc2;
+ }}, {{
+ EA = sp + sdisp;
+ }});
}
}
- 0x33: decode FUNCT3 {
- format ROp {
- 0x0: decode FUNCT7 {
- 0x0: add({{
- Rd = Rs1_sd + Rs2_sd;
+ 0x3: decode OPCODE {
+ 0x00: decode FUNCT3 {
+ format Load {
+ 0x0: lb({{
+ Rd_sd = Mem_sb;
}});
- 0x1: mul({{
- Rd = Rs1_sd*Rs2_sd;
- }}, IntMultOp);
- 0x20: sub({{
- Rd = Rs1_sd - Rs2_sd;
+ 0x1: lh({{
+ Rd_sd = Mem_sh;
}});
- }
- 0x1: decode FUNCT7 {
- 0x0: sll({{
- Rd = Rs1 << Rs2<5:0>;
+ 0x2: lw({{
+ Rd_sd = Mem_sw;
}});
- 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;
+ 0x3: ld({{
+ Rd_sd = Mem_sd;
}});
- 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;
+ 0x4: lbu({{
+ Rd = Mem_ub;
}});
- 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;
+ 0x5: lhu({{
+ Rd = Mem_uh;
}});
- 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: lwu({{
+ Rd = Mem_uw;
}});
}
- 0x6: decode FUNCT7 {
- 0x0: or({{
- Rd = Rs1 | Rs2;
+ }
+
+ 0x01: decode FUNCT3 {
+ format Load {
+ 0x2: flw({{
+ Fd_bits = (uint64_t)Mem_uw;
}});
- 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;
+ 0x3: fld({{
+ Fd_bits = Mem;
}});
- 0x1: remu({{
- if (Rs2 == 0) {
- Rd = Rs1;
- } else {
- Rd = Rs1%Rs2;
- }
- }}, IntDivOp);
}
}
- }
- 0x37: UOp::lui({{
- Rd = (uint64_t)imm;
- }});
+ 0x03: decode FUNCT3 {
+ format IOp {
+ 0x0: fence({{
+ }}, IsNonSpeculative, IsMemBarrier, No_OpClass);
+ 0x1: fence_i({{
+ }}, IsNonSpeculative, IsSerializeAfter, No_OpClass);
+ }
+ }
- 0x3b: decode FUNCT3 {
- format ROp {
- 0x0: decode FUNCT7 {
- 0x0: addw({{
- Rd_sd = Rs1_sw + Rs2_sw;
+ 0x04: decode FUNCT3 {
+ format IOp {
+ 0x0: addi({{
+ Rd_sd = Rs1_sd + imm;
}});
- 0x1: mulw({{
- Rd_sd = (int32_t)(Rs1_sw*Rs2_sw);
- }}, IntMultOp);
- 0x20: subw({{
- Rd_sd = Rs1_sw - Rs2_sw;
+ 0x1: slli({{
+ Rd = Rs1 << SHAMT6;
}});
- }
- 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;
+ 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;
+ }});
}
- }}, IntDivOp);
- 0x5: decode FUNCT7 {
- 0x0: srlw({{
- Rd_uw = Rs1_uw >> Rs2<4:0>;
+ 0x6: ori({{
+ Rd = Rs1 | (uint64_t)imm;
}});
- 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>;
+ 0x7: andi({{
+ Rd = Rs1 & (uint64_t)imm;
}});
}
- 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 FPROp {
- 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;
+ 0x05: UOp::auipc({{
+ Rd = PC + imm;
+ }});
- 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;
+ 0x06: 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;
+ }});
}
- }}, 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);
+ 0x08: 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;
+ }});
+ }
}
- 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);
+ 0x09: decode FUNCT3 {
+ format Store {
+ 0x2: fsw({{
+ Mem_uw = (uint32_t)Fs2_bits;
+ }});
+ 0x3: fsd({{
+ Mem_ud = Fs2_bits;
+ }});
+ }
}
- 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);
+ 0x0b: 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 = min<int32_t>(Rs2_sw, Rt_sd);
+ Rd_sd = Rt_sd;
+ }}, {{EA = Rs1;}});
+ 0x14: amomax_w({{Rt_sd = Mem_sw;}}, {{
+ Mem_sw = max<int32_t>(Rs2_sw, Rt_sd);
+ Rd_sd = Rt_sd;
+ }}, {{EA = Rs1;}});
+ 0x18: amominu_w({{Rt_sd = Mem_sw;}}, {{
+ Mem_sw = min<uint32_t>(Rs2_uw, Rt_sd);
+ Rd_sd = Rt_sd;
+ }}, {{EA = Rs1;}});
+ 0x1c: amomaxu_w({{Rt_sd = Mem_sw;}}, {{
+ Mem_sw = max<uint32_t>(Rs2_uw, Rt_sd);
+ Rd_sd = Rt_sd;
+ }}, {{EA = Rs1;}});
}
- 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);
+ }
+ 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 = min(Rs2_sd, Rt_sd);
+ Rd_sd = Rt_sd;
+ }}, {{EA = Rs1;}});
+ 0x14: amomax_d({{Rt_sd = Mem_sd;}}, {{
+ Mem_sd = max(Rs2_sd, Rt_sd);
+ Rd_sd = Rt_sd;
+ }}, {{EA = Rs1;}});
+ 0x18: amominu_d({{Rt = Mem;}}, {{
+ Mem = min(Rs2, Rt);
+ Rd = Rt;
+ }}, {{EA = Rs1;}});
+ 0x1c: amomaxu_d({{Rt = Mem;}}, {{
+ Mem = max(Rs2, Rt);
+ Rd = Rt;
+ }}, {{EA = Rs1;}});
}
- }}, FloatMultOp);
+ }
}
+ 0x0c: 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);
- 0x53: decode FUNCT7 {
- 0x0: fadd_s({{
- uint32_t temp;
- float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
- float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
- float fd;
+ uint64_t Rs1_lo = (uint32_t)abs(Rs1_sd);
+ uint64_t Rs1_hi = (uint64_t)abs(Rs1_sd) >> 32;
+ uint64_t Rs2_lo = (uint32_t)abs(Rs2_sd);
+ uint64_t Rs2_hi = (uint64_t)abs(Rs2_sd) >> 32;
- 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;
+ 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);
}
- 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;
+ 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)abs(Rs1_sd);
+ uint64_t Rs1_hi = (uint64_t)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);
}
- }}, 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;
+ 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;
- 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;
+ 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);
}
- 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;
+ 0x4: decode FUNCT7 {
+ 0x0: xor({{
+ Rd = Rs1 ^ Rs2;
+ }});
+ 0x1: div({{
+ if (Rs2_sd == 0) {
+ Rd_sd = -1;
+ } else if (Rs1_sd == numeric_limits<int64_t>::min()
+ && Rs2_sd == -1) {
+ Rd_sd = numeric_limits<int64_t>::min();
+ } else {
+ Rd_sd = Rs1_sd/Rs2_sd;
+ }
+ }}, IntDivOp);
}
- }}, 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;
+ 0x5: decode FUNCT7 {
+ 0x0: srl({{
+ Rd = Rs1 >> Rs2<5:0>;
+ }});
+ 0x1: divu({{
+ if (Rs2 == 0) {
+ Rd = numeric_limits<uint64_t>::max();
+ } else {
+ Rd = Rs1/Rs2;
+ }
+ }}, IntDivOp);
+ 0x20: sra({{
+ Rd_sd = Rs1_sd >> Rs2<5:0>;
+ }});
}
- 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;
+ 0x6: decode FUNCT7 {
+ 0x0: or({{
+ Rd = Rs1 | Rs2;
+ }});
+ 0x1: rem({{
+ if (Rs2_sd == 0) {
+ Rd = Rs1_sd;
+ } else if (Rs1_sd == 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);
}
- }}, 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;
+ 0x0d: UOp::lui({{
+ Rd = (uint64_t)imm;
+ }});
+
+ 0x0e: 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;
+ }});
}
- 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;
+ 0x1: sllw({{
+ Rd_sd = Rs1_sw << Rs2<4:0>;
+ }});
+ 0x4: divw({{
+ if (Rs2_sw == 0) {
+ Rd_sd = -1;
+ } else if (Rs1_sw == numeric_limits<int32_t>::min()
+ && Rs2_sw == -1) {
+ Rd_sd = numeric_limits<int32_t>::min();
+ } else {
+ Rd_sd = Rs1_sw/Rs2_sw;
}
- Fd = std::numeric_limits<double>::quiet_NaN();
- } else {
- Fd = Fs1/Fs2;
+ }}, IntDivOp);
+ 0x5: decode FUNCT7 {
+ 0x0: srlw({{
+ Rd_uw = Rs1_uw >> Rs2<4:0>;
+ }});
+ 0x1: divuw({{
+ if (Rs2_uw == 0) {
+ Rd_sd = numeric_limits<IntReg>::max();
+ } else {
+ Rd_sd = (int32_t)(Rs1_uw/Rs2_uw);
+ }
+ }}, IntDivOp);
+ 0x20: sraw({{
+ Rd_sd = Rs1_sw >> Rs2<4:0>;
+ }});
}
- }}, FloatDivOp);
- 0x10: decode ROUND_MODE {
- 0x0: fsgnj_s({{
+ 0x6: remw({{
+ if (Rs2_sw == 0) {
+ Rd_sd = Rs1_sw;
+ } else if (Rs1_sw == 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 FPROp {
+ 0x10: 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 (issignalingnan(fs1)) {
- fd = std::numeric_limits<float>::signaling_NaN();
- std::feclearexcept(FE_INVALID);
+ if (isnan(fs1) || isnan(fs2) || isnan(fs3)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)
+ || issignalingnan(fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
+ } else if (isinf(fs1) || isinf(fs2) ||
+ isinf(fs3)) {
+ if (signbit(fs1) == signbit(fs2)
+ && !isinf(fs3)) {
+ fd = numeric_limits<float>::infinity();
+ } else if (signbit(fs1) != signbit(fs2)
+ && !isinf(fs3)) {
+ fd = -numeric_limits<float>::infinity();
+ } else { // Fs3_sf is infinity
+ fd = fs3;
+ }
} else {
- fd = std::copysign(fs1, fs2);
+ fd = fs1*fs2 + fs3;
}
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
- }});
- 0x1: fsgnjn_s({{
+ }}, FloatMultOp);
+ 0x1: fmadd_d({{
+ if (isnan(Fs1) || isnan(Fs2) || isnan(Fs3)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)
+ || issignalingnan(Fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
+ } else if (isinf(Fs1) || isinf(Fs2) ||
+ isinf(Fs3)) {
+ if (signbit(Fs1) == signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = numeric_limits<double>::infinity();
+ } else if (signbit(Fs1) != signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = -numeric_limits<double>::infinity();
+ } else {
+ Fd = Fs3;
+ }
+ } else {
+ Fd = Fs1*Fs2 + Fs3;
+ }
+ }}, FloatMultOp);
+ }
+ 0x11: 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 (issignalingnan(fs1)) {
- fd = std::numeric_limits<float>::signaling_NaN();
- std::feclearexcept(FE_INVALID);
+ if (isnan(fs1) || isnan(fs2) || isnan(fs3)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)
+ || issignalingnan(fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
+ } else if (isinf(fs1) || isinf(fs2) ||
+ isinf(fs3)) {
+ if (signbit(fs1) == signbit(fs2)
+ && !isinf(fs3)) {
+ fd = numeric_limits<float>::infinity();
+ } else if (signbit(fs1) != signbit(fs2)
+ && !isinf(fs3)) {
+ fd = -numeric_limits<float>::infinity();
+ } else { // Fs3_sf is infinity
+ fd = -fs3;
+ }
} else {
- fd = std::copysign(fs1, -fs2);
+ fd = fs1*fs2 - fs3;
}
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
- }});
- 0x2: fsgnjx_s({{
+ }}, FloatMultOp);
+ 0x1: fmsub_d({{
+ if (isnan(Fs1) || isnan(Fs2) || isnan(Fs3)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)
+ || issignalingnan(Fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
+ } else if (isinf(Fs1) || isinf(Fs2) ||
+ isinf(Fs3)) {
+ if (signbit(Fs1) == signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = numeric_limits<double>::infinity();
+ } else if (signbit(Fs1) != signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = -numeric_limits<double>::infinity();
+ } else {
+ Fd = -Fs3;
+ }
+ } else {
+ Fd = Fs1*Fs2 - Fs3;
+ }
+ }}, FloatMultOp);
+ }
+ 0x12: 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 (issignalingnan(fs1)) {
- fd = std::numeric_limits<float>::signaling_NaN();
- std::feclearexcept(FE_INVALID);
+ if (isnan(fs1) || isnan(fs2) || isnan(fs3)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)
+ || issignalingnan(fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
+ } else if (isinf(fs1) || isinf(fs2) ||
+ isinf(fs3)) {
+ if (signbit(fs1) == signbit(fs2)
+ && !isinf(fs3)) {
+ fd = -numeric_limits<float>::infinity();
+ } else if (signbit(fs1) != signbit(fs2)
+ && !isinf(fs3)) {
+ fd = numeric_limits<float>::infinity();
+ } else { // Fs3_sf is infinity
+ fd = fs3;
+ }
} else {
- fd = fs1*(std::signbit(fs2) ? -1.0 : 1.0);
+ fd = -(fs1*fs2 - fs3);
}
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);
+ }}, FloatMultOp);
+ 0x1: fnmsub_d({{
+ if (isnan(Fs1) || isnan(Fs2) || isnan(Fs3)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)
+ || issignalingnan(Fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
+ } else if (isinf(Fs1) || isinf(Fs2)
+ || isinf(Fs3)) {
+ if (signbit(Fs1) == signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = -numeric_limits<double>::infinity();
+ } else if (signbit(Fs1) != signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = numeric_limits<double>::infinity();
+ } else {
+ Fd = Fs3;
+ }
} else {
- Fd = Fs1*(std::signbit(Fs2) ? -1.0 : 1.0);
+ Fd = -(Fs1*Fs2 - Fs3);
}
- }});
+ }}, FloatMultOp);
}
- 0x14: decode ROUND_MODE {
- 0x0: fmin_s({{
+ 0x13: 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 (issignalingnan(fs2)) {
- fd = fs1;
- FFLAGS |= FloatInvalid;
- } else if (issignalingnan(fs1)) {
- fd = fs2;
- FFLAGS |= FloatInvalid;
+ if (isnan(fs1) || isnan(fs2) || isnan(fs3)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)
+ || issignalingnan(fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
+ } else if (isinf(fs1) || isinf(fs2) ||
+ isinf(fs3)) {
+ if (signbit(fs1) == signbit(fs2)
+ && !isinf(fs3)) {
+ fd = -numeric_limits<float>::infinity();
+ } else if (signbit(fs1) != signbit(fs2)
+ && !isinf(fs3)) {
+ fd = numeric_limits<float>::infinity();
+ } else { // Fs3_sf is infinity
+ fd = -fs3;
+ }
} else {
- fd = std::fmin(fs1, fs2);
+ fd = -(fs1*fs2 + fs3);
}
Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
- }}, FloatCmpOp);
- 0x1: fmax_s({{
+ }}, FloatMultOp);
+ 0x1: fnmadd_d({{
+ if (isnan(Fs1) || isnan(Fs2) || isnan(Fs3)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)
+ || issignalingnan(Fs3)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
+ } else if (isinf(Fs1) || isinf(Fs2) ||
+ isinf(Fs3)) {
+ if (signbit(Fs1) == signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = -numeric_limits<double>::infinity();
+ } else if (signbit(Fs1) != signbit(Fs2)
+ && !isinf(Fs3)) {
+ Fd = numeric_limits<double>::infinity();
+ } else {
+ Fd = -Fs3;
+ }
+ } else {
+ Fd = -(Fs1*Fs2 + Fs3);
+ }
+ }}, FloatMultOp);
+ }
+ 0x14: decode FUNCT7 {
+ 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 (issignalingnan(fs2)) {
- fd = fs1;
- FFLAGS |= FloatInvalid;
- } else if (issignalingnan(fs1)) {
- fd = fs2;
- FFLAGS |= FloatInvalid;
+ if (isnan(fs1) || isnan(fs2)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
} else {
- fd = std::fmax(fs1, fs2);
+ fd = 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;
+ }}, FloatAddOp);
+ 0x1: fadd_d({{
+ if (isnan(Fs1) || isnan(Fs2)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
} else {
- Fd = std::fmax(Fs1, Fs2);
+ Fd = 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({{
+ }}, 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)) {
- FFLAGS |= FloatInvalid;
- Rd = 0;
+ if (isnan(fs1) || isnan(fs2)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
} else {
- Rd = fs1 <= fs2 ? 1 : 0;
+ fd = fs1 - fs2;
}
- }}, 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;
+ Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
+ }}, FloatAddOp);
+ 0x5: fsub_d({{
+ if (isnan(Fs1) || isnan(Fs2)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
} else {
- Rd = fs1 < fs2 ? 1 : 0;
+ Fd = Fs1 - Fs2;
}
- }}, FloatCmpOp);
- 0x2: feq_s({{
+ }}, 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 (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;
+ if (isnan(fs1) || isnan(fs2)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
} else {
- Rd = Fs1 <= Fs2 ? 1 : 0;
+ fd = fs1*fs2;
}
- }}, FloatCmpOp);
- 0x1: flt_d({{
- if (std::isnan(Fs1) || std::isnan(Fs2)) {
- FFLAGS |= FloatInvalid;
- Rd = 0;
+ Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
+ }}, FloatMultOp);
+ 0x9: fmul_d({{
+ if (isnan(Fs1) || isnan(Fs2)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ Fd = numeric_limits<double>::quiet_NaN();
} else {
- Rd = Fs1 < Fs2 ? 1 : 0;
+ Fd = Fs1*Fs2;
}
- }}, 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({{
+ }}, 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)) {
- Rd_sd = std::numeric_limits<int32_t>::max();
- FFLAGS |= FloatInvalid;
+ if (isnan(fs1) || isnan(fs2)) {
+ if (issignalingnan(fs1) || issignalingnan(fs2)) {
+ FFLAGS |= FloatInvalid;
+ }
+ fd = numeric_limits<float>::quiet_NaN();
} 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);
+ fd = fs1/fs2;
+ }
+ Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
+ }}, FloatDivOp);
+ 0xd: fdiv_d({{
+ if (isnan(Fs1) || isnan(Fs2)) {
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
}
+ Fd = numeric_limits<double>::quiet_NaN();
+ } else {
+ Fd = Fs1/Fs2;
}
- }}, FloatCvtOp);
- 0x1: fcvt_wu_s({{
- uint32_t temp;
- float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
+ }}, 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 (fs1 < 0.0) {
- Rd = 0;
+ if (issignalingnan(fs1)) {
+ fd = numeric_limits<float>::signaling_NaN();
+ feclearexcept(FE_INVALID);
+ } else {
+ fd = 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 = numeric_limits<float>::signaling_NaN();
+ feclearexcept(FE_INVALID);
+ } else {
+ fd = 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 = numeric_limits<float>::signaling_NaN();
+ feclearexcept(FE_INVALID);
+ } else {
+ fd = fs1*(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 = numeric_limits<double>::signaling_NaN();
+ feclearexcept(FE_INVALID);
+ } else {
+ Fd = copysign(Fs1, Fs2);
+ }
+ }});
+ 0x1: fsgnjn_d({{
+ if (issignalingnan(Fs1)) {
+ Fd = numeric_limits<double>::signaling_NaN();
+ feclearexcept(FE_INVALID);
+ } else {
+ Fd = copysign(Fs1, -Fs2);
+ }
+ }});
+ 0x2: fsgnjx_d({{
+ if (issignalingnan(Fs1)) {
+ Fd = numeric_limits<double>::signaling_NaN();
+ feclearexcept(FE_INVALID);
+ } else {
+ Fd = Fs1*(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 = 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 = 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 = fmin(Fs1, Fs2);
+ }
+ }}, FloatCmpOp);
+ 0x1: fmax_d({{
+ if (issignalingnan(Fs2)) {
+ Fd = Fs1;
+ FFLAGS |= FloatInvalid;
+ } else if (issignalingnan(Fs1)) {
+ Fd = Fs2;
+ FFLAGS |= FloatInvalid;
+ } else {
+ Fd = fmax(Fs1, Fs2);
+ }
+ }}, FloatCmpOp);
+ }
+ 0x20: fcvt_s_d({{
+ assert(CONV_SGN == 1);
+ float fd;
+ if (issignalingnan(Fs1)) {
+ fd = numeric_limits<float>::quiet_NaN();
FFLAGS |= FloatInvalid;
} else {
- Rd = (uint32_t)fs1;
- if (std::fetestexcept(FE_INVALID)) {
- Rd = std::numeric_limits<uint64_t>::max();
- std::feclearexcept(FE_INEXACT);
- }
+ fd = (float)Fs1;
}
+ Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
}}, FloatCvtOp);
- 0x2: fcvt_l_s({{
+ 0x21: fcvt_d_s({{
+ assert(CONV_SGN == 0);
uint32_t temp;
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
- if (std::isnan(fs1)) {
- Rd_sd = std::numeric_limits<int64_t>::max();
+ if (issignalingnan(fs1)) {
+ Fd = numeric_limits<double>::quiet_NaN();
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);
- }
+ Fd = (double)fs1;
}
}}, FloatCvtOp);
- 0x3: fcvt_lu_s({{
+ 0x2c: fsqrt_s({{
+ assert(RS2 == 0);
uint32_t temp;
float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
+ float fd;
- if (fs1 < 0.0) {
- Rd = 0;
+ if (issignalingnan(Fs1_sf)) {
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();
+ fd = sqrt(fs1);
+ Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
+ }}, FloatSqrtOp);
+ 0x2d: fsqrt_d({{
+ assert(RS2 == 0);
+ Fd = 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 (isnan(fs1) || isnan(fs2)) {
+ FFLAGS |= FloatInvalid;
+ Rd = 0;
} 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);
+ Rd = fs1 <= fs2 ? 1 : 0;
}
- }
- }}, 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();
+ }}, FloatCmpOp);
+ 0x1: flt_s({{
+ uint32_t temp;
+ float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
+ float fs2 = reinterpret_cast<float&>(temp = Fs2_bits);
+
+ if (isnan(fs1) || isnan(fs2)) {
+ FFLAGS |= FloatInvalid;
+ Rd = 0;
} else {
- Rd_sd = std::numeric_limits<int64_t>::max();
+ Rd = fs1 < fs2 ? 1 : 0;
}
- 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);
+ }}, 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;
}
- }
- }}, 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;
+ Rd = fs1 == fs2 ? 1 : 0;
+ }}, FloatCmpOp);
+ }
+ 0x51: decode ROUND_MODE {
+ 0x0: fle_d({{
+ if (isnan(Fs1) || isnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
+ Rd = 0;
} else {
- Rd = 1 << 7;
+ Rd = Fs1 <= Fs2 ? 1 : 0;
}
- break;
- case FP_NAN:
- if (issignalingnan(fs1)) {
- Rd = 1 << 8;
+ }}, FloatCmpOp);
+ 0x1: flt_d({{
+ if (isnan(Fs1) || isnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
+ Rd = 0;
} else {
- Rd = 1 << 9;
+ Rd = Fs1 < Fs2 ? 1 : 0;
}
- break;
- case FP_ZERO:
- if (std::signbit(fs1)) {
- Rd = 1 << 3;
- } else {
- Rd = 1 << 4;
+ }}, FloatCmpOp);
+ 0x2: feq_d({{
+ if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
+ FFLAGS |= FloatInvalid;
}
- break;
- case FP_SUBNORMAL:
- if (std::signbit(fs1)) {
- Rd = 1 << 2;
+ 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 (isnan(fs1)) {
+ Rd_sd = numeric_limits<int32_t>::max();
+ FFLAGS |= FloatInvalid;
} else {
- Rd = 1 << 5;
+ Rd_sd = (int32_t)fs1;
+ if (fetestexcept(FE_INVALID)) {
+ if (signbit(fs1)) {
+ Rd_sd = numeric_limits<int32_t>::min();
+ } else {
+ Rd_sd = numeric_limits<int32_t>::max();
+ }
+ feclearexcept(FE_INEXACT);
+ }
}
- break;
- case FP_NORMAL:
- if (std::signbit(fs1)) {
- Rd = 1 << 1;
+ }}, 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 = 1 << 6;
+ Rd = (uint32_t)fs1;
+ if (fetestexcept(FE_INVALID)) {
+ Rd = numeric_limits<uint64_t>::max();
+ feclearexcept(FE_INEXACT);
+ }
}
- 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;
+ }}, FloatCvtOp);
+ 0x2: fcvt_l_s({{
+ uint32_t temp;
+ float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
+
+ if (isnan(fs1)) {
+ Rd_sd = numeric_limits<int64_t>::max();
+ FFLAGS |= FloatInvalid;
} else {
- Rd = 1 << 7;
+ Rd_sd = (int64_t)fs1;
+ if (fetestexcept(FE_INVALID)) {
+ if (signbit(fs1)) {
+ Rd_sd = numeric_limits<int64_t>::min();
+ } else {
+ Rd_sd = numeric_limits<int64_t>::max();
+ }
+ feclearexcept(FE_INEXACT);
+ }
}
- break;
- case FP_NAN:
- if (issignalingnan(Fs1)) {
- Rd = 1 << 8;
+ }}, 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 = 1 << 9;
+ Rd = (uint64_t)fs1;
+ if (fetestexcept(FE_INVALID)) {
+ Rd = numeric_limits<uint64_t>::max();
+ feclearexcept(FE_INEXACT);
+ }
}
- break;
- case FP_ZERO:
- if (std::signbit(Fs1)) {
- Rd = 1 << 3;
- } else {
- Rd = 1 << 4;
+ }}, FloatCvtOp);
+ }
+ 0x61: decode CONV_SGN {
+ 0x0: fcvt_w_d({{
+ Rd_sd = (int32_t)Fs1;
+ if (fetestexcept(FE_INVALID)) {
+ if (Fs1 < 0.0) {
+ Rd_sd = numeric_limits<int32_t>::min();
+ } else {
+ Rd_sd = numeric_limits<int32_t>::max();
+ }
+ feclearexcept(FE_INEXACT);
}
- break;
- case FP_SUBNORMAL:
- if (std::signbit(Fs1)) {
- Rd = 1 << 2;
+ }}, FloatCvtOp);
+ 0x1: fcvt_wu_d({{
+ if (Fs1 < 0.0) {
+ Rd = 0;
+ FFLAGS |= FloatInvalid;
} else {
- Rd = 1 << 5;
+ Rd = (uint32_t)Fs1;
+ if (fetestexcept(FE_INVALID)) {
+ Rd = numeric_limits<uint64_t>::max();
+ feclearexcept(FE_INEXACT);
+ }
+ }
+ }}, FloatCvtOp);
+ 0x2: fcvt_l_d({{
+ Rd_sd = Fs1;
+ if (fetestexcept(FE_INVALID)) {
+ if (Fs1 < 0.0) {
+ Rd_sd = numeric_limits<int64_t>::min();
+ } else {
+ Rd_sd = numeric_limits<int64_t>::max();
+ }
+ feclearexcept(FE_INEXACT);
}
- break;
- case FP_NORMAL:
- if (std::signbit(Fs1)) {
- Rd = 1 << 1;
+ }}, FloatCvtOp);
+ 0x3: fcvt_lu_d({{
+ if (Fs1 < 0.0) {
+ Rd = 0;
+ FFLAGS |= FloatInvalid;
} else {
- Rd = 1 << 6;
+ Rd = (uint64_t)Fs1;
+ if (fetestexcept(FE_INVALID)) {
+ Rd = numeric_limits<uint64_t>::max();
+ feclearexcept(FE_INEXACT);
+ }
}
- 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 BOp {
- 0x0: beq({{
- if (Rs1 == Rs2) {
- NPC = PC + imm;
- } else {
- NPC = NPC;
+ }}, FloatCvtOp);
}
- }}, IsDirectControl, IsCondControl);
- 0x1: bne({{
- if (Rs1 != Rs2) {
- NPC = PC + imm;
- } else {
- NPC = NPC;
+ 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);
}
- }}, IsDirectControl, IsCondControl);
- 0x4: blt({{
- if (Rs1_sd < Rs2_sd) {
- NPC = PC + imm;
- } else {
- NPC = NPC;
+ 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);
}
- }}, 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;
+ 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 (fpclassify(fs1)) {
+ case FP_INFINITE:
+ if (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 (signbit(fs1)) {
+ Rd = 1 << 3;
+ } else {
+ Rd = 1 << 4;
+ }
+ break;
+ case FP_SUBNORMAL:
+ if (signbit(fs1)) {
+ Rd = 1 << 2;
+ } else {
+ Rd = 1 << 5;
+ }
+ break;
+ case FP_NORMAL:
+ if (signbit(fs1)) {
+ Rd = 1 << 1;
+ } else {
+ Rd = 1 << 6;
+ }
+ break;
+ default:
+ panic("Unknown classification for operand.");
+ break;
+ }
+ }});
}
- }}, IsDirectControl, IsCondControl);
- 0x7: bgeu({{
- if (Rs1 >= Rs2) {
- NPC = PC + imm;
- } else {
- NPC = NPC;
+ 0x71: decode ROUND_MODE {
+ 0x0: fmv_x_d({{
+ Rd = Fs1_bits;
+ }}, FloatCvtOp);
+ 0x1: fclass_d({{
+ switch (fpclassify(Fs1)) {
+ case FP_INFINITE:
+ if (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 (signbit(Fs1)) {
+ Rd = 1 << 3;
+ } else {
+ Rd = 1 << 4;
+ }
+ break;
+ case FP_SUBNORMAL:
+ if (signbit(Fs1)) {
+ Rd = 1 << 2;
+ } else {
+ Rd = 1 << 5;
+ }
+ break;
+ case FP_NORMAL:
+ if (signbit(Fs1)) {
+ Rd = 1 << 1;
+ } else {
+ Rd = 1 << 6;
+ }
+ break;
+ default:
+ panic("Unknown classification for operand.");
+ break;
+ }
+ }});
}
- }}, IsDirectControl, IsCondControl);
+ 0x78: fmv_s_x({{
+ Fd_bits = (uint64_t)Rs1_uw;
+ }}, FloatCvtOp);
+ 0x79: fmv_d_x({{
+ Fd_bits = Rs1;
+ }}, FloatCvtOp);
+ }
}
- }
-
- 0x67: decode FUNCT3 {
- 0x0: Jump::jalr({{
- Rd = NPC;
- NPC = (imm + Rs1) & (~0x1);
- }}, IsIndirectControl, IsUncondControl, IsCall);
- }
-
- 0x6f: JOp::jal({{
- Rd = NPC;
- NPC = PC + imm;
- }}, IsDirectControl, IsUncondControl, IsCall);
- 0x73: decode FUNCT3 {
- format SystemOp {
- 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);
+ 0x18: decode FUNCT3 {
+ format BOp {
+ 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);
}
}
- format CSROp {
- 0x1: csrrw({{
- Rd = xc->readMiscReg(csr);
- xc->setMiscReg(csr, Rs1);
- }}, IsNonSpeculative, No_OpClass);
- 0x2: csrrs({{
- Rd = xc->readMiscReg(csr);
- if (Rs1 != 0) {
- xc->setMiscReg(csr, Rd | Rs1);
- }
- }}, IsNonSpeculative, No_OpClass);
- 0x3: csrrc({{
- Rd = xc->readMiscReg(csr);
- if (Rs1 != 0) {
- xc->setMiscReg(csr, Rd & ~Rs1);
- }
- }}, IsNonSpeculative, No_OpClass);
- 0x5: csrrwi({{
- Rd = xc->readMiscReg(csr);
- xc->setMiscReg(csr, uimm);
- }}, IsNonSpeculative, No_OpClass);
- 0x6: csrrsi({{
- Rd = xc->readMiscReg(csr);
- if (uimm != 0) {
- xc->setMiscReg(csr, Rd | uimm);
- }
- }}, IsNonSpeculative, No_OpClass);
- 0x7: csrrci({{
- Rd = xc->readMiscReg(csr);
- if (uimm != 0) {
- xc->setMiscReg(csr, Rd & ~uimm);
+
+ 0x19: decode FUNCT3 {
+ 0x0: Jump::jalr({{
+ Rd = NPC;
+ NPC = (imm + Rs1) & (~0x1);
+ }}, IsIndirectControl, IsUncondControl, IsCall);
+ }
+
+ 0x1b: JOp::jal({{
+ Rd = NPC;
+ NPC = PC + imm;
+ }}, IsDirectControl, IsUncondControl, IsCall);
+
+ 0x1c: decode FUNCT3 {
+ format SystemOp {
+ 0x0: decode FUNCT12 {
+ 0x0: ecall({{
+ fault = make_shared<SyscallFault>();
+ }}, IsSerializeAfter, IsNonSpeculative, IsSyscall,
+ No_OpClass);
+ 0x1: ebreak({{
+ fault = make_shared<BreakpointFault>();
+ }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
+ 0x100: eret({{
+ fault = make_shared<UnimplementedFault>("eret");
+ }}, No_OpClass);
}
- }}, IsNonSpeculative, No_OpClass);
+ }
+ format CSROp {
+ 0x1: csrrw({{
+ Rd = xc->readMiscReg(csr);
+ xc->setMiscReg(csr, Rs1);
+ }}, IsNonSpeculative, No_OpClass);
+ 0x2: csrrs({{
+ Rd = xc->readMiscReg(csr);
+ if (Rs1 != 0) {
+ xc->setMiscReg(csr, Rd | Rs1);
+ }
+ }}, IsNonSpeculative, No_OpClass);
+ 0x3: csrrc({{
+ Rd = xc->readMiscReg(csr);
+ if (Rs1 != 0) {
+ xc->setMiscReg(csr, Rd & ~Rs1);
+ }
+ }}, IsNonSpeculative, No_OpClass);
+ 0x5: csrrwi({{
+ Rd = xc->readMiscReg(csr);
+ xc->setMiscReg(csr, uimm);
+ }}, IsNonSpeculative, No_OpClass);
+ 0x6: csrrsi({{
+ Rd = xc->readMiscReg(csr);
+ if (uimm != 0) {
+ xc->setMiscReg(csr, Rd | uimm);
+ }
+ }}, IsNonSpeculative, No_OpClass);
+ 0x7: csrrci({{
+ Rd = xc->readMiscReg(csr);
+ if (uimm != 0) {
+ xc->setMiscReg(csr, Rd & ~uimm);
+ }
+ }}, IsNonSpeculative, No_OpClass);
+ }
}
}
-}
+}
\ No newline at end of file