// 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.
//
// Authors: Ali Saidi
//          Gabe Black
//          Steve Reinhardt

// Declarations for execute() methods.
def template BasicExecDeclare {{
        Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};

def template DoFpOpDeclare {{
        Fault doFpOp(%(CPU_exec_context)s *, Trace::InstRecord *)
            const M5_NO_INLINE;
}};

// Definitions of execute methods that panic.
def template BasicExecPanic {{
        Fault
        execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
        {
            panic("Execute method called when it shouldn't!");
            M5_DUMMY_RETURN
        }
}};

// Basic instruction class declaration template.
def template BasicDeclare {{
        /**
         * Static instruction class for "%(mnemonic)s".
         */
        class %(class_name)s : public %(base_class)s
        {
          public:
            // Constructor.
            %(class_name)s(ExtMachInst machInst);
            %(BasicExecDeclare)s
        };
}};

// Basic instruction class declaration template.
def template FpBasicDeclare {{
        /**
         * Static instruction class for "%(mnemonic)s".
         */
        class %(class_name)s : public %(base_class)s
        {
          public:
            // Constructor.
            %(class_name)s(ExtMachInst machInst);
            %(BasicExecDeclare)s
            %(DoFpOpDeclare)s
        };
}};

// Basic instruction class declaration template.
def template BasicDeclareWithMnemonic {{
        /**
         * Static instruction class for "%(mnemonic)s".
         */
        class %(class_name)s : public %(base_class)s
        {
          public:
            // Constructor.
            %(class_name)s(const char * mnemonic, ExtMachInst machInst);
            %(BasicExecDeclare)s
        };
}};

// Basic instruction class constructor template.
def template BasicConstructor {{
        %(class_name)s::%(class_name)s(ExtMachInst machInst)
            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
        {
                %(constructor)s;
        }
}};

// Basic instruction class constructor template.
def template BasicConstructorWithMnemonic {{
        %(class_name)s::%(class_name)s(const char * mnemonic,
                ExtMachInst machInst)
            : %(base_class)s(mnemonic, machInst, %(op_class)s)
        {
                %(constructor)s;
        }
}};

// Basic instruction class execute method template.
def template BasicExecute {{
        Fault
        %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
                Trace::InstRecord *traceData) const
        {
            Fault fault = NoFault;

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

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

def template DoFpOpExecute {{
        Fault
        %(class_name)s::doFpOp(CPU_EXEC_CONTEXT *xc,
                Trace::InstRecord *traceData) const
        {
            Fault fault = NoFault;
            %(op_decl)s;
            %(op_rd)s;
            %(fp_code)s;
            if (fault == NoFault) {
                %(op_wb)s;
            }
            return fault;
        }
}};

// Basic decode template.
def template BasicDecode {{
        return new %(class_name)s(machInst);
}};

// Basic decode template, passing mnemonic in as string arg to constructor.
def template BasicDecodeWithMnemonic {{
    return new %(class_name)s("%(mnemonic)s", machInst);
}};

// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
        code = filterDoubles(code)
        iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags)
        header_output = BasicDeclare.subst(iop)
        decoder_output = BasicConstructor.subst(iop)
        decode_block = BasicDecode.subst(iop)
        exec_output = BasicExecute.subst(iop)
}};

def format FpBasic(code, *flags) {{
    exec_code = """
    Fsr |= bits(Fsr, 4, 0) << 5;
    Fsr = insertBits(Fsr, 4, 0, 0);
    int newrnd = M5_FE_TONEAREST;
    switch (Fsr<31:30>) {
      case 0: newrnd = M5_FE_TONEAREST; break;
      case 1: newrnd = M5_FE_TOWARDZERO; break;
      case 2: newrnd = M5_FE_UPWARD; break;
      case 3: newrnd = M5_FE_DOWNWARD; break;
    }
    int oldrnd = m5_fegetround();
    m5_fesetround(newrnd);
    __asm__ __volatile__("" ::: "memory");
    fault = doFpOp(xc, traceData);
    __asm__ __volatile__("" ::: "memory");
    m5_fesetround(oldrnd);
    return fault;
"""
    fp_code = filterDoubles(code)
    iop = InstObjParams(name, Name, 'SparcStaticInst',
            { "code" : exec_code, "fp_code" : fp_code }, flags)
    header_output = FpBasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    decode_block = BasicDecode.subst(iop)
    exec_output = BasicExecute.subst(iop)
    exec_output += DoFpOpExecute.subst(iop)
}};
