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

// Copyright (c) 2003-2005 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.
//
// Authors: Steve Reinhardt
//          Kevin Lim

////////////////////////////////////////////////////////////////////
//
// Memory-format instructions: LoadAddress, Load, Store
//

output header {{
    /**
     * Base class for general Alpha memory-format instructions.
     */
    class Memory : public AlphaStaticInst
    {
      protected:

        /// Memory request flags.  See mem_req_base.hh.
        Request::Flags memAccessFlags;

        /// Constructor
        Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
            : AlphaStaticInst(mnem, _machInst, __opClass)
        {
        }

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

    /**
     * Base class for memory-format instructions using a 32-bit
     * displacement (i.e. most of them).
     */
    class MemoryDisp32 : public Memory
    {
      protected:
        /// Displacement for EA calculation (signed).
        int32_t disp;

        /// Constructor.
        MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
            : Memory(mnem, _machInst, __opClass),
              disp(MEMDISP)
        {
        }
    };


    /**
     * Base class for a few miscellaneous memory-format insts
     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
     * None of these instructions has a destination register either.
     */
    class MemoryNoDisp : public Memory
    {
      protected:
        /// Constructor
        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
            : Memory(mnem, _machInst, __opClass)
        {
        }

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


output decoder {{
    std::string
    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
    {
        return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
                        flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
    }

    std::string
    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
    {
        return csprintf("%-10s (r%d)", mnemonic, RB);
    }
}};

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


def template LoadStoreDeclare {{
    /**
     * Static instruction class for "%(mnemonic)s".
     */
    class %(class_name)s : public %(base_class)s
    {
      public:

        /// Constructor.
        %(class_name)s(ExtMachInst machInst);

        %(BasicExecDeclare)s

        %(EACompDeclare)s

        %(InitiateAccDeclare)s

        %(CompleteAccDeclare)s
    };
}};


def template EACompDeclare {{
    Fault eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};

def template InitiateAccDeclare {{
    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};


def template CompleteAccDeclare {{
    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *,
                      Trace::InstRecord *) const;
}};

def template LoadStoreConstructor {{
    %(class_name)s::%(class_name)s(ExtMachInst machInst)
         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
    {
        %(constructor)s;
    }
}};

def template EACompExecute {{
    Fault %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
                                  Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            %(op_wb)s;
            xc->setEA(EA);
        }

        return fault;
    }
}};


def template LoadExecute {{
    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
                                  Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};


def template LoadInitiateAcc {{
    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_src_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
        }

        return fault;
    }
}};


def template LoadCompleteAcc {{
    Fault %(class_name)s::completeAcc(PacketPtr pkt,
                                      CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_decl)s;

        getMem(pkt, Mem, traceData);

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};


def template StoreExecute {{
    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
                                  Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            fault = writeMemAtomic(xc, traceData, Mem, EA,
                    memAccessFlags, NULL);
        }

        if (fault == NoFault) {
            %(postacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

def template StoreCondExecute {{
    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
                                  Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;
        uint64_t write_result = 0;

        %(fp_enable_check)s;
        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            fault = writeMemAtomic(xc, traceData, Mem, EA,
                    memAccessFlags, &write_result);
        }

        if (fault == NoFault) {
            %(postacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};

def template StoreInitiateAcc {{
    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        Addr EA;
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        if (fault == NoFault) {
            %(memacc_code)s;
        }

        if (fault == NoFault) {
            fault = writeMemTiming(xc, traceData, Mem, EA,
                    memAccessFlags, NULL);
        }

        return fault;
    }
}};


def template StoreCompleteAcc {{
    Fault %(class_name)s::completeAcc(PacketPtr pkt,
                                      CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        return NoFault;
    }
}};


def template StoreCondCompleteAcc {{
    Fault %(class_name)s::completeAcc(PacketPtr pkt,
                                      CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_dest_decl)s;

        uint64_t write_result = pkt->req->getExtraData();

        if (fault == NoFault) {
            %(postacc_code)s;
        }

        if (fault == NoFault) {
            %(op_wb)s;
        }

        return fault;
    }
}};


def template MiscExecute {{
    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
                                  Trace::InstRecord *traceData) const
    {
        Addr EA M5_VAR_USED;
        Fault fault = NoFault;

        %(fp_enable_check)s;
        %(op_decl)s;
        %(op_rd)s;
        %(ea_code)s;

        warn_once("Prefetch instructions in Alpha do not do anything\n");
        if (fault == NoFault) {
            %(memacc_code)s;
        }

        return NoFault;
    }
}};

// Prefetches in Alpha don't actually do anything
// They just build an effective address and complete
def template MiscInitiateAcc {{
    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        warn("initiateAcc undefined: Misc instruction does not support split "
             "access method!");
        return NoFault;
    }
}};


def template MiscCompleteAcc {{
    Fault %(class_name)s::completeAcc(PacketPtr pkt,
                                      CPU_EXEC_CONTEXT *xc,
                                      Trace::InstRecord *traceData) const
    {
        warn("completeAcc undefined: Misc instruction does not support split "
             "access method!");

        return NoFault;
    }
}};


// load instructions use Ra as dest, so check for
// Ra == 31 to detect nops
def template LoadNopCheckDecode {{
 {
     AlphaStaticInst *i = new %(class_name)s(machInst);
     if (RA == 31) {
         i = makeNop(i);
     }
     return i;
 }
}};


// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
def template LoadPrefetchCheckDecode {{
 {
     if (RA != 31) {
         return new %(class_name)s(machInst);
     }
     else {
         return new %(class_name)sPrefetch(machInst);
     }
 }
}};


let {{
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                  postacc_code = '', base_class = 'MemoryDisp32',
                  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)

    iop = InstObjParams(name, Name, base_class,
                        { '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 ]
        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
        iop.constructor += s

    # select templates

    # The InitiateAcc template is the same for StoreCond templates as the
    # corresponding Store template..
    StoreCondInitiateAcc = StoreInitiateAcc

    fullExecTemplate = eval(exec_template_base + 'Execute')
    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')

    # (header_output, decoder_output, decode_block, exec_output)
    return (LoadStoreDeclare.subst(iop),
            LoadStoreConstructor.subst(iop),
            decode_template.subst(iop),
            fullExecTemplate.subst(iop)
            + EACompExecute.subst(iop)
            + initiateAccTemplate.subst(iop)
            + completeAccTemplate.subst(iop))
}};

def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
                     mem_flags = [], inst_flags = []) {{
    (header_output, decoder_output, decode_block, exec_output) = \
        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                      decode_template = LoadNopCheckDecode,
                      exec_template_base = 'Load')
}};


// Note that the flags passed in apply only to the prefetch version
def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
                          mem_flags = [], pf_flags = [], inst_flags = []) {{
    # declare the load instruction object and generate the decode block
    (header_output, decoder_output, decode_block, exec_output) = \
        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                      decode_template = LoadPrefetchCheckDecode,
                      exec_template_base = 'Load')

    # Declare the prefetch instruction object.

    # Make sure flag args are lists so we can mess with them.
    mem_flags = makeList(mem_flags)
    pf_flags = makeList(pf_flags)
    inst_flags = makeList(inst_flags)

    pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
    pf_inst_flags = inst_flags

    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
        LoadStoreBase(name, Name + 'Prefetch', ea_code, ';',
                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')

    header_output += pf_header_output
    decoder_output += pf_decoder_output
    exec_output += pf_exec_output
}};


def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
                 mem_flags = [], inst_flags = []) {{
    (header_output, decoder_output, decode_block, exec_output) = \
        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                      exec_template_base = 'Store')
}};


def format StoreCond(memacc_code, postacc_code,
                     ea_code = {{ EA = Rb + disp; }},
                     mem_flags = [], inst_flags = []) {{
    (header_output, decoder_output, decode_block, exec_output) = \
        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                      postacc_code, exec_template_base = 'StoreCond')
}};


// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
def format MiscPrefetch(ea_code, memacc_code,
                        mem_flags = [], inst_flags = []) {{
    (header_output, decoder_output, decode_block, exec_output) = \
        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
}};


