// Copyright (c) AMD
// All rights reserved.

// Monitor Instruction

output header {{
    class MonitorInst : public X86ISA::X86StaticInst
    {
      public:
        static const RegIndex foldOBit = 0;
        /// Constructor
        MonitorInst(const char *_mnemonic, ExtMachInst _machInst,
                OpClass __opClass) :
            X86ISA::X86StaticInst(_mnemonic, _machInst, __opClass)
        { }

        std::string generateDisassembly(Addr pc,
                const loader::SymbolTable *symtab) const override;
    };
}};

output decoder {{
    std::string
    MonitorInst::generateDisassembly(
            Addr PC, const loader::SymbolTable *symtab) const
    {
        std::stringstream response;

        printMnemonic(response, mnemonic);
        return response.str();
    }
}};

def format MonitorInst(code, *opt_flags) {{
    iop = InstObjParams(name, Name, 'MonitorInst', code, opt_flags)
    header_output = BasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    decode_block = BasicDecode.subst(iop)
    exec_output = BasicExecute.subst(iop)
}};


// Mwait instruction

def template MwaitDeclare {{
    class %(class_name)s : public %(base_class)s
    {
      private:
        %(reg_idx_arr_decl)s;

      public:
        // Constructor.
        %(class_name)s(ExtMachInst machInst);
        Fault execute(ExecContext *, Trace::InstRecord *) const override;
        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
        Fault completeAcc(PacketPtr, ExecContext *,
                          Trace::InstRecord *) const override;
    };
}};

def template MwaitInitiateAcc {{
    Fault %(class_name)s::initiateAcc(ExecContext * xc,
            Trace::InstRecord * traceData) const
    {
        unsigned s = 0x8;        //size
        unsigned f = 0;          //flags
        initiateMemRead(xc, traceData, xc->getAddrMonitor()->vAddr, s, f);
        return NoFault;
    }
}};

def template MwaitCompleteAcc {{
    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
            Trace::InstRecord *traceData) const
    {
        MicroHalt hltObj(machInst, mnemonic, 0x0);
        if(xc->mwait(pkt)) {
            hltObj.execute(xc, traceData);
        }
        return NoFault;
    }
}};

output header {{
    class MwaitInst : public X86ISA::X86StaticInst
    {
      public:
        static const RegIndex foldOBit = 0;
        /// Constructor
        MwaitInst(const char *_mnemonic, ExtMachInst _machInst,
                OpClass __opClass) :
            X86ISA::X86StaticInst(_mnemonic, _machInst, __opClass)
        {
            flags[IsLoad] = 1;
        }

        std::string generateDisassembly(Addr pc,
                const loader::SymbolTable *symtab) const override;
    };
}};

output decoder {{
    std::string
    MwaitInst::generateDisassembly(
            Addr PC, const loader::SymbolTable *symtab) const
    {
        std::stringstream response;

        // Although mwait could take hints from eax and ecx, the srcRegIdx
        // is not set, and thus should not be printed here
        printMnemonic(response, mnemonic);
        return response.str();
    }
}};

def format MwaitInst(code, *opt_flags) {{
    iop = InstObjParams(name, Name, 'MwaitInst', code, opt_flags)
    header_output = MwaitDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    decode_block = BasicDecode.subst(iop)
    exec_output = BasicExecute.subst(iop)
    exec_output += MwaitInitiateAcc.subst(iop)
    exec_output += MwaitCompleteAcc.subst(iop)
}};

