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

////////////////////////////////////////////////////////////////////
//
// Integer operate instructions
//

output header {{
    /**
     * Base class for integer immediate instructions.
     */
    class IntegerImm : public AlphaStaticInst
    {
      protected:
        /// Immediate operand value (unsigned 8-bit int).
        uint8_t imm;

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

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

output decoder {{
    std::string
    IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
    {
        std::stringstream ss;

        ccprintf(ss, "%-10s ", mnemonic);

        // just print the first source reg... if there's
        // a second one, it's a read-modify-write dest (Rc),
        // e.g. for CMOVxx
        if (_numSrcRegs > 0) {
            printReg(ss, _srcRegIdx[0]);
            ss << ",";
        }

        ss << (int)imm;

        if (_numDestRegs > 0) {
            ss << ",";
            printReg(ss, _destRegIdx[0]);
        }

        return ss.str();
    }
}};


def template RegOrImmDecode {{
 {
     AlphaStaticInst *i =
         (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
               : (AlphaStaticInst *)new %(class_name)s(machInst);
     if (RC == 31) {
         i = makeNop(i);
     }
     return i;
 }
}};

// Primary format for integer operate instructions:
// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
// - Generates NOP if RC == 31.
def format IntegerOperate(code, *opt_flags) {{
    # If the code block contains 'Rb_or_imm', we define two instructions,
    # one using 'Rb' and one using 'imm', and have the decoder select
    # the right one.
    uses_imm = (code.find('Rb_or_imm') != -1)
    if uses_imm:
        orig_code = code
        # base code is reg version:
        # rewrite by substituting 'Rb' for 'Rb_or_imm'
        code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
        # generate immediate version by substituting 'imm'
        # note that imm takes no extenstion, so we extend
        # the regexp to replace any extension as well
        imm_code = re.sub(r'Rb_or_imm(_\w+)?', 'imm', orig_code)

    # generate declaration for register version
    iop = InstObjParams(name, Name, 'AlphaStaticInst', code, opt_flags)
    header_output = BasicDeclare.subst(iop)
    decoder_output = BasicConstructor.subst(iop)
    exec_output = BasicExecute.subst(iop)

    if uses_imm:
        # append declaration for imm version
        imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_code,
                                opt_flags)
        header_output += BasicDeclare.subst(imm_iop)
        decoder_output += BasicConstructor.subst(imm_iop)
        exec_output += BasicExecute.subst(imm_iop)
        # decode checks IMM bit to pick correct version
        decode_block = RegOrImmDecode.subst(iop)
    else:
        # no imm version: just check for nop
        decode_block = OperateNopCheckDecode.subst(iop)
}};
