/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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.
 */

#ifndef __ARCH_X86_INSTS_MICROOP_HH__
#define __ARCH_X86_INSTS_MICROOP_HH__

#include "arch/x86/insts/static_inst.hh"
#include "base/compiler.hh"

namespace gem5
{

namespace X86ISA
{

GEM5_DEPRECATED_NAMESPACE(ConditionTests, condition_tests);
namespace condition_tests
{

enum CondTest
{
    True,
    NotFalse = True,
    ECF,
    EZF,
    SZnZF,
    MSTRZ,
    STRZ,
    MSTRC,
    STRZnEZF,
    OF,
    CF,
    ZF,
    CvZF,
    SF,
    PF,
    SxOF,
    SxOvZF,

    False,
    NotTrue = False,
    NotECF,
    NotEZF,
    NotSZnZF,
    NotMSTRZ,
    NotSTRZ,
    NotMSTRC,
    STRnZnEZF,
    NotOF,
    NotCF,
    NotZF,
    NotCvZF,
    NotSF,
    NotPF,
    NotSxOF,
    NotSxOvZF
};

}

//A class which is the base of all x86 micro ops. It provides a function to
//set necessary flags appropriately.
class X86MicroopBase : public X86StaticInst
{
  protected:
    const char * instMnem;
    uint8_t opSize;
    uint8_t addrSize;

    X86MicroopBase(ExtMachInst _machInst,
            const char *mnem, const char *_instMnem,
            uint64_t setFlags, OpClass __opClass) :
        X86ISA::X86StaticInst(mnem, _machInst, __opClass),
        instMnem(_instMnem)
    {
        const int ChunkSize = sizeof(unsigned long);
        const int Chunks = sizeof(setFlags) / ChunkSize;

        // Since the bitset constructor can only handle unsigned long
        // sized chunks, feed it those one at a time while oring them in.
        for (int i = 0; i < Chunks; i++) {
            unsigned shift = i * ChunkSize * 8;
            flags |= (std::bitset<Num_Flags>(setFlags >> shift) << shift);
        }
    }

    std::string
    generateDisassembly(Addr pc,
                       const loader::SymbolTable *symtab) const override
    {
        std::stringstream ss;

        ccprintf(ss, "\t%s.%s", instMnem, mnemonic);

        return ss.str();
    }

    bool checkCondition(uint64_t flags, int condition) const;

    void
    advancePC(PCState &pcState) const override
    {
        if (flags[IsLastMicroop])
            pcState.uEnd();
        else
            pcState.uAdvance();
    }

    PCState branchTarget(const PCState &branchPC) const override;

    // Explicitly import the otherwise hidden branchTarget.
    using StaticInst::branchTarget;
};

class MicroCondBase : public X86MicroopBase
{
  protected:
    uint8_t cc;

  public:
    MicroCondBase(ExtMachInst mach_inst, const char *mnem,
            const char *inst_mnem, uint64_t set_flags, OpClass op_class,
            uint8_t _cc) :
        X86MicroopBase(mach_inst, mnem, inst_mnem, set_flags, op_class),
        cc(_cc)
    {}
};

} // namespace X86ISA
} // namespace gem5

#endif //__ARCH_X86_INSTS_MICROOP_HH__
