arch-riscv: Add support for compressed extension RV64C
authorAlec Roelke <ar4jc@virginia.edu>
Wed, 14 Jun 2017 21:33:29 +0000 (17:33 -0400)
committerAlec Roelke <ar4jc@virginia.edu>
Tue, 11 Jul 2017 03:45:14 +0000 (03:45 +0000)
This patch adds compatibility with the 64-bit compressed extension to
the RISC-V ISA, RV64C.  Current versions of the toolchain may use
compressed instructions in glibc by default, which can only be
overridden by recompiling the entire toolchain (simply adding
"-march=rv64g" or "-march=rv64imafd" when compiling a binary is not
sufficient to use uncompressed instructions in glibc functions in the
binary).

[Update diassembly generation for new RegId type.]
[Rebase onto master.]

Change-Id: Ifd5a5ea746704ce7e1b111442c3eb84c509a98b4
Reviewed-on: https://gem5-review.googlesource.com/3860
Reviewed-by: Alec Roelke <ar4jc@virginia.edu>
Maintainer: Alec Roelke <ar4jc@virginia.edu>

src/arch/riscv/decoder.cc
src/arch/riscv/decoder.hh
src/arch/riscv/isa/bitfields.isa
src/arch/riscv/isa/decoder.isa
src/arch/riscv/isa/formats/compressed.isa [new file with mode: 0644]
src/arch/riscv/isa/formats/formats.isa
src/arch/riscv/isa/formats/mem.isa
src/arch/riscv/isa/includes.isa
src/arch/riscv/isa/operands.isa
src/arch/riscv/types.hh

index acda6d04f644a29c4010e1232abaac465b686044..36504f4f8956387cf669b4604f715568b2201d00 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 Google
+ * Copyright (c) The University of Virginia
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Gabe Black
+ *          Alec Roelke
  */
 
 #include "arch/riscv/decoder.hh"
+#include "arch/riscv/types.hh"
+#include "debug/Decode.hh"
 
 namespace RiscvISA
 {
 
-GenericISA::BasicDecodeCache Decoder::defaultCache;
+void
+Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
+{
+    DPRINTF(Decode, "Getting bytes 0x%08x from address %#x\n",
+            inst, pc.pc());
+
+    bool aligned = pc.pc() % sizeof(MachInst) == 0;
+    if (mid) {
+        assert(!aligned);
+        emi |= (inst & 0xFFFF) << 16;
+        instDone = true;
+    } else {
+        MachInst instChunk = aligned ? inst & 0xFFFF :
+                                      (inst & 0xFFFF0000) >> 16;
+        if (aligned) {
+            emi = (inst & 0x3) < 0x3 ? instChunk : inst;
+            instDone = true;
+        } else {
+            emi = instChunk;
+            instDone = (instChunk & 0x3) < 0x3;
+        }
+    }
+    mid = !instDone;
+}
+
+StaticInstPtr
+Decoder::decode(ExtMachInst mach_inst, Addr addr)
+{
+    DPRINTF(Decode, "Decoding instruction 0x%08x at address %#x\n",
+            mach_inst, addr);
+    if (instMap.find(mach_inst) != instMap.end())
+        return instMap[mach_inst];
+    else {
+        StaticInstPtr si = decodeInst(mach_inst);
+        instMap[mach_inst] = si;
+        return si;
+    }
+}
+
+StaticInstPtr
+Decoder::decode(RiscvISA::PCState &nextPC)
+{
+    if (!instDone)
+        return nullptr;
+    instDone = false;
+
+    if ((emi & 0x3) < 0x3) {
+        nextPC.compressed(true);
+        nextPC.npc(nextPC.pc() + sizeof(MachInst)/2);
+    } else {
+        nextPC.compressed(false);
+        nextPC.npc(nextPC.pc() + sizeof(MachInst));
+    }
+
+    return decode(emi, nextPC.instAddr());
+}
 
 }
index b1d91d6101ca2a2c2c3c2271c6ce32fdd9b69d43..ef644fa13a962d27396ccb91bd954901919b35ff 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 Google
+ * Copyright (c) 2017 The University of Virginia
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Gabe Black
+ *          Alec Roelke
  */
 
 #ifndef __ARCH_RISCV_DECODER_HH__
 #define __ARCH_RISCV_DECODER_HH__
 
 #include "arch/generic/decode_cache.hh"
+#include "arch/riscv/isa_traits.hh"
 #include "arch/riscv/types.hh"
 #include "base/misc.hh"
 #include "base/types.hh"
 #include "cpu/static_inst.hh"
+#include "debug/Decode.hh"
 
 namespace RiscvISA
 {
@@ -43,73 +47,39 @@ namespace RiscvISA
 class ISA;
 class Decoder
 {
+  private:
+    DecodeCache::InstMap instMap;
+    bool mid;
+
   protected:
     //The extended machine instruction being generated
     ExtMachInst emi;
     bool instDone;
 
   public:
-    Decoder(ISA* isa = nullptr) : instDone(false)
+    Decoder(ISA* isa=nullptr)
+        : mid(false), emi(NoopMachInst), instDone(false)
     {}
 
-    void
-    process()
-    {
-    }
-
-    void
-    reset()
-    {
-        instDone = false;
-    }
+    void process() {}
+    void reset() { instDone = false; }
 
     //Use this to give data to the decoder. This should be used
     //when there is control flow.
-    void
-    moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
-    {
-        emi = inst;
-        instDone = true;
-    }
-
-    bool
-    needMoreBytes()
-    {
-        return true;
-    }
-
-    bool
-    instReady()
-    {
-        return instDone;
-    }
+    void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst);
 
+    bool needMoreBytes() { return true; }
+    bool instReady() { return instDone; }
     void takeOverFrom(Decoder *old) {}
 
-  protected:
-    /// A cache of decoded instruction objects.
-    static GenericISA::BasicDecodeCache defaultCache;
-
-  public:
     StaticInstPtr decodeInst(ExtMachInst mach_inst);
 
     /// Decode a machine instruction.
     /// @param mach_inst The binary instruction to decode.
     /// @retval A pointer to the corresponding StaticInst object.
-    StaticInstPtr
-    decode(ExtMachInst mach_inst, Addr addr)
-    {
-        return defaultCache.decode(this, mach_inst, addr);
-    }
+    StaticInstPtr decode(ExtMachInst mach_inst, Addr addr);
 
-    StaticInstPtr
-    decode(RiscvISA::PCState &nextPC)
-    {
-        if (!instDone)
-            return nullptr;
-        instDone = false;
-        return decode(emi, nextPC.instAddr());
-    }
+    StaticInstPtr decode(RiscvISA::PCState &nextPC);
 };
 
 } // namespace RiscvISA
index 23099a5e8999d0496680b73a999e25c7dce9121b..8372ed9735e310844a8f55292cb7ec1f0cda4b1f 100644 (file)
@@ -35,8 +35,8 @@
 // Bitfield definitions.
 //
 
-def bitfield OPCODE <6:0>;
-def bitfield NONOPCODE <31:7>;
+def bitfield QUADRANT <1:0>;
+def bitfield OPCODE <6:2>;
 
 // R-Type
 def bitfield ALL       <31:0>;
@@ -69,7 +69,7 @@ def bitfield BIMM12BITS10TO5 <30:25>;
 
 // UJ-Type
 def bitfield UJIMMBITS10TO1 <30:21>;
-def bitfield  UJIMMBIT11 <20>;
+def bitfield UJIMMBIT11 <20>;
 def bitfield UJIMMBITS19TO12 <19:12>;
 
 // System
@@ -90,3 +90,23 @@ def bitfield FUNCT2 <26:25>;
 def bitfield AMOFUNCT <31:27>;
 def bitfield AQ <26>;
 def bitfield RL <25>;
+
+// Compressed
+def bitfield COPCODE <15:13>;
+def bitfield CFUNCT1 <12>;
+def bitfield CFUNCT2HIGH <11:10>;
+def bitfield CFUNCT2LOW <6:5>;
+def bitfield RC1 <11:7>;
+def bitfield RC2 <6:2>;
+def bitfield RP1 <9:7>;
+def bitfield RP2 <4:2>;
+def bitfield FC1 <11:7>;
+def bitfield FC2 <6:2>;
+def bitfield FP2 <4:2>;
+def bitfield CJUMPIMM <12:2>;
+def bitfield CIMM8 <12:5>;
+def bitfield CIMM6 <12:7>;
+def bitfield CIMM5 <6:2>;
+def bitfield CIMM3 <12:10>;
+def bitfield CIMM2 <6:5>;
+def bitfield CIMM1 <12>;
index 8056d9615ebfe3fa7844ec98d5cdf9e0111c56ed..4f4ef7636034e79bcb080bb227a2cc1995938970 100644 (file)
@@ -1,7 +1,7 @@
 // -*- 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
diff --git a/src/arch/riscv/isa/formats/compressed.isa b/src/arch/riscv/isa/formats/compressed.isa
new file mode 100644 (file)
index 0000000..1fd2319
--- /dev/null
@@ -0,0 +1,102 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2015 RISC-V Foundation
+// Copyright (c) 2017 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
+
+output header {{
+    /**
+     * Base class for compressed operations that work only on registers
+     */
+    class CompRegOp : public RiscvStaticInst
+    {
+      protected:
+        /// Constructor
+        CompRegOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+            : RiscvStaticInst(mnem, _machInst, __opClass)
+        {}
+
+        std::string
+        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+    };
+}};
+
+output decoder {{
+    std::string
+    CompRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+    {
+        std::stringstream ss;
+        ss << mnemonic << ' ' << registerName(_destRegIdx[0]) << ", " <<
+            registerName(_srcRegIdx[0]);
+        return ss.str();
+    }
+}};
+
+def format CROp(code, *opt_flags) {{
+    iop = InstObjParams(name, Name, 'CompRegOp', code, opt_flags)
+    header_output = BasicDeclare.subst(iop)
+    decoder_output = BasicConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = BasicExecute.subst(iop)
+}};
+
+def format CIOp(imm_code, code, *opt_flags) {{
+    regs = ['_destRegIdx[0]','_srcRegIdx[0]']
+    iop = InstObjParams(name, Name, 'ImmOp',
+        {'code': code, 'imm_code': imm_code,
+         'regs': ','.join(regs)}, opt_flags)
+    header_output = ImmDeclare.subst(iop)
+    decoder_output = ImmConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = ImmExecute.subst(iop)
+}};
+
+def format CUIOp(imm_code, code, *opt_flags) {{
+    regs = ['_destRegIdx[0]','_srcRegIdx[0]']
+    iop = InstObjParams(name, Name, 'UImmOp',
+        {'code': code, 'imm_code': imm_code,
+         'regs': ','.join(regs)}, opt_flags)
+    header_output = ImmDeclare.subst(iop)
+    decoder_output = ImmConstructor.subst(iop)
+    decode_block = BasicDecode.subst(iop)
+    exec_output = ImmExecute.subst(iop)
+}};
+
+def format CompressedLoad(ldisp_code, memacc_code,
+        ea_code, mem_flags=[], inst_flags=[]) {{
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name, ldisp_code, ea_code, memacc_code, mem_flags,
+        inst_flags, 'Load', exec_template_base='Load')
+}};
+
+def format CompressedStore(sdisp_code, memacc_code,
+        ea_code, mem_flags=[], inst_flags=[]) {{
+    (header_output, decoder_output, decode_block, exec_output) = \
+        LoadStoreBase(name, Name, sdisp_code, ea_code, memacc_code, mem_flags,
+        inst_flags, 'Store', exec_template_base='Store')
+}};
\ No newline at end of file
index e13cac2639da19b712c0c980f33fe3507bdbc757..df2b3b84ad2ab0e6b4089ea704215dffaf7bd710 100644 (file)
 // Include the basic format
 ##include "basic.isa"
 
-//Include the type formats
+// Include the type formats
 ##include "standard.isa"
 ##include "mem.isa"
 ##include "fp.isa"
 ##include "amo.isa"
 
+// Include formats for nonstandard extensions
+##include "compressed.isa"
+
 // Include the unknown
 ##include "unknown.isa"
index 4ae8eb41a3d9faa91b0af215a7a56498ce3788ee..9b6bc9eb59ded5870f6b4a595f79b5a59958a6eb 100644 (file)
@@ -46,11 +46,8 @@ output header {{
 
         /// Constructor
         Load(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
-            : RiscvStaticInst(mnem, _machInst, __opClass), ldisp(IMM12)
-        {
-            if (IMMSIGN > 0)
-                ldisp |= ~((uint64_t)0xFFF);
-        }
+            : RiscvStaticInst(mnem, _machInst, __opClass), ldisp(0)
+        {}
 
         std::string
         generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -68,9 +65,9 @@ output header {{
 
         /// Constructor
         Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
-            : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(IMM5)
+            : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(0)
         {
-            sdisp |= IMM7 << 5;
+            sdisp = IMM5 | (IMM7 << 5);
             if (IMMSIGN > 0)
                 sdisp |= ~((uint64_t)0xFFF);
         }
@@ -143,6 +140,7 @@ def template LoadStoreConstructor {{
         %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
     {
         %(constructor)s;
+        %(offset_code)s;
     }
 }};
 
@@ -168,16 +166,17 @@ def template EACompExecute {{
 }};
 
 let {{
-def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
-        base_class, postacc_code='', decode_template=BasicDecode,
+def LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
+        inst_flags, base_class, postacc_code='', decode_template=BasicDecode,
         exec_template_base=''):
     # Make sure flags are in lists (convert to lists if not).
     mem_flags = makeList(mem_flags)
-    inst_flags = makeList(inst_flags) # + ['IsNonSpeculative']
+    inst_flags = makeList(inst_flags)
 
     iop = InstObjParams(name, Name, base_class,
-        { 'ea_code':ea_code, 'memacc_code':memacc_code,
-        'postacc_code':postacc_code }, inst_flags)
+        {'offset_code': offset_code, 'ea_code': ea_code,
+         'memacc_code': memacc_code, 'postacc_code': postacc_code },
+        inst_flags)
 
     if mem_flags:
         mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
@@ -342,14 +341,24 @@ def template StoreCompleteAcc {{
 
 def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[],
         inst_flags=[]) {{
+    offset_code = """
+                    ldisp = IMM12;
+                    if (IMMSIGN > 0)
+                        ldisp |= ~((uint64_t)0xFFF);
+                  """
     (header_output, decoder_output, decode_block, exec_output) = \
-        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
-        'Load', exec_template_base='Load')
+        LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
+        inst_flags, 'Load', exec_template_base='Load')
 }};
 
 def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[],
         inst_flags=[]) {{
+    offset_code = """
+                    sdisp = IMM5 | (IMM7 << 5);
+                    if (IMMSIGN > 0)
+                        sdisp |= ~((uint64_t)0xFFF);
+                  """
     (header_output, decoder_output, decode_block, exec_output) = \
-        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
-        'Store', exec_template_base='Store')
+        LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
+        inst_flags, 'Store', exec_template_base='Store')
 }};
index 443db67865fbcb4b86dbf9ab281ab2bfa29c17b8..82d1794fde6e0a2b00a1a3aae08de605502a97e1 100644 (file)
@@ -65,6 +65,7 @@ output decoder {{
 #include "sim/full_system.hh"
 
 using namespace RiscvISA;
+using namespace std;
 }};
 
 output exec {{
@@ -90,4 +91,5 @@ output exec {{
 #include "sim/system.hh"
 
 using namespace RiscvISA;
+using namespace std;
 }};
index 7a8385d0c6bfd300b50bd7b27a29bd1d3ec26c42..8dc1a3b82fa91aa5102fc8f00ed500358c440fe4 100644 (file)
@@ -49,6 +49,12 @@ def operands {{
     'Rs1': ('IntReg', 'ud', 'RS1', 'IsInteger', 2),
     'Rs2': ('IntReg', 'ud', 'RS2', 'IsInteger', 3),
     'Rt': ('IntReg', 'ud', 'AMOTempReg', 'IsInteger', 4),
+    'Rc1': ('IntReg', 'ud', 'RC1', 'IsInteger', 2),
+    'Rc2': ('IntReg', 'ud', 'RC2', 'IsInteger', 3),
+    'Rp1': ('IntReg', 'ud', 'RP1 + 8', 'IsInteger', 2),
+    'Rp2': ('IntReg', 'ud', 'RP2 + 8', 'IsInteger', 3),
+    'ra': ('IntReg', 'ud', 'ReturnAddrReg', 'IsInteger', 1),
+    'sp': ('IntReg', 'ud', 'StackPointerReg', 'IsInteger', 2),
 
     'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 1),
     'Fd_bits': ('FloatReg', 'ud', 'FD', 'IsFloating', 1),
@@ -58,6 +64,12 @@ def operands {{
     'Fs2_bits': ('FloatReg', 'ud', 'FS2', 'IsFloating', 3),
     'Fs3': ('FloatReg', 'df', 'FS3', 'IsFloating', 4),
     'Fs3_bits': ('FloatReg', 'ud', 'FS3', 'IsFloating', 4),
+    'Fc1': ('FloatReg', 'df', 'FC1', 'IsFloating', 1),
+    'Fc1_bits': ('FloatReg', 'ud', 'FC1', 'IsFloating', 1),
+    'Fc2': ('FloatReg', 'df', 'FC2', 'IsFloatReg', 2),
+    'Fc2_bits': ('FloatReg', 'ud', 'FC2', 'IsFloating', 2),
+    'Fp2': ('FloatReg', 'df', 'FP2 + 8', 'IsFloating', 2),
+    'Fp2_bits': ('FloatReg', 'ud', 'FP2 + 8', 'IsFloating', 2),
 
 #Memory Operand
     'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 5),
index 976a9e70e1f51a3774182e2bc0e82c503e58f009..f17d0b2350e733df45c7909de2899bda4627b7aa 100644 (file)
@@ -12,7 +12,7 @@
  * unmodified and in its entirety in all distributions of the software,
  * modified or unmodified, in source code or in binary form.
  *
- * 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
 
 namespace RiscvISA
 {
+
 typedef uint32_t MachInst;
 typedef uint64_t ExtMachInst;
 
-typedef GenericISA::UPCState<MachInst> PCState;
-}
+class PCState : public GenericISA::UPCState<MachInst>
+{
+  private:
+    bool _compressed;
+
+  public:
+    PCState() : UPCState() { _compressed = false; }
+    PCState(Addr val) : UPCState(val) { _compressed = false; }
 
+    void compressed(bool c) { _compressed = c; }
+    bool compressed() { return _compressed; }
+
+    bool
+    branching() const
+    {
+        if (_compressed) {
+            return npc() != pc() + sizeof(MachInst)/2 ||
+                    nupc() != upc() + 1;
+        } else {
+            return npc() != pc() + sizeof(MachInst) ||
+                    nupc() != upc() + 1;
+        }
+    }
+};
+
+}
 
-#endif // __ARCH_RISCV_TYPES_HH__
+#endif // __ARCH_RISCV_TYPES_HH__
\ No newline at end of file