arch-riscv: Stop "using namespace std"
[gem5.git] / src / arch / riscv / isa / decoder.isa
index 0c1d7726c57f290425ccbb3c5afcad40e08a20c9..b7e316122814a0d2a36ca3f88c9fb921e5d6c132 100644 (file)
@@ -2,6 +2,7 @@
 
 // Copyright (c) 2015 RISC-V Foundation
 // Copyright (c) 2017 The University of Virginia
+// Copyright (c) 2020 Barkhausen Institut
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -26,8 +27,6 @@
 // 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
 
 ////////////////////////////////////////////////////////////////////
 //
 
 decode QUADRANT default Unknown::unknown() {
     0x0: decode COPCODE {
-        0x0: CIOp::c_addi4spn({{
+        0x0: CIAddi4spnOp::c_addi4spn({{
             imm = CIMM8<1:1> << 2 |
                   CIMM8<0:0> << 3 |
                   CIMM8<7:6> << 4 |
                   CIMM8<5:2> << 6;
         }}, {{
             if (machInst == 0)
-                fault = make_shared<IllegalInstFault>("zero instruction",
-                                                      machInst);
+                fault = std::make_shared<IllegalInstFault>("zero instruction",
+                                                           machInst);
             Rp2 = sp + imm;
         }}, uint64_t);
         format CompressedLoad {
             0x1: c_fld({{
                 offset = CIMM3 << 3 | CIMM2 << 6;
             }}, {{
+                STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                if (status.fs == FPUStatus::OFF)
+                    fault = std::make_shared<IllegalInstFault>("FPU is off",
+                                                               machInst);
+
                 Fp2_bits = Mem;
             }}, {{
                 EA = Rp1 + offset;
@@ -76,6 +80,11 @@ decode QUADRANT default Unknown::unknown() {
             0x5: c_fsd({{
                 offset = CIMM3 << 3 | CIMM2 << 6;
             }}, {{
+                STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                if (status.fs == FPUStatus::OFF)
+                    fault = std::make_shared<IllegalInstFault>("FPU is off",
+                                                               machInst);
+
                 Mem = Fp2_bits;
             }}, {{
                 EA = Rp1 + offset;
@@ -107,11 +116,11 @@ decode QUADRANT default Unknown::unknown() {
             }}, {{
                 if ((RC1 == 0) != (imm == 0)) {
                     if (RC1 == 0) {
-                        fault = make_shared<IllegalInstFault>("source reg x0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x0", machInst);
                     } else // imm == 0
-                        fault = make_shared<IllegalInstFault>("immediate = 0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "immediate = 0", machInst);
                 }
                 Rc1_sd = Rc1_sd + imm;
             }});
@@ -121,8 +130,8 @@ decode QUADRANT default Unknown::unknown() {
                     imm |= ~((uint64_t)0x1F);
             }}, {{
                 if (RC1 == 0) {
-                    fault = make_shared<IllegalInstFault>("source reg x0",
-                                                          machInst);
+                    fault = std::make_shared<IllegalInstFault>(
+                            "source reg x0", machInst);
                 }
                 Rc1_sd = (int32_t)Rc1_sd + imm;
             }});
@@ -132,8 +141,8 @@ decode QUADRANT default Unknown::unknown() {
                     imm |= ~((uint64_t)0x1F);
             }}, {{
                 if (RC1 == 0) {
-                    fault = make_shared<IllegalInstFault>("source reg x0",
-                                                          machInst);
+                    fault = std::make_shared<IllegalInstFault>(
+                            "source reg x0", machInst);
                 }
                 Rc1_sd = imm;
             }});
@@ -147,8 +156,8 @@ decode QUADRANT default Unknown::unknown() {
                         imm |= ~((int64_t)0x1FF);
                 }}, {{
                     if (imm == 0) {
-                        fault = make_shared<IllegalInstFault>("immediate = 0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "immediate = 0", machInst);
                     }
                     sp_sd = sp_sd + imm;
                 }});
@@ -158,12 +167,12 @@ decode QUADRANT default Unknown::unknown() {
                         imm |= ~((uint64_t)0x1FFFF);
                 }}, {{
                     if (RC1 == 0 || RC1 == 2) {
-                        fault = make_shared<IllegalInstFault>("source reg x0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x0", machInst);
                     }
                     if (imm == 0) {
-                        fault = make_shared<IllegalInstFault>("immediate = 0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "immediate = 0", machInst);
                     }
                     Rc1_sd = imm;
                 }});
@@ -175,8 +184,8 @@ decode QUADRANT default Unknown::unknown() {
                     imm = CIMM5 | (CIMM1 << 5);
                 }}, {{
                     if (imm == 0) {
-                        fault = make_shared<IllegalInstFault>("immediate = 0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "immediate = 0", machInst);
                     }
                     Rp1 = Rp1 >> imm;
                 }}, uint64_t);
@@ -184,8 +193,8 @@ decode QUADRANT default Unknown::unknown() {
                     imm = CIMM5 | (CIMM1 << 5);
                 }}, {{
                     if (imm == 0) {
-                        fault = make_shared<IllegalInstFault>("immediate = 0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "immediate = 0", machInst);
                     }
                     Rp1_sd = Rp1_sd >> imm;
                 }}, uint64_t);
@@ -197,7 +206,7 @@ decode QUADRANT default Unknown::unknown() {
                     Rp1 = Rp1 & imm;
                 }}, uint64_t);
             }
-            format ROp {
+            format CompressedROp {
                 0x3: decode CFUNCT1 {
                     0x0: decode CFUNCT2LOW {
                         0x0: c_sub({{
@@ -224,18 +233,9 @@ decode QUADRANT default Unknown::unknown() {
                 }
             }
         }
-        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);
+        0x5: CJOp::c_j({{
+            NPC = PC + imm;
+        }}, IsDirectControl, IsUncondControl);
         format CBOp {
             0x6: c_beqz({{
                 if (Rp1 == 0)
@@ -256,12 +256,12 @@ decode QUADRANT default Unknown::unknown() {
             imm = CIMM5 | (CIMM1 << 5);
         }}, {{
             if (imm == 0) {
-                fault = make_shared<IllegalInstFault>("immediate = 0",
-                                                      machInst);
+                fault = std::make_shared<IllegalInstFault>(
+                        "immediate = 0", machInst);
             }
             if (RC1 == 0) {
-                fault = make_shared<IllegalInstFault>("source reg x0",
-                                                      machInst);
+                fault = std::make_shared<IllegalInstFault>(
+                        "source reg x0", machInst);
             }
             Rc1 = Rc1 << imm;
         }}, uint64_t);
@@ -281,8 +281,8 @@ decode QUADRANT default Unknown::unknown() {
                          CIMM5<1:0> << 6;
             }}, {{
                 if (RC1 == 0) {
-                    fault = make_shared<IllegalInstFault>("source reg x0",
-                                                          machInst);
+                    fault = std::make_shared<IllegalInstFault>(
+                            "source reg x0", machInst);
                 }
                 Rc1_sd = Mem_sw;
             }}, {{
@@ -294,8 +294,8 @@ decode QUADRANT default Unknown::unknown() {
                          CIMM5<2:0> << 6;
             }}, {{
                 if (RC1 == 0) {
-                    fault = make_shared<IllegalInstFault>("source reg x0",
-                                                          machInst);
+                    fault = std::make_shared<IllegalInstFault>(
+                            "source reg x0", machInst);
                 }
                 Rc1_sd = Mem_sd;
             }}, {{
@@ -306,15 +306,15 @@ decode QUADRANT default Unknown::unknown() {
             0x0: decode RC2 {
                 0x0: Jump::c_jr({{
                     if (RC1 == 0) {
-                        fault = make_shared<IllegalInstFault>("source reg x0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x0", machInst);
                     }
                     NPC = Rc1;
                 }}, IsIndirectControl, IsUncondControl, IsCall);
                 default: CROp::c_mv({{
                     if (RC1 == 0) {
-                        fault = make_shared<IllegalInstFault>("source reg x0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x0", machInst);
                     }
                     Rc1 = Rc2;
                 }});
@@ -322,22 +322,21 @@ decode QUADRANT default Unknown::unknown() {
             0x1: decode RC1 {
                 0x0: SystemOp::c_ebreak({{
                     if (RC2 != 0) {
-                        fault = make_shared<IllegalInstFault>("source reg x1",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x1", machInst);
                     }
-                    fault = make_shared<BreakpointFault>(xc->pcState());
+                    fault = std::make_shared<BreakpointFault>(xc->pcState());
                 }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
                 default: decode RC2 {
                     0x0: Jump::c_jalr({{
                         if (RC1 == 0) {
-                            fault = make_shared<IllegalInstFault>
-                                                        ("source reg x0",
-                                                         machInst);
+                            fault = std::make_shared<IllegalInstFault>(
+                                    "source reg x0", machInst);
                         }
                         ra = NPC;
                         NPC = Rc1;
                     }}, IsIndirectControl, IsUncondControl, IsCall);
-                    default: ROp::c_add({{
+                    default: CompressedROp::c_add({{
                         Rc1_sd = Rc1_sd + Rc2_sd;
                     }});
                 }
@@ -400,18 +399,29 @@ decode QUADRANT default Unknown::unknown() {
         0x01: decode FUNCT3 {
             format Load {
                 0x2: flw({{
+                    STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                    if (status.fs == FPUStatus::OFF) {
+                        fault = std::make_shared<IllegalInstFault>(
+                                "FPU is off", machInst);
+                    }
+
                     Fd_bits = (uint64_t)Mem_uw;
                 }}, inst_flags=FloatMemReadOp);
                 0x3: fld({{
+                    STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                    if (status.fs == FPUStatus::OFF)
+                        fault = std::make_shared<IllegalInstFault>(
+                                "FPU is off", machInst);
+
                     Fd_bits = Mem;
                 }}, inst_flags=FloatMemReadOp);
             }
         }
 
         0x03: decode FUNCT3 {
-            format IOp {
+            format FenceOp {
                 0x0: fence({{
-                }}, uint64_t, IsNonSpeculative, IsMemBarrier, No_OpClass);
+                }}, uint64_t, IsReadBarrier, IsWriteBarrier, No_OpClass);
                 0x1: fence_i({{
                 }}, uint64_t, IsNonSpeculative, IsSerializeAfter, No_OpClass);
             }
@@ -423,8 +433,8 @@ decode QUADRANT default Unknown::unknown() {
                     Rd_sd = Rs1_sd + imm;
                 }});
                 0x1: slli({{
-                    Rd = Rs1 << SHAMT6;
-                }});
+                    Rd = Rs1 << imm;
+                }}, imm_type = uint64_t, imm_code = {{ imm = SHAMT6; }});
                 0x2: slti({{
                     Rd = (Rs1_sd < imm) ? 1 : 0;
                 }});
@@ -436,11 +446,11 @@ decode QUADRANT default Unknown::unknown() {
                 }}, uint64_t);
                 0x5: decode SRTYPE {
                     0x0: srli({{
-                        Rd = Rs1 >> SHAMT6;
-                    }});
+                        Rd = Rs1 >> imm;
+                    }}, imm_type = uint64_t, imm_code = {{ imm = SHAMT6; }});
                     0x1: srai({{
-                        Rd_sd = Rs1_sd >> SHAMT6;
-                    }});
+                        Rd_sd = Rs1_sd >> imm;
+                    }}, imm_type = uint64_t, imm_code = {{ imm = SHAMT6; }});
                 }
                 0x6: ori({{
                     Rd = Rs1 | imm;
@@ -452,7 +462,7 @@ decode QUADRANT default Unknown::unknown() {
         }
 
         0x05: UOp::auipc({{
-            Rd = PC + imm;
+            Rd = PC + (sext<20>(imm) << 12);
         }});
 
         0x06: decode FUNCT3 {
@@ -461,15 +471,15 @@ decode QUADRANT default Unknown::unknown() {
                     Rd_sd = Rs1_sw + imm;
                 }}, int32_t);
                 0x1: slliw({{
-                    Rd_sd = Rs1_sw << SHAMT5;
-                }});
+                    Rd_sd = Rs1_sw << imm;
+                }}, imm_type = uint64_t, imm_code = {{ imm = SHAMT5; }});
                 0x5: decode SRTYPE {
                     0x0: srliw({{
-                        Rd_sd = (int32_t)(Rs1_uw >> SHAMT5);
-                    }});
+                        Rd_sd = (int32_t)(Rs1_uw >> imm);
+                    }}, imm_type = uint64_t, imm_code = {{ imm = SHAMT5; }});
                     0x1: sraiw({{
-                        Rd_sd = Rs1_sw >> SHAMT5;
-                    }});
+                        Rd_sd = Rs1_sw >> imm;
+                    }}, imm_type = uint64_t, imm_code = {{ imm = SHAMT5; }});
                 }
             }
         }
@@ -494,9 +504,19 @@ decode QUADRANT default Unknown::unknown() {
         0x09: decode FUNCT3 {
             format Store {
                 0x2: fsw({{
+                    STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                    if (status.fs == FPUStatus::OFF)
+                        fault = std::make_shared<IllegalInstFault>(
+                                "FPU is off", machInst);
+
                     Mem_uw = (uint32_t)Fs2_bits;
                 }}, inst_flags=FloatMemWriteOp);
                 0x3: fsd({{
+                    STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                    if (status.fs == FPUStatus::OFF)
+                        fault = std::make_shared<IllegalInstFault>(
+                                "FPU is off", machInst);
+
                     Mem_ud = Fs2_bits;
                 }}, inst_flags=FloatMemWriteOp);
             }
@@ -512,44 +532,69 @@ decode QUADRANT default Unknown::unknown() {
                 }}, {{
                     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;}});
-                }
+                0x0: AtomicMemOp::amoadd_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<int32_t> *amo_op =
+                          new AtomicGenericOp<int32_t>(Rs2_sw,
+                                  [](int32_t* b, int32_t a){ *b += a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x1: AtomicMemOp::amoswap_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<uint32_t> *amo_op =
+                          new AtomicGenericOp<uint32_t>(Rs2_uw,
+                                  [](uint32_t* b, uint32_t a){ *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x4: AtomicMemOp::amoxor_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<uint32_t> *amo_op =
+                          new AtomicGenericOp<uint32_t>(Rs2_uw,
+                                  [](uint32_t* b, uint32_t a){ *b ^= a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x8: AtomicMemOp::amoor_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<uint32_t> *amo_op =
+                          new AtomicGenericOp<uint32_t>(Rs2_uw,
+                                  [](uint32_t* b, uint32_t a){ *b |= a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0xc: AtomicMemOp::amoand_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<uint32_t> *amo_op =
+                          new AtomicGenericOp<uint32_t>(Rs2_uw,
+                                  [](uint32_t* b, uint32_t a){ *b &= a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x10: AtomicMemOp::amomin_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<int32_t> *amo_op =
+                      new AtomicGenericOp<int32_t>(Rs2_sw,
+                        [](int32_t* b, int32_t a){ if (a < *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x14: AtomicMemOp::amomax_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<int32_t> *amo_op =
+                      new AtomicGenericOp<int32_t>(Rs2_sw,
+                        [](int32_t* b, int32_t a){ if (a > *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x18: AtomicMemOp::amominu_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<uint32_t> *amo_op =
+                      new AtomicGenericOp<uint32_t>(Rs2_uw,
+                        [](uint32_t* b, uint32_t a){ if (a < *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x1c: AtomicMemOp::amomaxu_w({{
+                    Rd_sd = Mem_sw;
+                }}, {{
+                    TypedAtomicOpFunctor<uint32_t> *amo_op =
+                      new AtomicGenericOp<uint32_t>(Rs2_uw,
+                        [](uint32_t* b, uint32_t a){ if (a > *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
             }
             0x3: decode AMOFUNCT {
                 0x2: LoadReserved::lr_d({{
@@ -560,44 +605,69 @@ decode QUADRANT default Unknown::unknown() {
                 }}, {{
                     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;}});
-                }
+                0x0: AtomicMemOp::amoadd_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<int64_t> *amo_op =
+                          new AtomicGenericOp<int64_t>(Rs2_sd,
+                                  [](int64_t* b, int64_t a){ *b += a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x1: AtomicMemOp::amoswap_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<uint64_t> *amo_op =
+                          new AtomicGenericOp<uint64_t>(Rs2_ud,
+                                  [](uint64_t* b, uint64_t a){ *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x4: AtomicMemOp::amoxor_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<uint64_t> *amo_op =
+                          new AtomicGenericOp<uint64_t>(Rs2_ud,
+                                 [](uint64_t* b, uint64_t a){ *b ^= a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x8: AtomicMemOp::amoor_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<uint64_t> *amo_op =
+                          new AtomicGenericOp<uint64_t>(Rs2_ud,
+                                 [](uint64_t* b, uint64_t a){ *b |= a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0xc: AtomicMemOp::amoand_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<uint64_t> *amo_op =
+                          new AtomicGenericOp<uint64_t>(Rs2_ud,
+                                 [](uint64_t* b, uint64_t a){ *b &= a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x10: AtomicMemOp::amomin_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<int64_t> *amo_op =
+                      new AtomicGenericOp<int64_t>(Rs2_sd,
+                        [](int64_t* b, int64_t a){ if (a < *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x14: AtomicMemOp::amomax_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<int64_t> *amo_op =
+                      new AtomicGenericOp<int64_t>(Rs2_sd,
+                        [](int64_t* b, int64_t a){ if (a > *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x18: AtomicMemOp::amominu_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<uint64_t> *amo_op =
+                      new AtomicGenericOp<uint64_t>(Rs2_ud,
+                        [](uint64_t* b, uint64_t a){ if (a < *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
+                0x1c: AtomicMemOp::amomaxu_d({{
+                    Rd_sd = Mem_sd;
+                }}, {{
+                    TypedAtomicOpFunctor<uint64_t> *amo_op =
+                      new AtomicGenericOp<uint64_t>(Rs2_ud,
+                        [](uint64_t* b, uint64_t a){ if (a > *b) *b = a; });
+                }}, mem_flags=ATOMIC_RETURN_OP);
             }
         }
         0x0c: decode FUNCT3 {
@@ -692,9 +762,10 @@ decode QUADRANT default Unknown::unknown() {
                     0x1: div({{
                         if (Rs2_sd == 0) {
                             Rd_sd = -1;
-                        } else if (Rs1_sd == numeric_limits<int64_t>::min()
+                        } else if (
+                                Rs1_sd == std::numeric_limits<int64_t>::min()
                                 && Rs2_sd == -1) {
-                            Rd_sd = numeric_limits<int64_t>::min();
+                            Rd_sd = std::numeric_limits<int64_t>::min();
                         } else {
                             Rd_sd = Rs1_sd/Rs2_sd;
                         }
@@ -706,7 +777,7 @@ decode QUADRANT default Unknown::unknown() {
                     }});
                     0x1: divu({{
                         if (Rs2 == 0) {
-                            Rd = numeric_limits<uint64_t>::max();
+                            Rd = std::numeric_limits<uint64_t>::max();
                         } else {
                             Rd = Rs1/Rs2;
                         }
@@ -722,7 +793,8 @@ decode QUADRANT default Unknown::unknown() {
                     0x1: rem({{
                         if (Rs2_sd == 0) {
                             Rd = Rs1_sd;
-                        } else if (Rs1_sd == numeric_limits<int64_t>::min()
+                        } else if (
+                                Rs1_sd == std::numeric_limits<int64_t>::min()
                                 && Rs2_sd == -1) {
                             Rd = 0;
                         } else {
@@ -746,7 +818,7 @@ decode QUADRANT default Unknown::unknown() {
         }
 
         0x0d: UOp::lui({{
-            Rd = (uint64_t)imm;
+            Rd = (uint64_t)(sext<20>(imm) << 12);
         }});
 
         0x0e: decode FUNCT3 {
@@ -768,9 +840,9 @@ decode QUADRANT default Unknown::unknown() {
                 0x4: divw({{
                     if (Rs2_sw == 0) {
                         Rd_sd = -1;
-                    } else if (Rs1_sw == numeric_limits<int32_t>::min()
+                    } else if (Rs1_sw == std::numeric_limits<int32_t>::min()
                             && Rs2_sw == -1) {
-                        Rd_sd = numeric_limits<int32_t>::min();
+                        Rd_sd = std::numeric_limits<int32_t>::min();
                     } else {
                         Rd_sd = Rs1_sw/Rs2_sw;
                     }
@@ -781,7 +853,7 @@ decode QUADRANT default Unknown::unknown() {
                     }});
                     0x1: divuw({{
                         if (Rs2_uw == 0) {
-                            Rd_sd = numeric_limits<IntReg>::max();
+                            Rd_sd = std::numeric_limits<uint64_t>::max();
                         } else {
                             Rd_sd = (int32_t)(Rs1_uw/Rs2_uw);
                         }
@@ -793,7 +865,7 @@ decode QUADRANT default Unknown::unknown() {
                 0x6: remw({{
                     if (Rs2_sw == 0) {
                         Rd_sd = Rs1_sw;
-                    } else if (Rs1_sw == numeric_limits<int32_t>::min()
+                    } else if (Rs1_sw == std::numeric_limits<int32_t>::min()
                             && Rs2_sw == -1) {
                         Rd_sd = 0;
                     } else {
@@ -825,15 +897,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else if (std::isinf(fs1) || std::isinf(fs2) ||
                             std::isinf(fs3)) {
-                        if (signbit(fs1) == signbit(fs2)
+                        if (std::signbit(fs1) == std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = numeric_limits<float>::infinity();
-                        } else if (signbit(fs1) != signbit(fs2)
+                            fd = std::numeric_limits<float>::infinity();
+                        } else if (std::signbit(fs1) != std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = -numeric_limits<float>::infinity();
+                            fd = -std::numeric_limits<float>::infinity();
                         } else { // Fs3_sf is infinity
                             fd = fs3;
                         }
@@ -849,15 +921,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(Fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else if (std::isinf(Fs1) || std::isinf(Fs2) ||
                             std::isinf(Fs3)) {
-                        if (signbit(Fs1) == signbit(Fs2)
+                        if (std::signbit(Fs1) == std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = numeric_limits<double>::infinity();
-                        } else if (signbit(Fs1) != signbit(Fs2)
+                            Fd = std::numeric_limits<double>::infinity();
+                        } else if (std::signbit(Fs1) != std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = -numeric_limits<double>::infinity();
+                            Fd = -std::numeric_limits<double>::infinity();
                         } else {
                             Fd = Fs3;
                         }
@@ -880,15 +952,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else if (std::isinf(fs1) || std::isinf(fs2) ||
                             std::isinf(fs3)) {
-                        if (signbit(fs1) == signbit(fs2)
+                        if (std::signbit(fs1) == std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = numeric_limits<float>::infinity();
-                        } else if (signbit(fs1) != signbit(fs2)
+                            fd = std::numeric_limits<float>::infinity();
+                        } else if (std::signbit(fs1) != std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = -numeric_limits<float>::infinity();
+                            fd = -std::numeric_limits<float>::infinity();
                         } else { // Fs3_sf is infinity
                             fd = -fs3;
                         }
@@ -904,15 +976,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(Fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else if (std::isinf(Fs1) || std::isinf(Fs2) ||
                             std::isinf(Fs3)) {
-                        if (signbit(Fs1) == signbit(Fs2)
+                        if (std::signbit(Fs1) == std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = numeric_limits<double>::infinity();
-                        } else if (signbit(Fs1) != signbit(Fs2)
+                            Fd = std::numeric_limits<double>::infinity();
+                        } else if (std::signbit(Fs1) != std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = -numeric_limits<double>::infinity();
+                            Fd = -std::numeric_limits<double>::infinity();
                         } else {
                             Fd = -Fs3;
                         }
@@ -935,15 +1007,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else if (std::isinf(fs1) || std::isinf(fs2) ||
                             std::isinf(fs3)) {
-                        if (signbit(fs1) == signbit(fs2)
+                        if (std::signbit(fs1) == std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = -numeric_limits<float>::infinity();
-                        } else if (signbit(fs1) != signbit(fs2)
+                            fd = -std::numeric_limits<float>::infinity();
+                        } else if (std::signbit(fs1) != std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = numeric_limits<float>::infinity();
+                            fd = std::numeric_limits<float>::infinity();
                         } else { // Fs3_sf is infinity
                             fd = fs3;
                         }
@@ -959,15 +1031,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(Fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else if (std::isinf(Fs1) || std::isinf(Fs2)
                             || std::isinf(Fs3)) {
-                        if (signbit(Fs1) == signbit(Fs2)
+                        if (std::signbit(Fs1) == std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = -numeric_limits<double>::infinity();
-                        } else if (signbit(Fs1) != signbit(Fs2)
+                            Fd = -std::numeric_limits<double>::infinity();
+                        } else if (std::signbit(Fs1) != std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = numeric_limits<double>::infinity();
+                            Fd = std::numeric_limits<double>::infinity();
                         } else {
                             Fd = Fs3;
                         }
@@ -990,15 +1062,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else if (std::isinf(fs1) || std::isinf(fs2) ||
                             std::isinf(fs3)) {
-                        if (signbit(fs1) == signbit(fs2)
+                        if (std::signbit(fs1) == std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = -numeric_limits<float>::infinity();
-                        } else if (signbit(fs1) != signbit(fs2)
+                            fd = -std::numeric_limits<float>::infinity();
+                        } else if (std::signbit(fs1) != std::signbit(fs2)
                                 && !std::isinf(fs3)) {
-                            fd = numeric_limits<float>::infinity();
+                            fd = std::numeric_limits<float>::infinity();
                         } else { // Fs3_sf is infinity
                             fd = -fs3;
                         }
@@ -1014,15 +1086,15 @@ decode QUADRANT default Unknown::unknown() {
                                 || issignalingnan(Fs3)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else if (std::isinf(Fs1) || std::isinf(Fs2) ||
                             std::isinf(Fs3)) {
-                        if (signbit(Fs1) == signbit(Fs2)
+                        if (std::signbit(Fs1) == std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = -numeric_limits<double>::infinity();
-                        } else if (signbit(Fs1) != signbit(Fs2)
+                            Fd = -std::numeric_limits<double>::infinity();
+                        } else if (std::signbit(Fs1) != std::signbit(Fs2)
                                 && !std::isinf(Fs3)) {
-                            Fd = numeric_limits<double>::infinity();
+                            Fd = std::numeric_limits<double>::infinity();
                         } else {
                             Fd = -Fs3;
                         }
@@ -1042,7 +1114,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(fs1) || issignalingnan(fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else {
                         fd = fs1 + fs2;
                     }
@@ -1053,7 +1125,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else {
                         Fd = Fs1 + Fs2;
                     }
@@ -1068,7 +1140,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(fs1) || issignalingnan(fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else {
                         fd = fs1 - fs2;
                     }
@@ -1079,7 +1151,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else {
                         Fd = Fs1 - Fs2;
                     }
@@ -1094,7 +1166,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(fs1) || issignalingnan(fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else {
                         fd = fs1*fs2;
                     }
@@ -1105,7 +1177,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else {
                         Fd = Fs1*Fs2;
                     }
@@ -1120,7 +1192,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(fs1) || issignalingnan(fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                     } else {
                         fd = fs1/fs2;
                     }
@@ -1131,7 +1203,7 @@ decode QUADRANT default Unknown::unknown() {
                         if (issignalingnan(Fs1) || issignalingnan(Fs2)) {
                             FFLAGS |= FloatInvalid;
                         }
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                     } else {
                         Fd = Fs1/Fs2;
                     }
@@ -1144,7 +1216,7 @@ decode QUADRANT default Unknown::unknown() {
                         float fd;
 
                         if (issignalingnan(fs1)) {
-                            fd = numeric_limits<float>::signaling_NaN();
+                            fd = std::numeric_limits<float>::signaling_NaN();
                             feclearexcept(FE_INVALID);
                         } else {
                             fd = copysign(fs1, fs2);
@@ -1158,7 +1230,7 @@ decode QUADRANT default Unknown::unknown() {
                         float fd;
 
                         if (issignalingnan(fs1)) {
-                            fd = numeric_limits<float>::signaling_NaN();
+                            fd = std::numeric_limits<float>::signaling_NaN();
                             feclearexcept(FE_INVALID);
                         } else {
                             fd = copysign(fs1, -fs2);
@@ -1172,10 +1244,10 @@ decode QUADRANT default Unknown::unknown() {
                         float fd;
 
                         if (issignalingnan(fs1)) {
-                            fd = numeric_limits<float>::signaling_NaN();
+                            fd = std::numeric_limits<float>::signaling_NaN();
                             feclearexcept(FE_INVALID);
                         } else {
-                            fd = fs1*(signbit(fs2) ? -1.0 : 1.0);
+                            fd = fs1*(std::signbit(fs2) ? -1.0 : 1.0);
                         }
                         Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd);
                     }}, FloatMiscOp);
@@ -1183,7 +1255,7 @@ decode QUADRANT default Unknown::unknown() {
                 0x11: decode ROUND_MODE {
                     0x0: fsgnj_d({{
                         if (issignalingnan(Fs1)) {
-                            Fd = numeric_limits<double>::signaling_NaN();
+                            Fd = std::numeric_limits<double>::signaling_NaN();
                             feclearexcept(FE_INVALID);
                         } else {
                             Fd = copysign(Fs1, Fs2);
@@ -1191,7 +1263,7 @@ decode QUADRANT default Unknown::unknown() {
                     }}, FloatMiscOp);
                     0x1: fsgnjn_d({{
                         if (issignalingnan(Fs1)) {
-                            Fd = numeric_limits<double>::signaling_NaN();
+                            Fd = std::numeric_limits<double>::signaling_NaN();
                             feclearexcept(FE_INVALID);
                         } else {
                             Fd = copysign(Fs1, -Fs2);
@@ -1199,10 +1271,10 @@ decode QUADRANT default Unknown::unknown() {
                     }}, FloatMiscOp);
                     0x2: fsgnjx_d({{
                         if (issignalingnan(Fs1)) {
-                            Fd = numeric_limits<double>::signaling_NaN();
+                            Fd = std::numeric_limits<double>::signaling_NaN();
                             feclearexcept(FE_INVALID);
                         } else {
-                            Fd = Fs1*(signbit(Fs2) ? -1.0 : 1.0);
+                            Fd = Fs1*(std::signbit(Fs2) ? -1.0 : 1.0);
                         }
                     }}, FloatMiscOp);
                 }
@@ -1268,12 +1340,12 @@ decode QUADRANT default Unknown::unknown() {
                 }
                 0x20: fcvt_s_d({{
                     if (CONV_SGN != 1) {
-                        fault = make_shared<IllegalInstFault>("CONV_SGN != 1",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "CONV_SGN != 1", machInst);
                     }
                     float fd;
                     if (issignalingnan(Fs1)) {
-                        fd = numeric_limits<float>::quiet_NaN();
+                        fd = std::numeric_limits<float>::quiet_NaN();
                         FFLAGS |= FloatInvalid;
                     } else {
                         fd = (float)Fs1;
@@ -1282,14 +1354,14 @@ decode QUADRANT default Unknown::unknown() {
                 }}, FloatCvtOp);
                 0x21: fcvt_d_s({{
                     if (CONV_SGN != 0) {
-                        fault = make_shared<IllegalInstFault>("CONV_SGN != 0",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "CONV_SGN != 0", machInst);
                     }
                     uint32_t temp;
                     float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
 
                     if (issignalingnan(fs1)) {
-                        Fd = numeric_limits<double>::quiet_NaN();
+                        Fd = std::numeric_limits<double>::quiet_NaN();
                         FFLAGS |= FloatInvalid;
                     } else {
                         Fd = (double)fs1;
@@ -1297,8 +1369,8 @@ decode QUADRANT default Unknown::unknown() {
                 }}, FloatCvtOp);
                 0x2c: fsqrt_s({{
                     if (RS2 != 0) {
-                        fault = make_shared<IllegalInstFault>("source reg x1",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x1", machInst);
                     }
                     uint32_t temp;
                     float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
@@ -1312,8 +1384,8 @@ decode QUADRANT default Unknown::unknown() {
                 }}, FloatSqrtOp);
                 0x2d: fsqrt_d({{
                     if (RS2 != 0) {
-                        fault = make_shared<IllegalInstFault>("source reg x1",
-                                                              machInst);
+                        fault = std::make_shared<IllegalInstFault>(
+                                "source reg x1", machInst);
                     }
                     Fd = sqrt(Fs1);
                 }}, FloatSqrtOp);
@@ -1383,13 +1455,15 @@ decode QUADRANT default Unknown::unknown() {
                         float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
 
                         if (std::isnan(fs1)) {
-                            Rd_sd = numeric_limits<int32_t>::max();
+                            Rd_sd = std::numeric_limits<int32_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (fs1 >= numeric_limits<int32_t>::max()) {
-                            Rd_sd = numeric_limits<int32_t>::max();
+                        } else if (fs1 >=
+                                float(std::numeric_limits<int32_t>::max())) {
+                            Rd_sd = std::numeric_limits<int32_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (fs1 <= numeric_limits<int32_t>::min()) {
-                            Rd_sd = numeric_limits<int32_t>::min();
+                        } else if (fs1 <=
+                                float(std::numeric_limits<int32_t>::min())) {
+                            Rd_sd = std::numeric_limits<int32_t>::min();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd_sd = (int32_t)fs1;
@@ -1400,13 +1474,14 @@ decode QUADRANT default Unknown::unknown() {
                         float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
 
                         if (std::isnan(fs1)) {
-                            Rd = numeric_limits<uint64_t>::max();
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else if (fs1 < 0.0) {
                             Rd = 0;
                             FFLAGS |= FloatInvalid;
-                        } else if (fs1 > numeric_limits<uint32_t>::max()) {
-                            Rd = numeric_limits<uint64_t>::max();
+                        } else if (fs1 >
+                                float(std::numeric_limits<uint32_t>::max())) {
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd = (uint32_t)fs1;
@@ -1417,13 +1492,15 @@ decode QUADRANT default Unknown::unknown() {
                         float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
 
                         if (std::isnan(fs1)) {
-                            Rd_sd = numeric_limits<int64_t>::max();
+                            Rd_sd = std::numeric_limits<int64_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (fs1 > numeric_limits<int64_t>::max()) {
-                            Rd_sd = numeric_limits<int64_t>::max();
+                        } else if (fs1 >
+                                float(std::numeric_limits<int64_t>::max())) {
+                            Rd_sd = std::numeric_limits<int64_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (fs1 < numeric_limits<int64_t>::min()) {
-                            Rd_sd = numeric_limits<int64_t>::min();
+                        } else if (fs1 <
+                                float(std::numeric_limits<int64_t>::min())) {
+                            Rd_sd = std::numeric_limits<int64_t>::min();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd_sd = (int64_t)fs1;
@@ -1434,13 +1511,14 @@ decode QUADRANT default Unknown::unknown() {
                         float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
 
                         if (std::isnan(fs1)) {
-                            Rd = numeric_limits<uint64_t>::max();
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else if (fs1 < 0.0) {
                             Rd = 0;
                             FFLAGS |= FloatInvalid;
-                        } else if (fs1 > numeric_limits<uint64_t>::max()) {
-                            Rd = numeric_limits<uint64_t>::max();
+                        } else if (fs1 >
+                                float(std::numeric_limits<uint64_t>::max())) {
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd = (uint64_t)fs1;
@@ -1450,13 +1528,15 @@ decode QUADRANT default Unknown::unknown() {
                 0x61: decode CONV_SGN {
                     0x0: fcvt_w_d({{
                         if (std::isnan(Fs1)) {
-                            Rd_sd = numeric_limits<int32_t>::max();
+                            Rd_sd = std::numeric_limits<int32_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (Fs1 > numeric_limits<int32_t>::max()) {
-                            Rd_sd = numeric_limits<int32_t>::max();
+                        } else if (Fs1 >
+                                float(std::numeric_limits<int32_t>::max())) {
+                            Rd_sd = std::numeric_limits<int32_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (Fs1 < numeric_limits<int32_t>::min()) {
-                            Rd_sd = numeric_limits<int32_t>::min();
+                        } else if (Fs1 <
+                                float(std::numeric_limits<int32_t>::min())) {
+                            Rd_sd = std::numeric_limits<int32_t>::min();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd_sd = (int32_t)Fs1;
@@ -1464,13 +1544,14 @@ decode QUADRANT default Unknown::unknown() {
                     }}, FloatCvtOp);
                     0x1: fcvt_wu_d({{
                         if (std::isnan(Fs1)) {
-                            Rd = numeric_limits<uint64_t>::max();
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else if (Fs1 < 0) {
                             Rd = 0;
                             FFLAGS |= FloatInvalid;
-                        } else if (Fs1 > numeric_limits<uint32_t>::max()) {
-                            Rd = numeric_limits<uint64_t>::max();
+                        } else if (Fs1 >
+                                float(std::numeric_limits<uint32_t>::max())) {
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd = (uint32_t)Fs1;
@@ -1478,13 +1559,15 @@ decode QUADRANT default Unknown::unknown() {
                     }}, FloatCvtOp);
                     0x2: fcvt_l_d({{
                         if (std::isnan(Fs1)) {
-                            Rd_sd = numeric_limits<int64_t>::max();
+                            Rd_sd = std::numeric_limits<int64_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (Fs1 > numeric_limits<int64_t>::max()) {
-                            Rd_sd = numeric_limits<int64_t>::max();
+                        } else if (Fs1 >
+                                float(std::numeric_limits<int64_t>::max())) {
+                            Rd_sd = std::numeric_limits<int64_t>::max();
                             FFLAGS |= FloatInvalid;
-                        } else if (Fs1 < numeric_limits<int64_t>::min()) {
-                            Rd_sd = numeric_limits<int64_t>::min();
+                        } else if (Fs1 <
+                                float(std::numeric_limits<int64_t>::min())) {
+                            Rd_sd = std::numeric_limits<int64_t>::min();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd_sd = Fs1;
@@ -1492,13 +1575,14 @@ decode QUADRANT default Unknown::unknown() {
                     }}, FloatCvtOp);
                     0x3: fcvt_lu_d({{
                         if (std::isnan(Fs1)) {
-                            Rd = numeric_limits<uint64_t>::max();
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else if (Fs1 < 0) {
                             Rd = 0;
                             FFLAGS |= FloatInvalid;
-                        } else if (Fs1 > numeric_limits<uint64_t>::max()) {
-                            Rd = numeric_limits<uint64_t>::max();
+                        } else if (Fs1 >
+                                float(std::numeric_limits<uint64_t>::max())) {
+                            Rd = std::numeric_limits<uint64_t>::max();
                             FFLAGS |= FloatInvalid;
                         } else {
                             Rd = Fs1;
@@ -1547,9 +1631,9 @@ decode QUADRANT default Unknown::unknown() {
                     0x1: fclass_s({{
                         uint32_t temp;
                         float fs1 = reinterpret_cast<float&>(temp = Fs1_bits);
-                        switch (fpclassify(fs1)) {
+                        switch (std::fpclassify(fs1)) {
                           case FP_INFINITE:
-                            if (signbit(fs1)) {
+                            if (std::signbit(fs1)) {
                                 Rd = 1 << 0;
                             } else {
                                 Rd = 1 << 7;
@@ -1563,21 +1647,21 @@ decode QUADRANT default Unknown::unknown() {
                             }
                             break;
                           case FP_ZERO:
-                            if (signbit(fs1)) {
+                            if (std::signbit(fs1)) {
                                 Rd = 1 << 3;
                             } else {
                                 Rd = 1 << 4;
                             }
                             break;
                           case FP_SUBNORMAL:
-                            if (signbit(fs1)) {
+                            if (std::signbit(fs1)) {
                                 Rd = 1 << 2;
                             } else {
                                 Rd = 1 << 5;
                             }
                             break;
                           case FP_NORMAL:
-                            if (signbit(fs1)) {
+                            if (std::signbit(fs1)) {
                                 Rd = 1 << 1;
                             } else {
                                 Rd = 1 << 6;
@@ -1594,9 +1678,9 @@ decode QUADRANT default Unknown::unknown() {
                         Rd = Fs1_bits;
                     }}, FloatCvtOp);
                     0x1: fclass_d({{
-                        switch (fpclassify(Fs1)) {
+                        switch (std::fpclassify(Fs1)) {
                           case FP_INFINITE:
-                            if (signbit(Fs1)) {
+                            if (std::signbit(Fs1)) {
                                 Rd = 1 << 0;
                             } else {
                                 Rd = 1 << 7;
@@ -1610,21 +1694,21 @@ decode QUADRANT default Unknown::unknown() {
                             }
                             break;
                           case FP_ZERO:
-                            if (signbit(Fs1)) {
+                            if (std::signbit(Fs1)) {
                                 Rd = 1 << 3;
                             } else {
                                 Rd = 1 << 4;
                             }
                             break;
                           case FP_SUBNORMAL:
-                            if (signbit(Fs1)) {
+                            if (std::signbit(Fs1)) {
                                 Rd = 1 << 2;
                             } else {
                                 Rd = 1 << 5;
                             }
                             break;
                           case FP_NORMAL:
-                            if (signbit(Fs1)) {
+                            if (std::signbit(Fs1)) {
                                 Rd = 1 << 1;
                             } else {
                                 Rd = 1 << 6;
@@ -1706,40 +1790,71 @@ decode QUADRANT default Unknown::unknown() {
 
         0x1c: decode FUNCT3 {
             format SystemOp {
-                0x0: decode FUNCT12 {
-                    0x0: ecall({{
-                        fault = make_shared<SyscallFault>(
+                0x0: decode FUNCT7 {
+                    0x0: decode RS2 {
+                        0x0: ecall({{
+                            fault = std::make_shared<SyscallFault>(
                                 (PrivilegeMode)xc->readMiscReg(MISCREG_PRV));
-                    }}, IsSerializeAfter, IsNonSpeculative, IsSyscall,
-                        No_OpClass);
-                    0x1: ebreak({{
-                        fault = make_shared<BreakpointFault>(xc->pcState());
-                    }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
-                    0x2: uret({{
-                        STATUS status = xc->readMiscReg(MISCREG_STATUS);
-                        status.uie = status.upie;
-                        status.upie = 1;
-                        xc->setMiscReg(MISCREG_STATUS, status);
-                        NPC = xc->readMiscReg(MISCREG_UEPC);
-                    }}, IsReturn);
-                    0x102: sret({{
-                        if (xc->readMiscReg(MISCREG_PRV) == PRV_U) {
-                            fault = make_shared<IllegalInstFault>(
-                                        "sret in user mode", machInst);
-                            NPC = NPC;
-                        } else {
+                        }}, IsSerializeAfter, IsNonSpeculative, IsSyscall,
+                            No_OpClass);
+                        0x1: ebreak({{
+                            fault = std::make_shared<BreakpointFault>(
+                                xc->pcState());
+                        }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
+                        0x2: uret({{
                             STATUS status = xc->readMiscReg(MISCREG_STATUS);
-                            xc->setMiscReg(MISCREG_PRV, status.spp);
-                            status.sie = status.spie;
-                            status.spie = 1;
-                            status.spp = PRV_U;
+                            status.uie = status.upie;
+                            status.upie = 1;
                             xc->setMiscReg(MISCREG_STATUS, status);
-                            NPC = xc->readMiscReg(MISCREG_SEPC);
+                            NPC = xc->readMiscReg(MISCREG_UEPC);
+                        }}, IsSerializeAfter, IsNonSpeculative, IsReturn);
+                    }
+                    0x8: decode RS2 {
+                        0x2: sret({{
+                            STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                            auto pm = (PrivilegeMode)xc->readMiscReg(
+                                MISCREG_PRV);
+                            if (pm == PRV_U ||
+                                (pm == PRV_S && status.tsr == 1)) {
+                                fault = std::make_shared<IllegalInstFault>(
+                                            "sret in user mode or TSR enabled",
+                                            machInst);
+                                NPC = NPC;
+                            } else {
+                                xc->setMiscReg(MISCREG_PRV, status.spp);
+                                status.sie = status.spie;
+                                status.spie = 1;
+                                status.spp = PRV_U;
+                                xc->setMiscReg(MISCREG_STATUS, status);
+                                NPC = xc->readMiscReg(MISCREG_SEPC);
+                            }
+                        }}, IsSerializeAfter, IsNonSpeculative, IsReturn);
+                        0x5: wfi({{
+                            STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                            auto pm = (PrivilegeMode)xc->readMiscReg(
+                                MISCREG_PRV);
+                            if (pm == PRV_U ||
+                                (pm == PRV_S && status.tw == 1)) {
+                                fault = std::make_shared<IllegalInstFault>(
+                                            "wfi in user mode or TW enabled",
+                                            machInst);
+                            }
+                            // don't do anything for now
+                        }}, No_OpClass);
+                    }
+                    0x9: sfence_vma({{
+                        STATUS status = xc->readMiscReg(MISCREG_STATUS);
+                        auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
+                        if (pm == PRV_U || (pm == PRV_S && status.tvm == 1)) {
+                            fault = std::make_shared<IllegalInstFault>(
+                                        "sfence in user mode or TVM enabled",
+                                        machInst);
                         }
-                    }}, IsReturn);
-                    0x302: mret({{
+                        xc->tcBase()->getMMUPtr()->demapPage(Rs1, Rs2);
+                    }}, IsNonSpeculative, IsSerializeAfter, No_OpClass);
+                    0x18: mret({{
                         if (xc->readMiscReg(MISCREG_PRV) != PRV_M) {
-                            fault = make_shared<IllegalInstFault>(
+                            fault = std::make_shared<IllegalInstFault>(
                                         "mret at lower privilege", machInst);
                             NPC = NPC;
                         } else {
@@ -1751,35 +1866,37 @@ decode QUADRANT default Unknown::unknown() {
                             xc->setMiscReg(MISCREG_STATUS, status);
                             NPC = xc->readMiscReg(MISCREG_MEPC);
                         }
-                    }}, IsReturn);
+                    }}, IsSerializeAfter, IsNonSpeculative, IsReturn);
                 }
             }
             format CSROp {
                 0x1: csrrw({{
                     Rd = data;
                     data = Rs1;
-                }}, IsNonSpeculative, No_OpClass);
+                }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
                 0x2: csrrs({{
                     Rd = data;
                     data |= Rs1;
-                }}, IsNonSpeculative, No_OpClass);
+                }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
                 0x3: csrrc({{
                     Rd = data;
                     data &= ~Rs1;
-                }}, IsNonSpeculative, No_OpClass);
+                }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
                 0x5: csrrwi({{
                     Rd = data;
                     data = uimm;
-                }}, IsNonSpeculative, No_OpClass);
+                }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
                 0x6: csrrsi({{
                     Rd = data;
                     data |= uimm;
-                }}, IsNonSpeculative, No_OpClass);
+                }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
                 0x7: csrrci({{
                     Rd = data;
                     data &= ~uimm;
-                }}, IsNonSpeculative, No_OpClass);
+                }}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
             }
         }
+
+        0x1e: M5Op::M5Op();
     }
 }