/*
 * Copyright (c) 2012 Google
 * 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.
 */

#ifndef __ARCH_X86_DECODER_HH__
#define __ARCH_X86_DECODER_HH__

#include <cassert>
#include <unordered_map>
#include <vector>

#include "arch/generic/decoder.hh"
#include "arch/x86/microcode_rom.hh"
#include "arch/x86/regs/misc.hh"
#include "arch/x86/types.hh"
#include "base/bitfield.hh"
#include "base/logging.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "cpu/decode_cache.hh"
#include "cpu/static_inst.hh"
#include "debug/Decoder.hh"
#include "params/X86Decoder.hh"

namespace gem5
{

namespace X86ISA
{

class ISA;
class Decoder : public InstDecoder
{
  private:
    // These are defined and documented in decoder_tables.cc
    static const uint8_t SizeTypeToSize[3][10];
    typedef const uint8_t ByteTable[256];
    static ByteTable Prefixes[2];

    static ByteTable UsesModRMOneByte;
    static ByteTable UsesModRMTwoByte;
    static ByteTable UsesModRMThreeByte0F38;
    static ByteTable UsesModRMThreeByte0F3A;

    static ByteTable ImmediateTypeOneByte;
    static ByteTable ImmediateTypeTwoByte;
    static ByteTable ImmediateTypeThreeByte0F38;
    static ByteTable ImmediateTypeThreeByte0F3A;

    static X86ISAInst::MicrocodeRom microcodeRom;

  protected:
    using MachInst = uint64_t;

    struct InstBytes
    {
        StaticInstPtr si;
        std::vector<MachInst> chunks;
        std::vector<MachInst> masks;
        int lastOffset;

        InstBytes() : lastOffset(0)
        {}
    };

    static InstBytes dummy;

    // The bytes to be predecoded.
    MachInst fetchChunk;
    InstBytes *instBytes = &dummy;
    int chunkIdx;
    // The pc of the start of fetchChunk.
    Addr basePC = 0;
    // The pc the current instruction started at.
    Addr origPC = 0;
    // The offset into fetchChunk of current processing.
    int offset = 0;
    // The extended machine instruction being generated.
    ExtMachInst emi;
    // Predecoding state.
    X86Mode mode = LongMode;
    X86SubMode submode = SixtyFourBitMode;
    uint8_t altOp = 0;
    uint8_t defOp = 0;
    uint8_t altAddr = 0;
    uint8_t defAddr = 0;
    uint8_t stack = 0;

    uint8_t cpl = 0;

    uint8_t
    getNextByte()
    {
        return ((uint8_t *)&fetchChunk)[offset];
    }

    void
    getImmediate(int &collected, uint64_t &current, int size)
    {
        // Figure out how many bytes we still need to get for the
        // immediate.
        int toGet = size - collected;
        // Figure out how many bytes are left in our "buffer".
        int remaining = sizeof(MachInst) - offset;
        // Get as much as we need, up to the amount available.
        toGet = toGet > remaining ? remaining : toGet;

        // Shift the bytes we want to be all the way to the right
        uint64_t partialImm = fetchChunk >> (offset * 8);
        // Mask off what we don't want.
        partialImm &= mask(toGet * 8);
        // Shift it over to overlay with our displacement.
        partialImm <<= (immediateCollected * 8);
        // Put it into our displacement.
        current |= partialImm;
        // Update how many bytes we've collected.
        collected += toGet;
        consumeBytes(toGet);
    }

    void
    updateOffsetState()
    {
        assert(offset <= sizeof(MachInst));
        if (offset == sizeof(MachInst)) {
            DPRINTF(Decoder, "At the end of a chunk, idx = %d, chunks = %d.\n",
                    chunkIdx, instBytes->chunks.size());
            chunkIdx++;
            if (chunkIdx == instBytes->chunks.size()) {
                outOfBytes = true;
            } else {
                offset = 0;
                fetchChunk = instBytes->chunks[chunkIdx];
                basePC += sizeof(MachInst);
            }
        }
    }

    void
    consumeByte()
    {
        offset++;
        updateOffsetState();
    }

    void
    consumeBytes(int numBytes)
    {
        offset += numBytes;
        updateOffsetState();
    }

    // State machine state.
  protected:
    // The size of the displacement value.
    int displacementSize;
    // The size of the immediate value.
    int immediateSize;
    // This is how much of any immediate value we've gotten. This is used
    // for both the actual immediate and the displacement.
    int immediateCollected;

    enum State
    {
        ResetState,
        FromCacheState,
        PrefixState,
        Vex2Of2State,
        Vex2Of3State,
        Vex3Of3State,
        VexOpcodeState,
        OneByteOpcodeState,
        TwoByteOpcodeState,
        ThreeByte0F38OpcodeState,
        ThreeByte0F3AOpcodeState,
        ModRMState,
        SIBState,
        DisplacementState,
        ImmediateState,
        // We should never get to this state. Getting here is an error.
        ErrorState
    };

    State state = ResetState;

    // Functions to handle each of the states
    State doResetState();
    State doFromCacheState();
    State doPrefixState(uint8_t);
    State doVex2Of2State(uint8_t);
    State doVex2Of3State(uint8_t);
    State doVex3Of3State(uint8_t);
    State doVexOpcodeState(uint8_t);
    State doOneByteOpcodeState(uint8_t);
    State doTwoByteOpcodeState(uint8_t);
    State doThreeByte0F38OpcodeState(uint8_t);
    State doThreeByte0F3AOpcodeState(uint8_t);
    State doModRMState(uint8_t);
    State doSIBState(uint8_t);
    State doDisplacementState();
    State doImmediateState();

    // Process the actual opcode found earlier, using the supplied tables.
    State processOpcode(ByteTable &immTable, ByteTable &modrmTable,
                        bool addrSizedImm = false);
    // Process the opcode found with VEX / XOP prefix.
    State processExtendedOpcode(ByteTable &immTable);

  protected:
    /// Caching for decoded instruction objects.

    typedef RegVal CacheKey;

    typedef decode_cache::AddrMap<Decoder::InstBytes> DecodePages;
    DecodePages *decodePages = nullptr;
    typedef std::unordered_map<CacheKey, DecodePages *> AddrCacheMap;
    AddrCacheMap addrCacheMap;

    decode_cache::InstMap<ExtMachInst> *instMap = nullptr;
    typedef std::unordered_map<
            CacheKey, decode_cache::InstMap<ExtMachInst> *> InstCacheMap;
    static InstCacheMap instCacheMap;

    StaticInstPtr decodeInst(ExtMachInst mach_inst);

    /// Decode a machine instruction.
    /// @param mach_inst The binary instruction to decode.
    /// @retval A pointer to the corresponding StaticInst object.
    StaticInstPtr decode(ExtMachInst mach_inst, Addr addr);

    void process();

  public:
    Decoder(const X86DecoderParams &p) : InstDecoder(p, &fetchChunk)
    {
        emi.reset();
        emi.mode.cpl = cpl;
        emi.mode.mode = mode;
        emi.mode.submode = submode;
    }

    void
    setM5Reg(HandyM5Reg m5Reg)
    {
        cpl = m5Reg.cpl;
        mode = (X86Mode)(uint64_t)m5Reg.mode;
        submode = (X86SubMode)(uint64_t)m5Reg.submode;
        emi.mode.cpl = cpl;
        emi.mode.mode = mode;
        emi.mode.submode = submode;
        altOp = m5Reg.altOp;
        defOp = m5Reg.defOp;
        altAddr = m5Reg.altAddr;
        defAddr = m5Reg.defAddr;
        stack = m5Reg.stack;

        AddrCacheMap::iterator amIter = addrCacheMap.find(m5Reg);
        if (amIter != addrCacheMap.end()) {
            decodePages = amIter->second;
        } else {
            decodePages = new DecodePages;
            addrCacheMap[m5Reg] = decodePages;
        }

        InstCacheMap::iterator imIter = instCacheMap.find(m5Reg);
        if (imIter != instCacheMap.end()) {
            instMap = imIter->second;
        } else {
            instMap = new decode_cache::InstMap<ExtMachInst>;
            instCacheMap[m5Reg] = instMap;
        }
    }

    void
    takeOverFrom(InstDecoder *old) override
    {
        InstDecoder::takeOverFrom(old);

        Decoder *dec = dynamic_cast<Decoder *>(old);
        assert(dec);

        cpl = dec->cpl;
        mode = dec->mode;
        submode = dec->submode;
        emi.mode.cpl = cpl;
        emi.mode.mode = mode;
        emi.mode.submode = submode;
        altOp = dec->altOp;
        defOp = dec->defOp;
        altAddr = dec->altAddr;
        defAddr = dec->defAddr;
        stack = dec->stack;
    }

    void
    reset() override
    {
        InstDecoder::reset();
        state = ResetState;
    }

    // Use this to give data to the decoder. This should be used
    // when there is control flow.
    void
    moreBytes(const PCStateBase &pc, Addr fetchPC) override
    {
        DPRINTF(Decoder, "Getting more bytes.\n");
        basePC = fetchPC;
        offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
        fetchChunk = letoh(fetchChunk);
        outOfBytes = false;
        process();
    }

    void
    updateNPC(X86ISA::PCState &nextPC)
    {
        if (!nextPC.size()) {
            int size = basePC + offset - origPC;
            DPRINTF(Decoder,
                    "Calculating the instruction size: "
                    "basePC: %#x offset: %#x origPC: %#x size: %d\n",
                    basePC, offset, origPC, size);
            nextPC.size(size);
            nextPC.npc(nextPC.pc() + size);
        }
    }

  public:
    StaticInstPtr decode(PCStateBase &next_pc) override;

    StaticInstPtr fetchRomMicroop(
            MicroPC micropc, StaticInstPtr curMacroop) override;
};

} // namespace X86ISA
} // namespace gem5

#endif // __ARCH_X86_DECODER_HH__
