/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Alexander V. Astapchuk
 */
 
/**
 * @file
 * @brief Main encoding routines and structures.
 */
 
#ifndef __ENC_BASE_H_INCLUDED__
#define __ENC_BASE_H_INCLUDED__

#include "enc_defs.h"


#include <stdlib.h>
#include <assert.h>
#include <memory.h>

ENCODER_NAMESPACE_START
struct MnemonicInfo;
struct OpcodeInfo;
struct Rex;

/**
 * @brief Basic facilities for generation of processor's instructions.
 *
 * The class EncoderBase represents the basic facilities for the encoding of 
 * processor's instructions on IA32 and EM64T platforms.
 * 
 * The class provides general interface to generate the instructions as well
 * as to retrieve some static data about instructions (number of arguments, 
 * their roles, etc).
 * 
 * Currently, the EncoderBase class is used for both LIL and Jitrino code
 * generators. Each of these code generators has its own wrapper to adapt
 * this general interface for specific needs - see encoder.h for LIL wrappers
 * and Ia32Encoder.h for Jitrino's adapter.
 *
 * Interface is provided through static methods, no instances of EncoderBase
 * to be created.
 * 
 * @todo RIP-based addressing on EM64T - it's not yet supported currently.
 */
class EncoderBase {
public:
    class Operands;
    struct MnemonicDesc;
    /**
     * @brief Generates processor's instruction.
     *
     * @param stream - a buffer to generate into
     * @param mn - \link Mnemonic mnemonic \endlink of the instruction
     * @param opnds - operands for the instruction
     * @returns (stream + length of the just generated instruction)
     */
    static char * encode(char * stream, Mnemonic mn, const Operands& opnds);
    
    /**
     * @brief Generates the smallest possible number of NOP-s.
     *
     * Effectively generates the smallest possible number of instructions, 
     * which are NOP-s for CPU. Normally used to make a code alignment.
     * 
     * The method inserts exactly number of bytes specified. It's a caller's
     * responsibility to make sure the buffer is big enough.
     * 
     * @param stream - buffer where to generate code into, can not be NULL
     * @param howMany - how many bytes to fill with NOP-s
     * @return \c (stream+howMany)
     */
    static char * nops(char * stream, unsigned howMany);

    /**
     * @brief Inserts a prefix into the code buffer.
     *
     * The method writes no more than one byte into the buffer. This is a 
     * caller's responsibility to make sure the buffer is big enough.
     * 
     * @param stream - buffer where to insert the prefix
     * @param pref - prefix to be inserted. If it's InstPrefix_Null, then 
     *        no action performed and return value is \c stream.
     * @return \c (stream+1) if pref is not InstPrefix_Null, or \c stream 
     *         otherwise
     */
     static char * prefix(char* stream, InstPrefix pref);

    /**
     * @brief Returns #MnemonicDesc by the given Mnemonic.
     */
    static const MnemonicDesc * getMnemonicDesc(Mnemonic mn)
    {
        assert(mn < Mnemonic_Count);
        return mnemonics + mn;
    }
    
    /**
     * @brief Returns a Mnemonic for the given name.
     * 
     * The lookup is case insensitive, if no mnemonic found for the given 
     * string, then Mnemonic_Null returned.
     */
    static Mnemonic str2mnemonic(const char * mn_name);
    
    /**
     * @brief Returns a string representation of the given Mnemonic.
     *
     * If invalid mnemonic passed, then the behavior is unpredictable.
     */
    static const char * getMnemonicString(Mnemonic mn)
    {
        return getMnemonicDesc(mn)->name;
    }
    
    static const char * toStr(Mnemonic mn)
    {
        return getMnemonicDesc(mn)->name;
    }


    /**
     * @brief Description of operand.
     *
     * Description of an operand in opcode - its kind, size or RegName if 
     * operand must be a particular register.
     */
    struct OpndDesc {
        /**
         * @brief Location of the operand.
         * 
         * May be a mask, i.e. OpndKind_Imm|OpndKind_Mem.
         */
        OpndKind        kind;
        /**
         * @brief Size of the operand.
         */
        OpndSize        size;
        /**
         * @brief Appropriate RegName if operand must reside on a particular
         *        register (i.e. CWD/CDQ instructions), RegName_Null 
         *        otherwise.
         */
        RegName         reg;
    };

    /**
     * @brief Description of operands' roles in instruction.
     */
    struct OpndRolesDesc {
        /**
         * @brief Total number of operands in the operation.
         */
        unsigned                count;
        /**
         * @brief Number of defs in the operation.
         */
        unsigned                defCount;
        /**
         * @brief Number of uses in the operation.
         */
        unsigned                useCount;
        /**
         * @brief Operand roles, bit-packed.
         * 
         * A bit-packed info about operands' roles. Each operand's role is 
         * described by two bits, counted from right-to-left - the less 
         * significant bits (0,1) represent operand#0. 
         * 
         * The mask is build by ORing #OpndRole_Def and #OpndRole_Use 
         * appropriately and shifting left, i.e. operand#0's role would be 
         * - '(OpndRole_Def|OpndRole_Use)'
         * - opnd#1's role would be 'OpndRole_Use<<2' 
         * - and operand#2's role would be, say, 'OpndRole_Def<<4'.
         */
        unsigned                roles;
    };

    /**
     * @brief Extracts appropriate OpndRole for a given operand.
     * 
     * The order of operands is left-to-right, i.e. for MOV, it 
     * would be 'MOV op0, op1'
     */
    static OpndRole getOpndRoles(OpndRolesDesc ord, unsigned idx)
    {
        assert(idx < ord.count);
        return (OpndRole)(ord.roles>>((ord.count-1-idx)*2) & 0x3);
    }

    /**
     * @brief Info about single opcode - its opcode bytes, operands, 
     *        operands' roles.
     */
   union OpcodeDesc {
       char dummy[128]; // To make total size a power of 2

       struct {
           /**
           * @brief Raw opcode bytes.
           *
           * 'Raw' opcode bytes which do not require any analysis and are
           * independent from arguments/sizes/etc (may include opcode size
           * prefix).
           */
           char        opcode[5];
           unsigned    opcode_len;
           unsigned    aux0;
           unsigned    aux1;
           /**
           * @brief Info about opcode's operands.
           * 
           * The [3] mostly comes from IDIV/IMUL which both may have up to 3
           * operands.
           */
           OpndDesc        opnds[3];
           unsigned        first_opnd;
           /**
           * @brief Info about operands - total number, number of uses/defs,
           *        operands' roles.
           */
           OpndRolesDesc   roles;
           /**
           * @brief If not zero, then this is final OpcodeDesc structure in
           *        the list of opcodes for a given mnemonic.
           */
           char            last;
           char            platf;
       };
   };
public:
    /**
     * @brief General info about mnemonic.
     */
    struct MnemonicDesc {
        /**
        * @brief The mnemonic itself.
        */ 
        Mnemonic        mn;
        /**
        * Various characteristics of mnemonic.
        * @see MF_
         */
        unsigned    flags;
        /**
         * @brief Operation's operand's count and roles.
         *
         * For the operations whose opcodes may use different number of 
         * operands (i.e. IMUL/SHL) either most common value used, or empty 
         * value left.
         */
        OpndRolesDesc   roles;
        /**
         * @brief Print name of the mnemonic.
         */
        const char *    name;
    };


    /**
     * @brief Magic number, shows a maximum value a hash code can take.
     * 
     * For meaning and arithmetics see enc_tabl.cpp.
     *
     * The value was increased from '5155' to '8192' to make it aligned
     * for faster access in EncoderBase::lookup().
     */
    static const unsigned int               HASH_MAX = 8192; //5155;
    /**
     * @brief Empty value, used in hash-to-opcode map to show an empty slot.
     */
    static const unsigned char              NOHASH = 0xFF;
    /**
     * @brief The name says it all.
     */
    static const unsigned char              HASH_BITS_PER_OPERAND = 5;

    /**
     * @brief Contains info about a single instructions's operand - its 
     *        location, size and a value for immediate or RegName for 
     *        register operands.
     */
    class Operand {
    public:
        /**
         * @brief Initializes the instance with empty size and kind.
         */
        Operand() : m_kind(OpndKind_Null), m_size(OpndSize_Null), m_need_rex(false) {}
        /**
         * @brief Creates register operand from given RegName.
         */
        Operand(RegName reg) : m_kind(getRegKind(reg)), 
                               m_size(getRegSize(reg)), m_reg(reg) 
        {
            hash_it();
        }
        /**
         * @brief Creates register operand from given RegName and with the
         *        specified size and kind.
         *
         * Used to speedup Operand creation as there is no need to extract
         * size and kind from the RegName. 
         * The provided size and kind must match the RegName's ones though.
         */
        Operand(OpndSize sz, OpndKind kind, RegName reg) : m_kind(kind), 
                                                           m_size(sz), 
                                                           m_reg(reg) 
        {
            assert(m_size == getRegSize(reg));
            assert(m_kind == getRegKind(reg));
            hash_it();
        }
        /**
         * @brief Creates immediate operand with the given size and value.
         */
        Operand(OpndSize size, long long ival) : m_kind(OpndKind_Imm), 
                                                 m_size(size), m_imm64(ival)
        {
            hash_it();
        }
        /**
         * @brief Creates immediate operand of OpndSize_32.
         */
        Operand(int ival) : m_kind(OpndKind_Imm), m_size(OpndSize_32), 
                            m_imm64(ival)
        {
            hash_it();
        }
        /**
         * @brief Creates immediate operand of OpndSize_16.
         */
        Operand(short ival) : m_kind(OpndKind_Imm), m_size(OpndSize_16), 
                              m_imm64(ival)
        {
            hash_it();
        }

        /**
         * @brief Creates immediate operand of OpndSize_8.
         */
        Operand(char ival) : m_kind(OpndKind_Imm), m_size(OpndSize_8), 
                             m_imm64(ival)
        {
            hash_it();
        }

        /**
         * @brief Creates memory operand.
         */
        Operand(OpndSize size, RegName base, RegName index, unsigned scale,
                int disp) : m_kind(OpndKind_Mem), m_size(size)
        {
            m_base = base;
            m_index = index;
            m_scale = scale;
            m_disp = disp;
            hash_it();
        }
                
        /**
         * @brief Creates memory operand with only base and displacement.
         */
        Operand(OpndSize size, RegName base, int disp) : 
                               m_kind(OpndKind_Mem), m_size(size)
        {
            m_base = base;
            m_index = RegName_Null;
            m_scale = 0;
            m_disp = disp;
            hash_it();
        }
        //
        // general info
        //
        /**
         * @brief Returns kind of the operand.
         */
        OpndKind kind(void) const { return m_kind; }
        /**
         * @brief Returns size of the operand.
         */
        OpndSize size(void) const { return m_size; }
        /**
         * @brief Returns hash of the operand.
         */
        unsigned hash(void) const { return m_hash; }
        //
#ifdef _EM64T_
        bool need_rex(void) const { return m_need_rex; }
#else
        bool need_rex(void) const { return false; }
#endif
        /**
         * @brief Tests whether operand is memory operand.
         */
        bool is_mem(void) const { return is_placed_in(OpndKind_Mem); }
        /**
         * @brief Tests whether operand is immediate operand.
         */
        bool is_imm(void) const { return is_placed_in(OpndKind_Imm); }
        /**
         * @brief Tests whether operand is register operand.
         */
        bool is_reg(void) const { return is_placed_in(OpndKind_Reg); }
        /**
         * @brief Tests whether operand is general-purpose register operand.
         */
        bool is_gpreg(void) const { return is_placed_in(OpndKind_GPReg); }
        /**
         * @brief Tests whether operand is float-point pseudo-register operand.
         */
        bool is_fpreg(void) const { return is_placed_in(OpndKind_FPReg); }
        /**
         * @brief Tests whether operand is XMM register operand.
         */
        bool is_xmmreg(void) const { return is_placed_in(OpndKind_XMMReg); }
#ifdef _HAVE_MMX_
        /**
         * @brief Tests whether operand is MMX register operand.
         */
        bool is_mmxreg(void) const { return is_placed_in(OpndKind_MMXReg); }
#endif
        /**
         * @brief Returns base of memory operand (RegName_Null if not memory).
         */
        RegName base(void) const { return is_mem() ? m_base : RegName_Null; }
        /**
         * @brief Returns index of memory operand (RegName_Null if not memory).
         */
        RegName index(void) const { return is_mem() ? m_index : RegName_Null; }
        /**
         * @brief Returns scale of memory operand (0 if not memory).
         */
        unsigned scale(void) const { return is_mem() ? m_scale : 0; }
        /**
         * @brief Returns displacement of memory operand (0 if not memory).
         */
        int disp(void) const { return is_mem() ? m_disp : 0; }
        /**
         * @brief Returns RegName of register operand (RegName_Null if not 
         *        register).
         */
        RegName reg(void) const { return is_reg() ? m_reg : RegName_Null; }
        /**
         * @brief Returns value of immediate operand (0 if not immediate).
         */
        long long imm(void) const { return is_imm() ? m_imm64 : 0; }
    private:
        bool is_placed_in(OpndKind kd) const
        {
                return kd == OpndKind_Reg ?
                        m_kind == OpndKind_GPReg || 
#ifdef _HAVE_MMX_
                        m_kind == OpndKind_MMXReg ||
#endif
                        m_kind == OpndKind_FPReg || 
                        m_kind == OpndKind_XMMReg 
                        : kd == m_kind; 
        }
        void hash_it(void)
        {
            m_hash = size_hash[m_size] | kind_hash[m_kind];
#ifdef _EM64T_
            m_need_rex = false;
            if (is_reg() && is_em64t_extra_reg(m_reg)) {
                m_need_rex = true;
            }
            else if (is_mem() && (is_em64t_extra_reg(m_base) || 
                                  is_em64t_extra_reg(m_index))) {
                m_need_rex = true;
            }
#endif
        }
        // general info
        OpndKind    m_kind;
        OpndSize    m_size;
        // complex address form support
        RegName     m_base;
        RegName     m_index;
        unsigned    m_scale;
        union {
            int         m_disp;
            RegName     m_reg;
            long long   m_imm64;
        };
        unsigned    m_hash;
        bool        m_need_rex;
        friend class EncoderBase::Operands;
    };
    /**
     * @brief Simple container for up to 3 Operand-s.
     */
    class Operands {
    public:
        Operands(void) 
        {
            clear();
        }
        Operands(const Operand& op0) 
        {
            clear();
            add(op0);
        }
    
        Operands(const Operand& op0, const Operand& op1)
        {
            clear();
            add(op0); add(op1);
        }
            
        Operands(const Operand& op0, const Operand& op1, const Operand& op2)
        {
            clear();
            add(op0); add(op1); add(op2);
        }

        unsigned count(void) const { return m_count; }
        unsigned hash(void) const { return m_hash; }
        const Operand& operator[](unsigned idx) const
        {
            assert(idx<m_count);
            return m_operands[idx];
        }

        void add(const Operand& op)
        {
            assert(m_count < COUNTOF(m_operands));
            m_hash = (m_hash<<HASH_BITS_PER_OPERAND) | op.hash();
            m_operands[m_count++] = op;
            m_need_rex = m_need_rex || op.m_need_rex;
        }
#ifdef _EM64T_
        bool need_rex(void) const { return m_need_rex; }
#else
        bool need_rex(void) const { return false; }
#endif
        void clear(void)
        {
            m_count = 0; m_hash = 0; m_need_rex = false;
        }
    private:
        unsigned    m_count;
        Operand     m_operands[COUNTOF( ((OpcodeDesc*)NULL)->opnds )];
        unsigned    m_hash;
        bool        m_need_rex;
    };
public:
#ifdef _DEBUG
    /**
     * Verifies some presumptions about encoding data table. 
     * Called automagicaly during statics initialization.
     */
    static int verify(void);
#endif

private:
    /**
     * @brief Returns found OpcodeDesc by the given Mnemonic and operands.
     */
    static const OpcodeDesc * lookup(Mnemonic mn, const Operands& opnds);
    /**
     * @brief Encodes mod/rm byte.
     */
    static char* encodeModRM(char* stream, const Operands& opnds,
                             unsigned idx, const OpcodeDesc * odesc, Rex * prex);
    /**
     * @brief Encodes special things of opcode description - '/r', 'ib', etc.
     */
    static char* encode_aux(char* stream, unsigned aux, 
                            const Operands& opnds, const OpcodeDesc * odesc,
                            unsigned * pargsCount, Rex* prex);
#ifdef _EM64T_
    /**
     * @brief Returns true if the 'reg' argument represents one of the new 
     *        EM64T registers - R8(D)-R15(D).
     * 
     * The 64 bits versions of 'old-fashion' registers, i.e. RAX are not 
     * considered as 'extra'.
     */
    static bool is_em64t_extra_reg(const RegName reg)
    {
        if (needs_rex_r(reg)) {
            return true;
        }
        if (RegName_SPL <= reg && reg <= RegName_R15L) {
            return true;
        }
        return false;
    }
    static bool needs_rex_r(const RegName reg)
    {
        if (RegName_R8 <= reg && reg <= RegName_R15) {
            return true;
        }
        if (RegName_R8D <= reg && reg <= RegName_R15D) {
            return true;
        }
        if (RegName_R8S <= reg && reg <= RegName_R15S) {
            return true;
        }
        if (RegName_R8L <= reg && reg <= RegName_R15L) {
            return true;
        }
        if (RegName_XMM8 <= reg && reg <= RegName_XMM15) {
            return true;
        }
        if (RegName_XMM8D <= reg && reg <= RegName_XMM15D) {
            return true;
        }
        if (RegName_XMM8S <= reg && reg <= RegName_XMM15S) {
            return true;
        }
        return false;
    }
    /**
     * @brief Returns an 'processor's index' of the register - the index 
     *        used to encode the register in ModRM/SIB bytes.
     * 
     * For the new EM64T registers the 'HW index' differs from the index 
     * encoded in RegName. For old-fashion registers it's effectively the 
     * same as ::getRegIndex(RegName).
     */
    static unsigned char getHWRegIndex(const RegName reg) 
    {
        if (getRegKind(reg) != OpndKind_GPReg) {
            return getRegIndex(reg);
        }
        if (RegName_SPL <= reg && reg<=RegName_DIL) {
            return getRegIndex(reg);
        }
        if (RegName_R8L<= reg && reg<=RegName_R15L) {
            return getRegIndex(reg) - getRegIndex(RegName_R8L);
        }
        return is_em64t_extra_reg(reg) ? 
                getRegIndex(reg)-getRegIndex(RegName_R8D) : getRegIndex(reg);
    }
#else
    static unsigned char getHWRegIndex(const RegName reg)
    {
        return getRegIndex(reg);
    }
    static bool is_em64t_extra_reg(const RegName reg)
    {
        return false;
    }
#endif
public:
    /**
     * @brief A table used for the fast computation of hash value.
     *
     * A change must be strictly balanced with hash-related functions and data 
     * in enc_base.h/.cpp.
     */ 
    static const unsigned char size_hash[OpndSize_64+1];
    /**
     * @brief A table used for the fast computation of hash value.
     *
     * A change must be strictly balanced with hash-related functions and data 
     * in enc_base.h/.cpp.
     */ 
    static const unsigned char kind_hash[OpndKind_Mem+1];
    /**
     * @brief Maximum number of opcodes used for a single mnemonic.
     * 
     * No arithmetics behind the number, simply estimated.
     */
    static const unsigned int   MAX_OPCODES = 32; //20;
    /**
     * @brief Mapping between operands hash code and operands.
     */
    static unsigned char    opcodesHashMap[Mnemonic_Count][HASH_MAX];
    /**
     * @brief Array of mnemonics.
     */
    static MnemonicDesc         mnemonics[Mnemonic_Count];
    /**
     * @brief Array of available opcodes.
     */
    static OpcodeDesc opcodes[Mnemonic_Count][MAX_OPCODES];

    static int buildTable(void);
    static void buildMnemonicDesc(const MnemonicInfo * minfo);
    /**
     * @brief Computes hash value for the given operands.
     */
    static unsigned short getHash(const OpcodeInfo* odesc);
    /**
     * @brief Dummy variable, for automatic invocation of buildTable() at
     *        startup.
     */
    static int dummy;
};

ENCODER_NAMESPACE_END

#endif // ifndef __ENC_BASE_H_INCLUDED__
