// 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.

// 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);
    Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};

// 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);
    Fault execute(ExecContext *, Trace::InstRecord *) const override;
    Fault doFpOp(ExecContext *, Trace::InstRecord *) const M5_NO_INLINE;
};
}};

// 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);
    Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};

// 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(ExecContext *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(ExecContext *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)
}};
