// 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
{
  private:
    %(reg_idx_arr_decl)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
{
  private:
    %(reg_idx_arr_decl)s;

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

// Basic instruction class declaration template.
def template BasicDeclareWithMnemonic {{
/**
 * 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(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)
{
    %(set_reg_idx_arr)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)
{
    %(set_reg_idx_arr)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)
}};
