// -*- mode:c++ -*-

// Copyright (c) 2006-2007 The Regents of The University of Michigan
// 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.

////////////////////////////////////////////////////////////////////
//
// Mem instructions
//

def template MemDeclare {{
        /**
         * Static instruction class for "%(mnemonic)s".
         */
        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;
        };
}};

let {{
    def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''):
        addrCalcReg = 'EA = Rs1 + Rs2;'
        addrCalcImm = 'EA = Rs1 + imm;'
        iop = InstObjParams(name, Name, 'Mem',
                {"code": code, "postacc_code" : postacc_code,
                 "fault_check": faultCode, "ea_code": addrCalcReg,
                 "EA_trunc": TruncateEA}, opt_flags)
        iop_imm = InstObjParams(name, Name + "Imm", 'MemImm',
                {"code": code, "postacc_code" : postacc_code,
                 "fault_check": faultCode, "ea_code": addrCalcImm,
                 "EA_trunc": TruncateEA}, opt_flags)
        header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
        decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
        decode_block = ROrImmDecode.subst(iop)
        exec_output = doDualSplitExecute(code, postacc_code, addrCalcReg,
                addrCalcImm, execute, faultCode, name, name + "Imm",
                Name, Name + "Imm", asi, opt_flags)
        return (header_output, decoder_output, exec_output, decode_block)
}};

def format LoadAlt(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code, LoadFuncs,
            AlternateASIPrivFaultCheck, name, Name, "EXT_ASI", opt_flags)
}};

def format LoadfAlt(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code, LoadFuncs,
            AlternateASIPrivFaultCheck + fp_enabled, name, Name, "EXT_ASI",
            opt_flags)
}};

def format StoreAlt(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code, StoreFuncs,
            AlternateASIPrivFaultCheck, name, Name, "EXT_ASI", opt_flags)
}};

def format StorefAlt(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code, StoreFuncs,
            AlternateASIPrivFaultCheck + fp_enabled, name, Name, "EXT_ASI",
            opt_flags)
}};

def format Load(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code,
             LoadFuncs, '', name, Name, 0, opt_flags)
}};

def format Loadf(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code,
             LoadFuncs, fp_enabled, name, Name, 0, opt_flags)
}};

def format Store(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code,
             StoreFuncs, '', name, Name, 0, opt_flags)
}};

def format Storef(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code,
             StoreFuncs, fp_enabled, name, Name, 0, opt_flags)
}};

def format StoreFsr(code, *opt_flags) {{
        code = filterDoubles(code)
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code,
             StoreFuncs, '', name, Name, 0, opt_flags,
             'Fsr = insertBits(Fsr,16,14,0);')
}};

def format TwinLoad(code, *opt_flags) {{
        (header_output,
         decoder_output,
         exec_output,
         decode_block) = doMemFormat(code, LoadFuncs,
            AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck,
            name, Name, "EXT_ASI", opt_flags)
}};
