#include "Assembly.h"

#include "InMemoryBuffer.h"

enum OperandSizeOverwrite
{
    NO_PREFIX = 0,
    X66 = 0x66,
    XF2 = 0xF2,
    XF3 = 0xF3
};

bool isVolatile(Framework::Assembly::GPRegister reg)
{
    return reg == Framework::Assembly::RAX || reg == Framework::Assembly::RCX
        || reg == Framework::Assembly::RDX || reg == Framework::Assembly::R8
        || reg == Framework::Assembly::R9 || reg == Framework::Assembly::R10
        || reg == Framework::Assembly::R11;
}

bool isVolatile(Framework::Assembly::FPRegister reg)
{
    return reg == Framework::Assembly::MM0 || reg == Framework::Assembly::MM1
        || reg == Framework::Assembly::MM2 || reg == Framework::Assembly::MM3
        || reg == Framework::Assembly::MM4 || reg == Framework::Assembly::MM5;
}

struct MachineCodeInstruction
{
    bool needsRex;
    char opcode[3];
    char opcodeLength;
    bool needsModRM;
    char modRM;
    bool sibNeeded;
    char sib;
    char disp[4];
    char dispLength;
    char imm[8];
    char immLength;
    OperandSizeOverwrite operandSizeOverride;
    bool errIfRex;
    bool errIfNoRex;
    bool exR;
    bool exX;
    bool exB;
    bool vexL;
    bool exWE;
    int vexVVVV;
    char vexPP;
    bool needsVex;

    void write(Framework::StreamWriter& writer) const
    {
        if (operandSizeOverride)
        {
            char prefix = *(char*)&operandSizeOverride;
            writer.schreibe(&prefix, 1);
        }
        if (needsRex && !needsVex)
        {
            char rex = 0b01000000 | ((exWE & 0b1) << 3) | ((exR & 0b1) << 2)
                     | ((exX & 0b1) << 1) | (exB & 0b1);
            writer.schreibe(&rex, 1);
        }
        int opCodeOffset = 0;
        if (needsVex)
        {
            char vexMapSelect = 0;
            if (opcode[0] == 0x0F)
            {
                opCodeOffset = 1;
                vexMapSelect = 1;
                if (opcode[1] == 0x38)
                {
                    vexMapSelect = 2;
                    opCodeOffset = 2;
                }
                else if (opcode[1] == 0x3A)
                {
                    vexMapSelect = 3;
                    opCodeOffset = 2;
                }
            }
            if (exX || exB || exWE || vexMapSelect != 1)
            {
                // 3-byte VEX
                char vex2[3];
                vex2[0] = (char)0xC4;
                vex2[1]
                    = (((~(char)exR) & 0b1) << 7) | (((~(char)exX) & 0b1) << 6)
                    | (((~(char)exB) & 0b1) << 5) | (vexMapSelect & 0b11111);
                vex2[2] = ((exWE & 0b1) << 7)
                        | (((~(char)vexVVVV) & 0b1111) << 3)
                        | ((vexL & 0b1) << 2) | (vexPP & 0b11);
                writer.schreibe(vex2, 3);
            }
            else
            {
                // 2-byte VEX
                char vex2[2];
                vex2[0] = (char)0xC5;
                vex2[1] = (((~(char)exR) & 0b1) << 7)
                        | (((~(char)vexVVVV) & 0b1111) << 3)
                        | ((vexL & 0b1) << 2) | (vexPP & 0b11);
                writer.schreibe(vex2, 2);
            }
        }
        writer.schreibe(opcode + opCodeOffset, opcodeLength - opCodeOffset);
        if (needsModRM)
        {
            writer.schreibe(&modRM, 1);
        }
        if (sibNeeded)
        {
            writer.schreibe(&sib, 1);
        }
        if (dispLength > 0)
        {
            writer.schreibe(disp, dispLength);
        }
        if (immLength > 0)
        {
            writer.schreibe(imm, immLength);
        }
    }

    int calculateSize() const
    {
        int size = 0;
        if (operandSizeOverride)
        {
            size += 1;
        }
        if (needsRex && !needsVex)
        {
            size += 1;
        }
        int opCodeOffset = 0;
        if (needsVex)
        {
            char vexMapSelect = 0;
            if (opcode[0] == 0x0F)
            {
                opCodeOffset = 1;
                vexMapSelect = 1;
                if (opcode[1] == 0x38)
                {
                    vexMapSelect = 2;
                    opCodeOffset = 2;
                }
                else if (opcode[1] == 0x3A)
                {
                    vexMapSelect = 3;
                    opCodeOffset = 2;
                }
            }
            if (exX || exB || exWE || vexMapSelect != 1)
            {
                size += 3;
            }
            else
            {
                size += 2;
            }
        }
        size += opcodeLength - opCodeOffset;
        if (needsModRM)
        {
            size += 1;
        }
        if (sibNeeded)
        {
            size += 1;
        }
        size += dispLength;
        size += immLength;
        return size;
    }
};

enum OperandEncoding
{
    UNDEFINED,
    MODRM_REG,
    MODRM_RM,
    VEX_VVVV,
    OPCODE_RD,
    // EVEX_VVVV,
    IMM8,
    IMM16,
    IMM32,
    IMM64,
};

enum OperandRW
{
    NONE = 0,
    READ = 1,
    WRITE = 2,
    READWRITE = 3,
};

class MachineCodeTableEntry
{
private:
    int numArgs;
    std::function<bool(const Framework::Assembly::OperationArgument& arg)>
        op1Validator;
    std::function<bool(const Framework::Assembly::OperationArgument& arg)>
        op2Validator;
    std::function<bool(const Framework::Assembly::OperationArgument& arg)>
        op3Validator;
    std::function<bool(const Framework::Assembly::OperationArgument& arg)>
        op4Validator;
    bool vex;
    bool vexL;
    char vexPP;
    bool rexW;
    char rmReg;
    char opcode[3];
    char opcodeLength;
    OperandEncoding op1Encoding;
    OperandEncoding op2Encoding;
    OperandEncoding op3Encoding;
    OperandEncoding op4Encoding;
    OperandRW op1RW;
    OperandRW op2RW;
    OperandRW op3RW;
    OperandRW op4RW;
    std::vector<Framework::Assembly::GPRegister> impliedReadGPRegs;
    std::vector<Framework::Assembly::GPRegister> impliedWriteGPRegs;
    std::vector<Framework::Assembly::FPRegister> impliedReadFPRegs;
    std::vector<Framework::Assembly::FPRegister> impliedWriteFPRegs;
    OperandSizeOverwrite operandSizeOverride;

public:
    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg)
        : numArgs(0),
          rexW(rexW),
          rmReg(rmReg),
          opcodeLength(opcodeLength),
          operandSizeOverride(operandSizeOverride),
          vex(vex),
          vexL(vexL),
          vexPP(vexPP),
          op1Encoding(UNDEFINED),
          op2Encoding(UNDEFINED),
          op3Encoding(UNDEFINED),
          op4Encoding(UNDEFINED),
          op1RW(NONE),
          op2RW(NONE),
          op3RW(NONE),
          op4RW(NONE)
    {
        this->opcode[0] = (char)(opcode & 0xFF);
        this->opcode[1] = (char)((opcode >> 8) & 0xFF);
        this->opcode[2] = (char)((opcode >> 16) & 0xFF);
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedReadGPRegs,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedWriteGPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedReadFPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedWriteFPRegs)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg)
    {
        this->opcode[0] = (char)(opcode & 0xFF);
        this->opcode[1] = (char)((opcode >> 8) & 0xFF);
        this->opcode[2] = (char)((opcode >> 16) & 0xFF);
        this->impliedReadGPRegs = impliedReadGPRegs;
        this->impliedWriteGPRegs = impliedWriteGPRegs;
        this->impliedReadFPRegs = impliedReadFPRegs;
        this->impliedWriteFPRegs = impliedWriteFPRegs;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg)
    {
        numArgs = 1;
        this->op1Validator = op1Validator;
        this->op1Encoding = op1Encoding;
        this->op1RW = op1RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedReadGPRegs,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedWriteGPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedReadFPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedWriteFPRegs,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              impliedReadGPRegs,
              impliedWriteGPRegs,
              impliedReadFPRegs,
              impliedWriteFPRegs)
    {
        numArgs = 1;
        this->op1Validator = op1Validator;
        this->op1Encoding = op1Encoding;
        this->op1RW = op1RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op2Validator,
        OperandEncoding op2Encoding,
        OperandRW op2RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              op1Validator,
              op1Encoding,
              op1RW)
    {
        numArgs = 2;
        this->op2Validator = op2Validator;
        this->op2Encoding = op2Encoding;
        this->op2RW = op2RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedReadGPRegs,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedWriteGPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedReadFPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedWriteFPRegs,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op2Validator,
        OperandEncoding op2Encoding,
        OperandRW op2RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              impliedReadGPRegs,
              impliedWriteGPRegs,
              impliedReadFPRegs,
              impliedWriteFPRegs,
              op1Validator,
              op1Encoding,
              op1RW)
    {
        numArgs = 2;
        this->op2Validator = op2Validator;
        this->op2Encoding = op2Encoding;
        this->op2RW = op2RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op2Validator,
        OperandEncoding op2Encoding,
        OperandRW op2RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op3Validator,
        OperandEncoding op3Encoding,
        OperandRW op3RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              op1Validator,
              op1Encoding,
              op1RW,
              op2Validator,
              op2Encoding,
              op2RW)
    {
        numArgs = 3;
        this->op3Validator = op3Validator;
        this->op3Encoding = op3Encoding;
        this->op3RW = op3RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedReadGPRegs,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedWriteGPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedReadFPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedWriteFPRegs,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op2Validator,
        OperandEncoding op2Encoding,
        OperandRW op2RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op3Validator,
        OperandEncoding op3Encoding,
        OperandRW op3RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              impliedReadGPRegs,
              impliedWriteGPRegs,
              impliedReadFPRegs,
              impliedWriteFPRegs,
              op1Validator,
              op1Encoding,
              op1RW,
              op2Validator,
              op2Encoding,
              op2RW)
    {
        numArgs = 3;
        this->op3Validator = op3Validator;
        this->op3Encoding = op3Encoding;
        this->op3RW = op3RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op2Validator,
        OperandEncoding op2Encoding,
        OperandRW op2RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op3Validator,
        OperandEncoding op3Encoding,
        OperandRW op3RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op4Validator,
        OperandEncoding op4Encoding,
        OperandRW op4RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              op1Validator,
              op1Encoding,
              op1RW,
              op2Validator,
              op2Encoding,
              op2RW,
              op3Validator,
              op3Encoding,
              op3RW)
    {
        numArgs = 4;
        this->op4Validator = op4Validator;
        this->op4Encoding = op4Encoding;
        this->op4RW = op4RW;
    }

    MachineCodeTableEntry(bool rexW,
        int opcode,
        char opcodeLength,
        OperandSizeOverwrite operandSizeOverride,
        bool vex,
        bool vexL,
        char vexPP,
        char rmReg,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedReadGPRegs,
        std::initializer_list<Framework::Assembly::GPRegister>
            impliedWriteGPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedReadFPRegs,
        std::initializer_list<Framework::Assembly::FPRegister>
            impliedWriteFPRegs,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op1Validator,
        OperandEncoding op1Encoding,
        OperandRW op1RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op2Validator,
        OperandEncoding op2Encoding,
        OperandRW op2RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op3Validator,
        OperandEncoding op3Encoding,
        OperandRW op3RW,
        std::function<bool(const Framework::Assembly::OperationArgument& arg)>
            op4Validator,
        OperandEncoding op4Encoding,
        OperandRW op4RW)
        : MachineCodeTableEntry(rexW,
              opcode,
              opcodeLength,
              operandSizeOverride,
              vex,
              vexL,
              vexPP,
              rmReg,
              impliedReadGPRegs,
              impliedWriteGPRegs,
              impliedReadFPRegs,
              impliedWriteFPRegs,
              op1Validator,
              op1Encoding,
              op1RW,
              op2Validator,
              op2Encoding,
              op2RW,
              op3Validator,
              op3Encoding,
              op3RW)
    {
        numArgs = 4;
        this->op4Validator = op4Validator;
        this->op4Encoding = op4Encoding;
        this->op4RW = op4RW;
    }

    MachineCodeTableEntry(const MachineCodeTableEntry& other) = default;

    bool matches(int numArgs,
        const std::vector<Framework::Assembly::OperationArgument*>& args) const
    {
        if (numArgs != this->numArgs)
        {
            return false;
        }
        if (numArgs >= 1 && !op1Validator(*args[0]))
        {
            return false;
        }
        if (numArgs >= 2 && !op2Validator(*args[1]))
        {
            return false;
        }
        if (numArgs >= 3 && !op3Validator(*args[2]))
        {
            return false;
        }
        if (numArgs >= 4 && !op4Validator(*args[3]))
        {
            return false;
        }
        return true;
    }

    OperandRW getOperandRW(int index) const
    {
        switch (index)
        {
        case 0:
            return op1RW;
        case 1:
            return op2RW;
        case 2:
            return op3RW;
        case 3:
            return op4RW;
        default:
            return NONE;
        }
    }

    const std::vector<Framework::Assembly::GPRegister>&
    getImpliedReadGPRegs() const
    {
        return impliedReadGPRegs;
    }

    const std::vector<Framework::Assembly::GPRegister>&
    getImpliedWriteGPRegs() const
    {
        return impliedWriteGPRegs;
    }

    const std::vector<Framework::Assembly::FPRegister>&
    getImpliedReadFPRegs() const
    {
        return impliedReadFPRegs;
    }

    const std::vector<Framework::Assembly::FPRegister>&
    getImpliedWriteFPRegs() const
    {
        return impliedWriteFPRegs;
    }

    friend class OperationCodeTable;
};

class OperationCodeTable : public Framework::ReferenceCounter
{
public:
    thread_local static Framework::RCArray<OperationCodeTable>
        machineCodeTranslationTable;

private:
    Framework::Assembly::Operation op;
    std::vector<MachineCodeTableEntry> entries;

public:
    OperationCodeTable(Framework::Assembly::Operation op,
        std::initializer_list<MachineCodeTableEntry> entries)
        : ReferenceCounter(),
          op(op),
          entries(entries)
    {}

    virtual MachineCodeInstruction getInstruction(
        const std::vector<Framework::Assembly::OperationArgument*>& args,
        const Framework::Assembly::AssemblyBlock* codeBlock,
        const Framework::Assembly::Instruction* current,
        Framework::Text& err)
    {
        MachineCodeInstruction result;
        memset(&result, 0, sizeof(MachineCodeInstruction));
        const MachineCodeTableEntry* entry
            = getEntry(args, codeBlock, current, err);
        if (!entry)
        {
            return result;
        }
        result.needsVex = entry->vex;
        result.vexL = entry->vexL;
        result.vexPP = entry->vexPP;
        result.needsRex = entry->rexW;
        result.exWE = entry->rexW;
        result.modRM = entry->rmReg << 3;
        if (entry->rmReg)
        {
            result.needsModRM = true;
        }
        memcpy(result.opcode, entry->opcode, 3);
        result.opcodeLength = entry->opcodeLength;
        result.operandSizeOverride = entry->operandSizeOverride;
        for (int i = 0; i < args.size(); i++)
        {
            OperandEncoding encoding = UNDEFINED;
            switch (i)
            {
            case 0:
                encoding = entry->op1Encoding;
                break;
            case 1:
                encoding = entry->op2Encoding;
                break;
            case 2:
                encoding = entry->op3Encoding;
                break;
            case 3:
                encoding = entry->op4Encoding;
                break;
            }
            switch (encoding)
            {
            case MODRM_REG:
                encodeModRM_REG(result, args[i], i + 1, err);
                break;
            case MODRM_RM:
                encodeModRM_RM(result, args[i], i + 1, err);
                break;
            case VEX_VVVV:
                encodeVex_VVVV(result, args[i], i + 1, err);
                break;
            case OPCODE_RD:
                encodeOpcode_RD(result, args[i], i + 1, err);
                break;
            case IMM8:
                encodeIMM8(result, args[i], i + 1, err);
                break;
            case IMM16:
                encodeIMM16(result, args[i], i + 1, err);
                break;
            case IMM32:
                encodeIMM32(result, args[i], i + 1, err);
                break;
            case IMM64:
                encodeIMM64(result, args[i], i + 1, err);
                break;
            }
        }
        if (result.errIfNoRex && !result.needsRex)
        {
            err.append() << "Instruction " << op
                         << " has no REX prefix and can not address "
                            "LOWER8 of registers RSP, RBP, RSI or RDI\n";
        }
        if (result.errIfRex && result.needsRex)
        {
            err.append() << "Instruction " << op
                         << " has a REX prefix and can not address "
                            "HIGHER8 of registers RAX, RBX, RCX or RDX\n";
        }
        return result;
    }

    MachineCodeTableEntry* getEntry(
        const std::vector<Framework::Assembly::OperationArgument*>& args,
        const Framework::Assembly::AssemblyBlock* codeBlock,
        const Framework::Assembly::Instruction* current,
        Framework::Text& err)
    {
        MachineCodeInstruction result;
        memset(&result, 0, sizeof(MachineCodeInstruction));
        for (MachineCodeTableEntry& entry : entries)
        {
            if (entry.matches((int)args.size(), args))
            {
                return &entry;
            }
        }
        err.append() << "operation " << (int)op
                     << " not found in translation table. args: \n";
        for (auto arg : args)
        {
            err.append() << "  " << typeid(*arg).name() << "\n";
        }
        return 0;
    }

    Framework::Assembly::Operation getOperation() const
    {
        return op;
    }

    void encodeModRM_REG(MachineCodeInstruction& result,
        const Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        result.needsModRM = true;
        const Framework::Assembly::GPRegisterArgument* gpRegArg
            = arg->asGPRegisterArgument();
        const Framework::Assembly::FPRegisterArgument* fpRegArg
            = arg->asFPRegisterArgument();
        if (gpRegArg)
        {
            encodeModRM_REG_GP(result, gpRegArg, index, err);
        }
        else if (fpRegArg)
        {
            encodeModRM_REG_FP(result, fpRegArg, index, err);
        }
        else
        {
            err.append()
                << "Invalid argument type for operand " << index
                << " for operation " << op << " encoded as MODRM_REG: found "
                << typeid(*arg).name()
                << " but expected GPRegisterArgument or FPRegisterArgument\n";
        }
    }

    void encodeModRM_REG_GP(MachineCodeInstruction& result,
        const Framework::Assembly::GPRegisterArgument* arg,
        int index,
        Framework::Text& err) const
    {
        Framework::Assembly::GPRegister reg = arg->getRegister();
        if (reg >= Framework::Assembly::R8)
        {
            result.needsRex = true;
            result.exR = 1;
        }
        if (arg->getPart() == Framework::Assembly::GPRegisterPart::HIGHER8)
        {
            if (reg == Framework::Assembly::RAX)
            {
                result.modRM |= 0b100000;
                result.errIfRex = true;
            }
            else if (reg == Framework::Assembly::RBX)
            {
                result.modRM |= 0b111000;
                result.errIfRex = true;
            }
            else if (reg == Framework::Assembly::RCX)
            {
                result.modRM |= 0b101000;
                result.errIfRex = true;
            }
            else if (reg == Framework::Assembly::RDX)
            {
                result.modRM |= 0b110000;
                result.errIfRex = true;
            }
            else
            {
                err.append() << "Invalid argument for operand " << index
                             << " for operation " << op
                             << " HIGHER8 can only be used for registers RAX, "
                                "RBX, RCX or RDX\n";
            }
        }
        else
        {
            result.modRM |= (reg & 0b111) << 3;
        }
        if (arg->getPart() == Framework::Assembly::GPRegisterPart::LOWER8
            && (reg == Framework::Assembly::RSP
                || reg == Framework::Assembly::RBP
                || reg == Framework::Assembly::RSI
                || reg == Framework::Assembly::RDI))
        {
            result.errIfNoRex = true;
        }
    }

    void encodeModRM_REG_FP(MachineCodeInstruction& result,
        const Framework::Assembly::FPRegisterArgument* arg,
        int index,
        Framework::Text& err) const
    {
        Framework::Assembly::FPRegister reg = arg->getRegister();
        if (reg >= Framework::Assembly::MM8)
        {
            result.needsRex = true;
            result.exR = 1;
        }
        result.modRM |= (reg & 0b111) << 3;
    }

    void encodeModRM_RM(MachineCodeInstruction& result,
        const Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        result.needsModRM = true;
        const Framework::Assembly::GPRegisterArgument* gpRegArg
            = arg->asGPRegisterArgument();
        const Framework::Assembly::FPRegisterArgument* fpRegArg
            = arg->asFPRegisterArgument();
        const Framework::Assembly::MemoryAccessArgument* memArg
            = arg->asMemoryAccessArgument();
        if (gpRegArg)
        {
            encodeModRM_RM_GP(result, gpRegArg, index, err);
        }
        else if (fpRegArg)
        {
            encodeModRM_RM_FP(result, fpRegArg, index, err);
        }
        else if (memArg)
        {
            encodeModRM_RM_Mem(result, memArg, index, err);
        }
        else
        {
            err.append()
                << "Invalid argument type for operand " << index
                << " for operation " << op << " encoded as MODRM_RM: found "
                << typeid(*arg).name()
                << " but expected GPRegisterArgument, FPRegisterArgument "
                   "or MemoryAccessArgument\n";
        }
    }

    void encodeModRM_RM_GP(MachineCodeInstruction& result,
        const Framework::Assembly::GPRegisterArgument* arg,
        int index,
        Framework::Text& err) const
    {
        Framework::Assembly::GPRegister reg = arg->getRegister();
        if (reg >= Framework::Assembly::R8)
        {
            result.needsRex = true;
            result.exB = 1;
        }
        result.modRM |= 0b11 << 6; // direct register access
        if (arg->getPart() == Framework::Assembly::GPRegisterPart::HIGHER8)
        {
            if (reg == Framework::Assembly::RAX)
            {
                result.modRM |= 0b100;
                result.errIfRex = true;
            }
            else if (reg == Framework::Assembly::RBX)
            {
                result.modRM |= 0b111;
                result.errIfRex = true;
            }
            else if (reg == Framework::Assembly::RCX)
            {
                result.modRM |= 0b101;
                result.errIfRex = true;
            }
            else if (reg == Framework::Assembly::RDX)
            {
                result.modRM |= 0b110;
                result.errIfRex = true;
            }
            else
            {
                err.append() << "Invalid argument for operand " << index
                             << " for operation " << op
                             << " HIGHER8 can only be used for registers RAX, "
                                "RBX, RCX or RDX\n";
            }
        }
        else
        {
            result.modRM |= reg & 0b111;
        }
        if (arg->getPart() == Framework::Assembly::GPRegisterPart::LOWER8
            && (reg == Framework::Assembly::RSP
                || reg == Framework::Assembly::RBP
                || reg == Framework::Assembly::RSI
                || reg == Framework::Assembly::RDI))
        {
            result.errIfNoRex = true;
        }
    }

    void encodeModRM_RM_FP(MachineCodeInstruction& result,
        const Framework::Assembly::FPRegisterArgument* arg,
        int index,
        Framework::Text& err) const
    {
        Framework::Assembly::FPRegister reg = arg->getRegister();
        if (reg >= Framework::Assembly::MM8)
        {
            result.needsRex = true;
            result.exB = 1;
        }
        result.modRM |= 0b11 << 6; // direct register access
        result.modRM |= reg & 0b111;
    }

    void encodeModRM_RM_Mem(MachineCodeInstruction& result,
        const Framework::Assembly::MemoryAccessArgument* arg,
        int index,
        Framework::Text& err) const
    {
        if (arg->isUsingAddressRegister() || arg->isUsingOffsetRegister())
        {
            Framework::Assembly::GPRegister reg = arg->isUsingAddressRegister()
                                                    ? arg->getAddressRegister()
                                                    : arg->getOffsetRegister();
            if (arg->isUsingAddressRegister() && arg->isUsingOffsetRegister())
            {
                // SIB needed
                result.sibNeeded = true;
                result.modRM |= 0b100; // indicate SIB
                if (reg >= Framework::Assembly::R8)
                {
                    result.needsRex = true;
                    result.exB = 1;
                }
                result.sib |= reg & 0b111;
                Framework::Assembly::GPRegister offsetReg
                    = arg->getOffsetRegister();
                if (offsetReg == Framework::Assembly::RSP)
                {
                    err.append() << "Invalid argument for operand " << index
                                 << " for operation " << op
                                 << " RSP can not be used as index register\n";
                }
                if (offsetReg >= Framework::Assembly::R8)
                {
                    result.needsRex = true;
                    result.exX = 1;
                }
                result.sib |= (offsetReg & 0b111) << 3; // index register
            }
            else if (reg == 0b100)
            {
                // SIB needed
                result.sibNeeded = true;
                result.modRM |= 0b100; // indicate SIB
                result.sib |= reg & 0b111;
                result.sib |= 0b100 << 3; // no index register
            }
            else
            {
                if (reg >= Framework::Assembly::R8)
                {
                    result.needsRex = true;
                    result.exB = 1;
                }
                result.modRM |= reg & 0b111;
            }
            int offset = arg->getOffset();
            if (offset)
            {
                if (offset <= 127 && offset >= -128)
                {
                    result.modRM |= 0b01 << 6; // 8 bit displacement
                    result.disp[0] = (char)offset;
                    result.dispLength = 1;
                }
                else
                {
                    result.modRM |= 0b10 << 6; // 32 bit displacement
                    memcpy(result.disp, &offset, 4);
                }
            }
            else
            {
                if ((result.modRM & 0b111) == 0b101)
                {
                    // special case: EBP or R13 as
                    // address register needs disp8=0
                    result.modRM |= 0b01 << 6; // 8 bit displacement
                    result.disp[0] = 0;
                    result.dispLength = 1;
                }
            }
        }
        else
        {
            result.modRM |= 0b100;
            result.sibNeeded = true;
            result.sib = 0b00100101; // no base, no index only
                                     // disp32
            int offset = arg->getOffset();
            memcpy(result.disp, &offset, 4);
            result.dispLength = 4;
        }
    }

    void encodeVex_VVVV(MachineCodeInstruction& result,
        const Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        const Framework::Assembly::FPRegisterArgument* fpRegArg
            = arg->asFPRegisterArgument();
        if (fpRegArg)
        {
            encodeVex_VVVV_FP(result, fpRegArg, index, err);
        }
        else
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as VEX_VVVV: found "
                         << typeid(*arg).name()
                         << " but expected FPRegisterArgument\n";
        }
    }

    void encodeVex_VVVV_FP(MachineCodeInstruction& result,
        const Framework::Assembly::FPRegisterArgument* arg,
        int index,
        Framework::Text& err) const
    {
        Framework::Assembly::FPRegister reg = arg->getRegister();
        result.vexVVVV = reg & 0b1111;
        result.needsVex = true;
    }

    void encodeOpcode_RD(MachineCodeInstruction& result,
        const Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        const Framework::Assembly::GPRegisterArgument* gpRegArg
            = arg->asGPRegisterArgument();
        if (gpRegArg)
        {
            encodeOpcode_RD_GP(result, gpRegArg, index, err);
        }
        else
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as OPCODE_RD: found "
                         << typeid(*arg).name()
                         << " but expected GPRegisterArgument\n";
        }
    }

    void encodeOpcode_RD_GP(MachineCodeInstruction& result,
        const Framework::Assembly::GPRegisterArgument* arg,
        int index,
        Framework::Text& err) const
    {
        Framework::Assembly::GPRegister reg = arg->getRegister();
        if (reg >= Framework::Assembly::R8)
        {
            result.needsRex = true;
            result.exB = 1;
        }
        result.opcode[result.opcodeLength - 1] |= reg & 0b111;
    }

    void encodeIMM8(MachineCodeInstruction& result,
        Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        if (result.immLength >= 8)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM8: imm bytes are already in use\n";
            return;
        }
        const Framework::Assembly::ConstantArgument* constArg
            = arg->asConstantArgument();
        if (constArg == 0)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM8: found " << typeid(*arg).name()
                         << " but expected ConstantArgument\n";
            return;
        }
        int value = (int)constArg->getValue();
        int len = (int)constArg->getSize();
        if (len > 1)
        {
            err.append() << "Constant size too large for operand " << index
                         << " for operation " << op
                         << " encoded as IMM8: found size " << len
                         << " but expected size BYTE\n";
            return;
        }
        result.imm[(int)result.immLength] = (char)(value);
        result.immLength += 1;
    }

    void encodeIMM16(MachineCodeInstruction& result,
        Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        if (result.immLength >= 7)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM16: imm bytes are already in use\n";
            return;
        }
        const Framework::Assembly::ConstantArgument* constArg
            = arg->asConstantArgument();
        if (constArg == 0)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM16: found " << typeid(*arg).name()
                         << " but expected ConstantArgument\n";
            return;
        }
        int value = (int)constArg->getValue();
        int len = (int)constArg->getSize();
        if (len > 2)
        {
            err.append() << "Constant size too large for operand " << index
                         << " for operation " << op
                         << " encoded as IMM16: found size " << len
                         << " but expected size range [BYTE, WORD]\n";
            return;
        }
        short val = (short)(value);
        memcpy(result.imm + result.immLength, &val, 2);
        result.immLength += 2;
    }

    void encodeIMM32(MachineCodeInstruction& result,
        Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        if (result.immLength >= 5)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM32: imm bytes are already in use\n";
            return;
        }
        const Framework::Assembly::ConstantArgument* constArg
            = arg->asConstantArgument();
        if (constArg == 0)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM32: found " << typeid(*arg).name()
                         << " but expected ConstantArgument\n";
            return;
        }
        int value = (int)constArg->getValue();
        int len = (int)constArg->getSize();
        if (len > 4)
        {
            err.append() << "Constant size too large for operand " << index
                         << " for operation " << op
                         << " encoded as IMM32: found size " << len
                         << " but expected size range [BYTE, DWORD]\n";
            return;
        }
        memcpy(result.imm + result.immLength, &value, 4);
        result.immLength += 4;
    }

    void encodeIMM64(MachineCodeInstruction& result,
        Framework::Assembly::OperationArgument* arg,
        int index,
        Framework::Text& err) const
    {
        if (result.immLength >= 1)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM64: imm bytes are already in use\n";
            return;
        }
        const Framework::Assembly::ConstantArgument* constArg
            = arg->asConstantArgument();
        if (constArg == 0)
        {
            err.append() << "Invalid argument type for operand " << index
                         << " for operation " << op
                         << " encoded as IMM64: found " << typeid(*arg).name()
                         << " but expected ConstantArgument\n";
            return;
        }
        __int64 value = constArg->getValue();
        int len = (int)constArg->getSize();
        if (len > 8)
        {
            err.append() << "Constant size too large for operand " << index
                         << " for operation " << op
                         << " encoded as IMM64: found size " << len
                         << " but expected size range [BYTE, QWORD]\n";
            return;
        }
        memcpy(result.imm + result.immLength, &value, 8);
        result.immLength += 8;
    }
};

class JumpOperationCodeTable : public OperationCodeTable
{
private:
    char opCodeLength;
    bool inGetEntry;

public:
    JumpOperationCodeTable(Framework::Assembly::Operation op,
        char opCodeLength,
        std::initializer_list<MachineCodeTableEntry> entries)
        : OperationCodeTable(op, entries),
          opCodeLength(opCodeLength),
          inGetEntry(0)
    {}

    virtual MachineCodeInstruction getInstruction(
        const std::vector<Framework::Assembly::OperationArgument*>& args,
        const Framework::Assembly::AssemblyBlock* codeBlock,
        const Framework::Assembly::Instruction* current,
        Framework::Text& err) override
    {
        if (inGetEntry)
        {
            // recursion can only happen during size calculation so we just
            // create a dummy const argument for each jump target
            std::vector<Framework::Assembly::OperationArgument*> newArgs;
            std::vector<Framework::Assembly::OperationArgument*>
                transformedArgs;
            for (Framework::Assembly::OperationArgument* arg : args)
            {
                if (arg->asJumpTargetArgument())
                {
                    Framework::Assembly::ConstantArgument* constArg
                        = new Framework::Assembly::ConstantArgument(0);
                    transformedArgs.push_back(constArg);
                    newArgs.push_back(constArg);
                }
                else
                {
                    transformedArgs.push_back(arg);
                }
            }
            MachineCodeInstruction result = OperationCodeTable::getInstruction(
                transformedArgs, codeBlock, current, err);
            for (Framework::Assembly::OperationArgument* arg : newArgs)
            {
                delete arg;
            }
            return result;
        }
        inGetEntry = 1;
        std::vector<Framework::Assembly::OperationArgument*> newArgs;
        std::vector<Framework::Assembly::OperationArgument*> transformedArgs;
        for (Framework::Assembly::OperationArgument* arg : args)
        {
            if (arg->asJumpTargetArgument())
            {
                Framework::Text label = arg->asJumpTargetArgument()->getLabel();
                bool currentFound = false;
                bool labelFound = false;
                bool backwords = false;
                int jumpLength = 0;
                // search for the label
                for (const Framework::Assembly::Instruction* instr :
                    codeBlock->getInstructions())
                {
                    if (instr == current)
                    {
                        currentFound = true;
                        if (labelFound)
                        {
                            break;
                        }
                        continue;
                    }
                    if (instr->definesLabel(label))
                    {
                        labelFound = true;
                        if (currentFound)
                        {
                            break;
                        }
                        else
                        {
                            backwords = true;
                        }
                        continue;
                    }
                    if (labelFound || currentFound)
                    {
                        jumpLength += instr->compiledSize(codeBlock);
                    }
                }
                if (backwords)
                {
                    jumpLength = -jumpLength - 4 - opCodeLength;
                }
                Framework::Assembly::ConstantArgument* constArg
                    = new Framework::Assembly::ConstantArgument(jumpLength);
                transformedArgs.push_back(constArg);
                newArgs.push_back(constArg);
            }
            else
            {
                transformedArgs.push_back(arg);
            }
        }
        MachineCodeInstruction result = OperationCodeTable::getInstruction(
            transformedArgs, codeBlock, current, err);
        for (Framework::Assembly::OperationArgument* arg : newArgs)
        {
            delete arg;
        }
        inGetEntry = 0;
        return result;
    }
};

thread_local Framework::RCArray<OperationCodeTable>
    OperationCodeTable::machineCodeTranslationTable;

std::function<bool(const Framework::Assembly::OperationArgument& arg)>
isGPRegister(Framework::Assembly::MemoryBlockSize size)
{
    return [size](const Framework::Assembly::OperationArgument& arg) {
        return arg.asGPRegisterArgument() != 0
            && ((size == Framework::Assembly::MemoryBlockSize::BYTE
                    && (arg.asGPRegisterArgument()->getPart()
                            == Framework::Assembly::LOWER8
                        || arg.asGPRegisterArgument()->getPart()
                               == Framework::Assembly::HIGHER8))
                || (size == Framework::Assembly::MemoryBlockSize::WORD
                    && arg.asGPRegisterArgument()->getPart()
                           == Framework::Assembly::LOWER16)
                || (size == Framework::Assembly::MemoryBlockSize::DWORD
                    && arg.asGPRegisterArgument()->getPart()
                           == Framework::Assembly::LOWER32)
                || (size == Framework::Assembly::MemoryBlockSize::QWORD
                    && arg.asGPRegisterArgument()->getPart()
                           == Framework::Assembly::FULL64));
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)>
isSpecificGPRegister(Framework::Assembly::GPRegister reg,
    Framework::Assembly::GPRegisterPart part)
{
    return [reg, part](const Framework::Assembly::OperationArgument& arg) {
        return arg.asGPRegisterArgument() != 0
            && arg.asGPRegisterArgument()->getRegister() == reg
            && arg.asGPRegisterArgument()->getPart() == part;
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)>
isGPRegisterOrMemoryAccess(Framework::Assembly::MemoryBlockSize size)
{
    return [size](const Framework::Assembly::OperationArgument& arg) {
        return isGPRegister(size)(arg)
            || arg.asMemoryAccessArgument()
                   && arg.asMemoryAccessArgument()->getBlockSize() == size;
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)> isIMM()
{
    return [](const Framework::Assembly::OperationArgument& arg) {
        return arg.asConstantArgument();
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)> isIMM(
    Framework::Assembly::MemoryBlockSize maxSize)
{
    return [maxSize](const Framework::Assembly::OperationArgument& arg) {
        return arg.asConstantArgument()
            && arg.asConstantArgument()->getSize() <= maxSize;
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)>
isFPRegister(Framework::Assembly::MemoryBlockSize size)
{
    return [size](const Framework::Assembly::OperationArgument& arg) {
        return arg.asFPRegisterArgument() != 0
            && ((size == Framework::Assembly::MemoryBlockSize::M128
                    && arg.asFPRegisterArgument()->getPart()
                           == Framework::Assembly::X)
                || (size == Framework::Assembly::MemoryBlockSize::M256
                    && arg.asFPRegisterArgument()->getPart()
                           == Framework::Assembly::Y)
                /*
                || (size == Framework::Assembly::MemoryBlockSize::M512
                    && arg.asFPRegisterArgument()->getPart()
                           == Framework::Assembly::Z)*/);
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)>
isFPRegisterOrMEmoryAccess(Framework::Assembly::MemoryBlockSize size)
{
    return [size](const Framework::Assembly::OperationArgument& arg) {
        return isFPRegister(size)
            || (arg.asMemoryAccessArgument()
                && arg.asMemoryAccessArgument()->getBlockSize() == size);
    };
}

std::function<bool(const Framework::Assembly::OperationArgument& arg)>
isFPRegisterOrMEmoryAccess(Framework::Assembly::MemoryBlockSize regSize,
    Framework::Assembly::MemoryBlockSize memSize)
{
    return
        [regSize, memSize](const Framework::Assembly::OperationArgument& arg) {
            return isFPRegister(regSize)
                || (arg.asMemoryAccessArgument()
                    && arg.asMemoryAccessArgument()->getBlockSize() == memSize);
        };
}

void __intializeMachineCodeTranslationTable()
{
    if (!OperationCodeTable::machineCodeTranslationTable.getEintragAnzahl())
    {
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::ADD,
                {// ADD AL, IMM8
                    MachineCodeTableEntry(false,
                        0x04,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READWRITE,
                        isIMM(),
                        IMM8,
                        READ),
                    // ADD AX, IMM16
                    MachineCodeTableEntry(false,
                        0x05,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READWRITE,
                        isIMM(),
                        IMM16,
                        READ),
                    // ADD EAX, IMM32
                    MachineCodeTableEntry(
                        false,
                        0x05,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READWRITE,
                        [](const Framework::Assembly::OperationArgument& arg) {
                            return arg.asConstantArgument() != 0;
                        },
                        IMM32,
                        READ),
                    // ADD RAX, IMM32
                    MachineCodeTableEntry(true,
                        0x05,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READWRITE,
                        isIMM(),
                        IMM32,
                        READ),
                    // ADD r/m8, IMM8
                    MachineCodeTableEntry(false,
                        0x80,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isIMM(),
                        IMM8,
                        READ),
                    // ADD r/m16, IMM8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // ADD r/m32, IMM8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // ADD r/m64, IMM8
                    MachineCodeTableEntry(true,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // ADD r/m16, IMM16
                    MachineCodeTableEntry(
                        false,
                        0x81,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        [](const Framework::Assembly::OperationArgument& arg) {
                            return arg.asConstantArgument()
                                && arg.asConstantArgument()->getSize()
                                       != Framework::Assembly::MemoryBlockSize::
                                           BYTE;
                        },
                        IMM16,
                        READ),
                    // ADD r/m32, IMM32
                    MachineCodeTableEntry(
                        false,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        [](const Framework::Assembly::OperationArgument& arg) {
                            return arg.asConstantArgument() != 0
                                && arg.asConstantArgument()->getSize()
                                       != Framework::Assembly::MemoryBlockSize::
                                           BYTE;
                        },
                        IMM32,
                        READ),
                    // ADD r/m64, IMM32
                    MachineCodeTableEntry(
                        true,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        [](const Framework::Assembly::OperationArgument& arg) {
                            return arg.asConstantArgument() != 0
                                && arg.asConstantArgument()->getSize()
                                       != Framework::Assembly::MemoryBlockSize::
                                           BYTE;
                        },
                        IMM32,
                        READ),
                    // ADD r/m8, r8
                    MachineCodeTableEntry(false,
                        0x00,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    // ADD r/m16, r16
                    MachineCodeTableEntry(false,
                        0x01,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    // ADD r/m32, r32
                    MachineCodeTableEntry(false,
                        0x01,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    // ADD r/m64, r64
                    MachineCodeTableEntry(true,
                        0x01,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    // ADD r8, r/m8
                    MachineCodeTableEntry(false,
                        0x02,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // ADD r16, r/m16
                    MachineCodeTableEntry(false,
                        0x03,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // ADD r32, r/m32
                    MachineCodeTableEntry(false,
                        0x03,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // ADD r64, r/m64
                    MachineCodeTableEntry(true,
                        0x03,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::ADDPD,
                {// ADDPD xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VADDPD xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VADDPD ymm1,ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::ADDPS,
                {// ADDPS xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VADDPS xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VADDPS ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::ADDSD,
                {// ADDSD xmm1, xmm2/m64
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // VADDPS VADDSD xmm1, xmm2, xmm3/m64
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b11,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::ADDSS,
                {// ADDPS xmm1, xmm2/m32
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,

                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // VADDPS VADDSD xmm1, xmm2, xmm3/m64
                    MachineCodeTableEntry(false,
                        0x580F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b10,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::SUB,
                {
                    // SUB AL, imm8
                    MachineCodeTableEntry(false,
                        0x2C,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // SUB AX, imm16
                    MachineCodeTableEntry(false,
                        0x2D,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // SUB EAX, imm32
                    MachineCodeTableEntry(false,
                        0x2D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // SUB RAX, imm32
                    MachineCodeTableEntry(true,
                        0x2D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // SUB r/m8, imm8
                    MachineCodeTableEntry(false,
                        0x80,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // SUB r/m16, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // SUB r/m32, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // SUB r/m64, imm8
                    MachineCodeTableEntry(true,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // SUB r/m16, imm16
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // SUB r/m32, imm32
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // SUB r/m64, imm32
                    MachineCodeTableEntry(true,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // SUB r/m8, r8
                    MachineCodeTableEntry(false,
                        0x28,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    // SUB r/m16, r16
                    MachineCodeTableEntry(false,
                        0x29,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    // SUB r/m32, r32
                    MachineCodeTableEntry(false,
                        0x29,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    // SUB r/m64, r64
                    MachineCodeTableEntry(true,
                        0x29,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    // SUB r8, r/m8
                    MachineCodeTableEntry(false,
                        0x2A,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // SUB r16, r/m16
                    MachineCodeTableEntry(false,
                        0x2B,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // SUB r32, r/m32
                    MachineCodeTableEntry(false,
                        0x2B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // SUB SUB r64, r/m64
                    MachineCodeTableEntry(true,
                        0x2B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::SUBPD,
                {
                    // SUBPD xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x5D0F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VSUBPD xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VSUBPD ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::SUBPS,
                {
                    // SUBPS xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x5D0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VSUBPS xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b00,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VSUBPS ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b00,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::SUBSD,
                {
                    // SUBSD xmm1, xmm2/m64
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // VSUBSD xmm1,xmm2, xmm3/m64
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b11,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::SUBSS,
                {
                    // SUBSS xmm1, xmm2/m32
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // VSUBSD xmm1,xmm2, xmm3/m32
                    MachineCodeTableEntry(false,
                        0x5C0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b10,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MUL,
                {
                    // MUL r/m8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // MUL r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b100,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // MUL r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // MUL r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::IMUL,
                {
                    // IMUL r/m8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // IMUL r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b101,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // IMUL r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // IMUL r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b101,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // IMUL r16, r/m16
                    MachineCodeTableEntry(false,
                        0xAF0F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // IMUL r32, r/m32
                    MachineCodeTableEntry(false,
                        0xAF0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // IMUL r64, r/m64
                    MachineCodeTableEntry(true,
                        0xAF0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // IMUL r16, r/m16, imm8
                    MachineCodeTableEntry(false,
                        0x6B,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // IMUL r32, r/m32, imm8
                    MachineCodeTableEntry(false,
                        0x6B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // IMUL r64, r/m64, imm8
                    MachineCodeTableEntry(true,
                        0x6B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // IMUL r16, r/m16, imm16
                    MachineCodeTableEntry(false,
                        0x69,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // IMUL r32, r/m32, imm32
                    MachineCodeTableEntry(false,
                        0x69,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // IMUL r64, r/m64
                    MachineCodeTableEntry(true,
                        0x69,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MULPD,
                {
                    // MULPD xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VMULPD xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VMULPD ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MULPS,
                {
                    // MULPS xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VMULPS xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VMULPS ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MULSD,
                {
                    // MULSD xmm1,xmm2/m64
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VMULSD xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b11,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MULSS,
                {
                    // MULSS xmm1,xmm2/m64
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VMULSS xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x590F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b10,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::DIV,
                {
                    // DIV r/m8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // DIV r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b110,
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // DIV r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // DIV r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::IDIV,
                {
                    // IDIV r/m8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        {Framework::Assembly::RAX},
                        {Framework::Assembly::RAX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // IDIV r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b111,
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // IDIV r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // IDIV r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {Framework::Assembly::RAX, Framework::Assembly::RDX},
                        {},
                        {},
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::DIVPD,
                {
                    // DIVPD xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VDIVPD xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VDIVPD ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::DIVPS,
                {
                    // DIVPS xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VDIVPS xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VDIVPS ymm1, ymm2, ymm3/m256
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::DIVSD,
                {
                    // DIVSD xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VDIVSD xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b11,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::DIVSS,
                {
                    // DIVSS xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // VDIVSS xmm1,xmm2, xmm3/m128
                    MachineCodeTableEntry(false,
                        0x5E0F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b10,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::NEG,
                {
                    // NEG r/m8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b011,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE),
                    // NEG r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b011,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE),
                    // NEG r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b011,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE),
                    // NEG r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b011,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::INC,
                {
                    // INC r/m8
                    MachineCodeTableEntry(false,
                        0xFE,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE),
                    // INC r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE),
                    // INC r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE),
                    // INC r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::AND,
                {
                    // AND AL, imm8
                    MachineCodeTableEntry(false,
                        0x24,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // AND AX, imm16
                    MachineCodeTableEntry(false,
                        0x25,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // AND EAX, imm32
                    MachineCodeTableEntry(false,
                        0x25,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // AND RAX, imm32
                    MachineCodeTableEntry(true,
                        0x25,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // AND r/m8, imm8
                    MachineCodeTableEntry(false,
                        0x80,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // AND r/m16, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    //	AND r/m32, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    //	AND r/m64, imm8
                    MachineCodeTableEntry(true,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // AND r/m16, imm16
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    //	AND r/m32, imm32
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    //	AND r/m64, imm32
                    MachineCodeTableEntry(true,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b100,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    //	AND r/m8, r8
                    MachineCodeTableEntry(false,
                        0x20,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    //	AND r/m16, r16
                    MachineCodeTableEntry(false,
                        0x21,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    //	AND r/m32, r32
                    MachineCodeTableEntry(false,
                        0x21,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    //	AND r/m64, r64
                    MachineCodeTableEntry(true,
                        0x21,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    //	AND r8, r/m8
                    MachineCodeTableEntry(false,
                        0x22,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    //	AND r16, r/m16
                    MachineCodeTableEntry(false,
                        0x23,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    //	AND r32, r/m32
                    MachineCodeTableEntry(false,
                        0x23,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    //	AND r64, r/m64
                    MachineCodeTableEntry(true,
                        0x23,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::OR,
                {
                    // OR AL, imm8
                    MachineCodeTableEntry(false,
                        0x0C,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // OR AX, imm16
                    MachineCodeTableEntry(false,
                        0x0D,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // OR EAX, imm32
                    MachineCodeTableEntry(false,
                        0x0D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // OR RAX, imm32
                    MachineCodeTableEntry(true,
                        0x0D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // OR r/m8, imm8
                    MachineCodeTableEntry(false,
                        0x80,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // OR r/m16, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    //	OR r/m32, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    //	OR r/m64, imm8
                    MachineCodeTableEntry(true,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // OR r/m16, imm16
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    //	OR r/m32, imm32
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    //	OR r/m64, imm32
                    MachineCodeTableEntry(true,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b001,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    //	OR r/m8, r8
                    MachineCodeTableEntry(false,
                        0x08,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    //	OR r/m16, r16
                    MachineCodeTableEntry(false,
                        0x09,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    //	OR r/m32, r32
                    MachineCodeTableEntry(false,
                        0x09,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    //	OR r/m64, r64
                    MachineCodeTableEntry(true,
                        0x09,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    //	OR r8, r/m8
                    MachineCodeTableEntry(false,
                        0x0A,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    //	OR r16, r/m16
                    MachineCodeTableEntry(false,
                        0x0B,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    //	OR r32, r/m32
                    MachineCodeTableEntry(false,
                        0x0B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    //	OR r64, r/m64
                    MachineCodeTableEntry(true,
                        0x0B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::XOR,
                {
                    // XOR AL, imm8
                    MachineCodeTableEntry(false,
                        0x34,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // XOR AX, imm16
                    MachineCodeTableEntry(false,
                        0x35,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // XOR EAX, imm32
                    MachineCodeTableEntry(false,
                        0x35,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // XOR RAX, imm32
                    MachineCodeTableEntry(true,
                        0x35,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // XOR r/m8, imm8
                    MachineCodeTableEntry(false,
                        0x80,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // XOR r/m16, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    //	XOR r/m32, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    //	XOR r/m64, imm8
                    MachineCodeTableEntry(true,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // XOR r/m16, imm16
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    //	XOR r/m32, imm32
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    //	XOR r/m64, imm32
                    MachineCodeTableEntry(true,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    //	XOR r/m8, r8
                    MachineCodeTableEntry(false,
                        0x30,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    //	XOR r/m16, r16
                    MachineCodeTableEntry(false,
                        0x31,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    //	XOR r/m32, r32
                    MachineCodeTableEntry(false,
                        0x31,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    //	XOR r/m64, r64
                    MachineCodeTableEntry(true,
                        0x31,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READWRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    //	XOR r8, r/m8
                    MachineCodeTableEntry(false,
                        0x32,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    //	XOR r16, r/m16
                    MachineCodeTableEntry(false,
                        0x33,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    //	XOR r32, r/m32
                    MachineCodeTableEntry(false,
                        0x33,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    //	XOR r64, r/m64
                    MachineCodeTableEntry(true,
                        0x33,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READWRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::NOT,
                {
                    // NOT r/m8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b010,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READWRITE),
                    // NOT r/m16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b010,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READWRITE),
                    // NOT r/m32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b010,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE),
                    // NOT r/m64
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b010,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READWRITE),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::TEST,
                {
                    // TEST AL, imm8
                    MachineCodeTableEntry(false,
                        0xA8,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // TEST AX, imm16
                    MachineCodeTableEntry(false,
                        0xA9,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // TEST EAX, imm32
                    MachineCodeTableEntry(false,
                        0xA9,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // TEST RAX, imm32
                    MachineCodeTableEntry(true,
                        0xA9,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // TEST r/m8, imm8
                    MachineCodeTableEntry(false,
                        0xF6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // TEST r/m16, imm16
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // TEST r/m32, imm32
                    MachineCodeTableEntry(false,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // TEST r/m64, imm32
                    MachineCodeTableEntry(true,
                        0xF7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // TEST r/m8, r8
                    MachineCodeTableEntry(false,
                        0x84,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    // TEST r/m16, r16
                    MachineCodeTableEntry(false,
                        0x85,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    // TEST r/m32, r32
                    MachineCodeTableEntry(false,
                        0x85,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    // TEST r/m64, r64
                    MachineCodeTableEntry(true,
                        0x85,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CMP,
                {
                    // CMP AL, imm8
                    MachineCodeTableEntry(false,
                        0x3C,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER8),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // CMP AX, imm16
                    MachineCodeTableEntry(false,
                        0x3D,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER16),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // CMP EAX, imm32
                    MachineCodeTableEntry(false,
                        0x3D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::LOWER32),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // CMP RAX, imm32
                    MachineCodeTableEntry(true,
                        0x3D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isSpecificGPRegister(Framework::Assembly::RAX,
                            Framework::Assembly::FULL64),
                        UNDEFINED,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // CMP r/m8, imm8
                    MachineCodeTableEntry(false,
                        0x80,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // CMP r/m16, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // CMP r/m32, imm8
                    MachineCodeTableEntry(false,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // CMP r/m64, imm8
                    MachineCodeTableEntry(true,
                        0x83,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // CMP r/m16, imm16
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // CMP r/m32, imm32
                    MachineCodeTableEntry(false,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // TEST r/m64, imm32
                    MachineCodeTableEntry(true,
                        0x81,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // CMP r/m8, r8
                    MachineCodeTableEntry(false,
                        0x38,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b111,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    // CMP r/m16, r16
                    MachineCodeTableEntry(false,
                        0x39,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    // CMP r/m32, r32
                    MachineCodeTableEntry(false,
                        0x39,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    // CMP r/m64, r64
                    MachineCodeTableEntry(true,
                        0x39,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    // CMP r8, r/m8
                    MachineCodeTableEntry(false,
                        0x3A,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    //	CMP r16, r/m16
                    MachineCodeTableEntry(false,
                        0x3B,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    //	CMP r32, r/m32
                    MachineCodeTableEntry(false,
                        0x3B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    //	CMP r64, r/m64
                    MachineCodeTableEntry(true,
                        0x3B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CMPPD,
                {
                    // CMPPD xmm1, xmm2/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // VCMPPD xmm1, xmm2, xmm3/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // VCMPPD ymm1, ymm2, ymm3/m256, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CMPPS,
                {
                    // CMPPS xmm1, xmm2/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // VCMPPS xmm1, xmm2, xmm3/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b00,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // VCMPPS ymm1, ymm2, ymm3/m256, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b00,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CMPSD,
                {
                    // CMPSD xmm1, xmm2/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // VCMPSD xmm1, xmm2, xmm3/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b11,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CMPSS,
                {
                    // CMPSS xmm1, xmm2/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READWRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // VCMPSS xmm1, xmm2, xmm3/m128, imm8
                    MachineCodeTableEntry(false,
                        0xC20F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b10,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::COMISD,
                {// COMISD xmm1, xmm2/m64
                    MachineCodeTableEntry(false,
                        0x2F0F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::COMISS,
                {// COMISS xmm1, xmm2/m32
                    MachineCodeTableEntry(false,
                        0x2F0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READ,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MOV,
                {// MOV r/m8, r8
                    MachineCodeTableEntry(false,
                        0x88,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        WRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        READ),
                    // MOV r/m16, r16
                    MachineCodeTableEntry(false,
                        0x89,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        WRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        READ),
                    // MOV r/m32, r32
                    MachineCodeTableEntry(false,
                        0x89,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        WRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        READ),
                    // MOV r/m64, r64
                    MachineCodeTableEntry(true,
                        0x89,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        WRITE,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        READ),
                    // MOV r8, r/m8
                    MachineCodeTableEntry(false,
                        0x8A,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        READ),
                    // MOV r/m16, r16
                    MachineCodeTableEntry(false,
                        0x8B,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // MOV r/m32, r32
                    MachineCodeTableEntry(false,
                        0x8B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // MOV r/m64, r64
                    MachineCodeTableEntry(true,
                        0x8B,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // Move imm8 to r8
                    MachineCodeTableEntry(false,
                        0xB0,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        OPCODE_RD,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // MOV r16, imm16
                    MachineCodeTableEntry(false,
                        0xB8,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        OPCODE_RD,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // MOV r32, imm32
                    MachineCodeTableEntry(false,
                        0xB8,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        OPCODE_RD,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // MOV r64, imm64
                    MachineCodeTableEntry(true,
                        0xB8,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        OPCODE_RD,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::QWORD),
                        IMM64,
                        READ),
                    // MOV r/m8, imm8
                    MachineCodeTableEntry(false,
                        0xC6,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::BYTE),
                        MODRM_RM,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // MOV r/m16, imm16
                    MachineCodeTableEntry(false,
                        0xC7,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // MOV r/m32, imm32
                    MachineCodeTableEntry(false,
                        0xC7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // MOV r/m64, imm64
                    MachineCodeTableEntry(true,
                        0xC7,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        WRITE,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MOVUPD,
                {
                    // MOVUPD xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // MOVUPD xmm2/m128, xmm1
                    MachineCodeTableEntry(false,
                        0x110F,
                        (char)2,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READ),
                    // VMOVUPD ymm1, ymm2/m256
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                    // VMOVUPD ymm2/m256, ymm1
                    MachineCodeTableEntry(false,
                        0x110F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b01,
                        0,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MOVUPS,
                {
                    // MOVUPS xmm1, xmm2/m128
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                    // MOVUPS xmm2/m128, xmm1
                    MachineCodeTableEntry(false,
                        0x110F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READ),
                    // VMOVUPS ymm1, ymm2/m256
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b00,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        READ),
                    // VMOVUPS ymm2/m256, ymm1
                    MachineCodeTableEntry(false,
                        0x110F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        true,
                        0b00,
                        0,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_RM,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M256),
                        MODRM_REG,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MOVSD,
                {
                    // MOVSD xmm1, xmm2/m64
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // MOVSD xmm2/m128, xmm1
                    MachineCodeTableEntry(false,
                        0x110F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READ),
                    // VMOVSD VMOVSD xmm1, xmm2, xmm3
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b11,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::MOVSS,
                {
                    // MOVSS xmm1, xmm2/m32
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // MOVSS xmm2/m128, xmm1
                    MachineCodeTableEntry(false,
                        0x110F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        READ),
                    // VMOVSS VMOVSD xmm1, xmm2, xmm3
                    MachineCodeTableEntry(false,
                        0x100F,
                        (char)2,
                        NO_PREFIX,
                        true,
                        false,
                        0b10,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        VEX_VVVV,
                        READ,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::LEA,
                {
                    // LEA r16,m
                    MachineCodeTableEntry(
                        false,
                        0x8D,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_REG,
                        WRITE,
                        [](const Framework::Assembly::OperationArgument& p) {
                            return p.asMemoryAccessArgument();
                        },
                        MODRM_RM,
                        READ),
                    // LEA r32,m
                    MachineCodeTableEntry(
                        false,
                        0x8D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        WRITE,
                        [](const Framework::Assembly::OperationArgument& p) {
                            return p.asMemoryAccessArgument();
                        },
                        MODRM_RM,
                        READ),
                    // LEA r64,m
                    MachineCodeTableEntry(
                        true,
                        0x8D,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        WRITE,
                        [](const Framework::Assembly::OperationArgument& p) {
                            return p.asMemoryAccessArgument();
                        },
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CVTSI2SD,
                {
                    // CVTSI2SD xmm1, r32/m32
                    MachineCodeTableEntry(false,
                        0x2A0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // CVTSI2SD xmm1, r64/m64
                    MachineCodeTableEntry(true,
                        0x2A0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CVTTSD2SI,
                {
                    // CVTTSD2SI r32, xmm1/m64
                    MachineCodeTableEntry(false,
                        0x2C0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // CVTTSD2SI r64, xmm1/m64
                    MachineCodeTableEntry(true,
                        0x2C0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CVTTSS2SI,
                {
                    // CVTTSS2SI r32, xmm1/m32
                    MachineCodeTableEntry(false,
                        0x2C0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // CVTTSS2SI r64, xmm1/m32
                    MachineCodeTableEntry(true,
                        0x2C0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CVTSD2SI,
                {
                    // CVTSD2SI r32, xmm1/m64
                    MachineCodeTableEntry(false,
                        0x2D0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // CVTSD2SI r64, xmm1/m64
                    MachineCodeTableEntry(true,
                        0x2D0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CVTSS2SI,
                {
                    // CVTSS2SI r32, xmm1/m32
                    MachineCodeTableEntry(false,
                        0x2D0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // CVTSS2SI r64, xmm1/m32
                    MachineCodeTableEntry(true,
                        0x2D0F,
                        (char)2,
                        XF3,
                        false,
                        false,
                        0,
                        0,
                        isGPRegister(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_REG,
                        WRITE,
                        isFPRegisterOrMEmoryAccess(
                            Framework::Assembly::MemoryBlockSize::M128,
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CVTSI2SS,
                {
                    // CVTSI2SS xmm1, r32/m32
                    MachineCodeTableEntry(false,
                        0x2A0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::DWORD),
                        MODRM_RM,
                        READ),
                    // CVTSI2SS xmm1, r64/m64
                    MachineCodeTableEntry(true,
                        0x2A0F,
                        (char)2,
                        XF2,
                        false,
                        false,
                        0,
                        0,
                        isFPRegister(
                            Framework::Assembly::MemoryBlockSize::M128),
                        MODRM_REG,
                        WRITE,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JMP,
                1,
                {// JMP rel32
                    MachineCodeTableEntry(false,
                        0xE9,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JZ,
                2,
                {// JZ rel32
                    MachineCodeTableEntry(false,
                        0x840F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JNZ,
                2,
                {// JNZ rel32
                    MachineCodeTableEntry(false,
                        0x850F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JG,
                2,
                {// JG rel32
                    MachineCodeTableEntry(false,
                        0x8F0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JGE,
                2,
                {// JGE rel32
                    MachineCodeTableEntry(false,
                        0x8D0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JL,
                2,
                {// JL rel32
                    MachineCodeTableEntry(false,
                        0x8C0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JLE,
                2,
                {// JLE rel32
                    MachineCodeTableEntry(false,
                        0x8E0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JA,
                2,
                {// JA rel32
                    MachineCodeTableEntry(false,
                        0x870F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JC,
                2,
                {// JC rel32
                    MachineCodeTableEntry(false,
                        0x820F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JNC,
                2,
                {// JNC rel32
                    MachineCodeTableEntry(false,
                        0x830F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JBE,
                2,
                {// JBE rel32
                    MachineCodeTableEntry(false,
                        0x860F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JO,
                2,
                {// JO rel32
                    MachineCodeTableEntry(false,
                        0x800F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JNO,
                2,
                {// JNO rel32
                    MachineCodeTableEntry(false,
                        0x810F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JP,
                2,
                {// JP rel32
                    MachineCodeTableEntry(false,
                        0x8A0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JNP,
                2,
                {// JNP rel32
                    MachineCodeTableEntry(false,
                        0x8B0F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JS,
                2,
                {// JS rel32
                    MachineCodeTableEntry(false,
                        0x880F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new JumpOperationCodeTable(Framework::Assembly::JNS,
                2,
                {// JNS rel32
                    MachineCodeTableEntry(false,
                        0x890F,
                        (char)2,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::CALL,
                {// CALL rel32
                    MachineCodeTableEntry(false,
                        0xE8,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                    // CALL r/m64
                    MachineCodeTableEntry(false,
                        0xFF,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b010,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::RET,
                {// RET
                    MachineCodeTableEntry(
                        false, 0xC3, (char)1, NO_PREFIX, false, false, 0, 0)}));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::PUSH,
                {
                    // PUSH r/m16
                    MachineCodeTableEntry(false,
                        0xFF,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // PUSH r/m64
                    MachineCodeTableEntry(false,
                        0xFF,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0b110,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                    // PUSH imm8
                    MachineCodeTableEntry(false,
                        0x6A,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::BYTE),
                        IMM8,
                        READ),
                    // PUSH imm16
                    MachineCodeTableEntry(false,
                        0x68,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::WORD),
                        IMM16,
                        READ),
                    // PUSH imm32
                    MachineCodeTableEntry(false,
                        0x68,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isIMM(Framework::Assembly::MemoryBlockSize::DWORD),
                        IMM32,
                        READ),
                }));
        OperationCodeTable::machineCodeTranslationTable.add(
            new OperationCodeTable(Framework::Assembly::POP,
                {
                    // POP r/m16
                    MachineCodeTableEntry(false,
                        0x8F,
                        (char)1,
                        X66,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::WORD),
                        MODRM_RM,
                        READ),
                    // POP r/m64
                    MachineCodeTableEntry(false,
                        0x8F,
                        (char)1,
                        NO_PREFIX,
                        false,
                        false,
                        0,
                        0,
                        isGPRegisterOrMemoryAccess(
                            Framework::Assembly::MemoryBlockSize::QWORD),
                        MODRM_RM,
                        READ),
                }));
    }
}

bool Framework::Assembly::OperationArgument::usesRegister(GPRegister reg) const
{
    return false;
}

bool Framework::Assembly::OperationArgument::usesRegister(FPRegister reg) const
{
    return false;
}

void Framework::Assembly::OperationArgument::replaceRegister(
    GPRegister oldReg, GPRegister newReg)
{}

void Framework::Assembly::OperationArgument::replaceRegister(
    FPRegister oldReg, FPRegister newReg)
{}

void Framework::Assembly::OperationArgument::addJumpLabelPrefix(
    Text labelPrefix)
{}

const Framework::Assembly::GPRegisterArgument*
Framework::Assembly::OperationArgument::asGPRegisterArgument() const
{
    return dynamic_cast<const GPRegisterArgument*>(this);
}

const Framework::Assembly::MemoryAccessArgument*
Framework::Assembly::OperationArgument::asMemoryAccessArgument() const
{
    return dynamic_cast<const MemoryAccessArgument*>(this);
}

const Framework::Assembly::ConstantArgument*
Framework::Assembly::OperationArgument::asConstantArgument() const
{
    return dynamic_cast<const ConstantArgument*>(this);
}

const Framework::Assembly::FPRegisterArgument*
Framework::Assembly::OperationArgument::asFPRegisterArgument() const
{
    return dynamic_cast<const FPRegisterArgument*>(this);
}

const Framework::Assembly::JumpTargetArgument*
Framework::Assembly::OperationArgument::asJumpTargetArgument() const
{
    return dynamic_cast<const JumpTargetArgument*>(this);
}

Framework::Assembly::GPRegisterArgument::GPRegisterArgument(
    GPRegister reg, GPRegisterPart part)
    : reg(reg),
      part(part)
{}

bool Framework::Assembly::GPRegisterArgument::usesRegister(GPRegister reg) const
{
    return this->reg == reg;
}

void Framework::Assembly::GPRegisterArgument::replaceRegister(
    GPRegister oldReg, GPRegister newReg)
{
    if (reg == oldReg)
    {
        reg = newReg;
    }
}

Framework::Assembly::GPRegister
Framework::Assembly::GPRegisterArgument::getRegister() const
{
    return reg;
}

Framework::Assembly::GPRegisterPart
Framework::Assembly::GPRegisterArgument::getPart() const
{
    return part;
}

Framework::Assembly::FPRegisterArgument::FPRegisterArgument(
    FPRegister reg, FPRegisterPart part)
    : reg(reg),
      part(part)
{}

bool Framework::Assembly::FPRegisterArgument::usesRegister(FPRegister reg) const
{
    return this->reg == reg;
}

void Framework::Assembly::FPRegisterArgument::replaceRegister(
    FPRegister oldReg, FPRegister newReg)
{
    if (reg == oldReg)
    {
        reg = newReg;
    }
}

Framework::Assembly::FPRegister
Framework::Assembly::FPRegisterArgument::getRegister() const
{
    return reg;
}

Framework::Assembly::FPRegisterPart
Framework::Assembly::FPRegisterArgument::getPart() const
{
    return part;
}

Framework::Assembly::MemoryAccessArgument::MemoryAccessArgument(
    MemoryBlockSize blockSize,
    GPRegister address,
    bool useAddressReg,
    int offset,
    bool useOffsetReg,
    GPRegister offsetReg)
    : blockSize(blockSize),
      useAddressReg(useAddressReg),
      address(address),
      offset(offset),
      offsetReg(offsetReg),
      useOffsetReg(useOffsetReg)
{}

bool Framework::Assembly::MemoryAccessArgument::usesRegister(
    GPRegister reg) const
{
    return (useAddressReg && this->address == reg)
        || (useOffsetReg && offsetReg == reg);
}

void Framework::Assembly::MemoryAccessArgument::replaceRegister(
    GPRegister oldReg, GPRegister newReg)
{
    if (useAddressReg && address == oldReg)
    {
        address = newReg;
    }
    if (useOffsetReg && offsetReg == oldReg)
    {
        offsetReg = newReg;
    }
}

bool Framework::Assembly::MemoryAccessArgument::isUsingAddressRegister() const
{
    return useAddressReg;
}

Framework::Assembly::GPRegister
Framework::Assembly::MemoryAccessArgument::getAddressRegister() const
{
    return address;
}

int Framework::Assembly::MemoryAccessArgument::getOffset() const
{
    return offset;
}

bool Framework::Assembly::MemoryAccessArgument::isUsingOffsetRegister() const
{
    return useOffsetReg;
}

Framework::Assembly::GPRegister
Framework::Assembly::MemoryAccessArgument::getOffsetRegister() const
{
    return offsetReg;
}

Framework::Assembly::MemoryBlockSize
Framework::Assembly::MemoryAccessArgument::getBlockSize() const
{
    return blockSize;
}

Framework::Assembly::ConstantArgument::ConstantArgument(
    __int64 value, MemoryBlockSize size)
    : value(value),
      size(size)
{}

Framework::Assembly::ConstantArgument::ConstantArgument(
    int value, MemoryBlockSize size)
    : value((__int64)value),
      size(size)
{}

Framework::Assembly::ConstantArgument::ConstantArgument(
    short value, MemoryBlockSize size)
    : value((__int64)value),
      size(size)
{}

Framework::Assembly::ConstantArgument::ConstantArgument(
    char value, MemoryBlockSize size)
    : value((__int64)value),
      size(size)
{}

__int64 Framework::Assembly::ConstantArgument::getValue() const
{
    return value;
}

Framework::Assembly::MemoryBlockSize
Framework::Assembly::ConstantArgument::getSize() const
{
    return size;
}

Framework::Assembly::JumpTargetArgument::JumpTargetArgument(Text name)
    : name(name)
{}

void Framework::Assembly::JumpTargetArgument::addJumpLabelPrefix(
    Text labelPrefix)
{
    name = labelPrefix + name;
}

const Framework::Text& Framework::Assembly::JumpTargetArgument::getLabel() const
{
    return name;
}

Framework::Assembly::Instruction::Instruction(
    Operation op, std::initializer_list<OperationArgument*> args)
    : Instruction(op, args, {}, {}, {}, {})
{}

Framework::Assembly::Instruction::Instruction(Operation op,
    std::initializer_list<OperationArgument*> params,
    std::initializer_list<GPRegister> implicitReadGPs,
    std::initializer_list<FPRegister> implicitReadFPs,
    std::initializer_list<GPRegister> implicitWriteGPs,
    std::initializer_list<FPRegister> implicitWriteFPs)
    : ReferenceCounter(),
      op(op),
      args(params),
      implicitReadGPs(implicitReadGPs),
      implicitReadFPs(implicitReadFPs),
      implicitWriteGPs(implicitWriteGPs),
      implicitWriteFPs(implicitWriteFPs)
{}

Framework::Assembly::Instruction::~Instruction()
{
    for (auto arg : args)
    {
        delete arg;
    }
}

bool Framework::Assembly::Instruction::writesToRegister(
    GPRegister reg, const AssemblyBlock* block) const
{
    for (GPRegister r : implicitWriteGPs)
    {
        if (r == reg)
        {
            return 0;
        }
    }
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeTableEntry* entry
                = tableEntry->getEntry(args, block, this, err);
            if (entry)
            {
                for (GPRegister r : entry->getImpliedWriteGPRegs())
                {
                    if (r == reg)
                    {
                        return 1;
                    }
                }
                int index = 0;
                for (const OperationArgument* arg : args)
                {
                    OperandRW rw = entry->getOperandRW(index);
                    if (rw == WRITE || rw == READWRITE)
                    {
                        if (arg->asGPRegisterArgument()
                            && arg->asGPRegisterArgument()->getRegister()
                                   == reg)
                        {
                            return 1;
                        }
                    }
                    index++;
                }
            }
        }
    }
    return 0;
}

bool Framework::Assembly::Instruction::writesToRegister(
    FPRegister reg, const AssemblyBlock* block) const
{
    for (FPRegister r : implicitWriteFPs)
    {
        if (r == reg)
        {
            return 0;
        }
    }
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeTableEntry* entry
                = tableEntry->getEntry(args, block, this, err);
            if (entry)
            {
                for (FPRegister r : entry->getImpliedWriteFPRegs())
                {
                    if (r == reg)
                    {
                        return 1;
                    }
                }
                int index = 0;
                for (const OperationArgument* arg : args)
                {
                    OperandRW rw = entry->getOperandRW(index);
                    if (rw == WRITE || rw == READWRITE)
                    {
                        if (arg->asFPRegisterArgument()
                            && arg->asFPRegisterArgument()->getRegister()
                                   == reg)
                        {
                            return 1;
                        }
                    }
                    index++;
                }
            }
        }
    }
    return 0;
}

bool Framework::Assembly::Instruction::readsFromRegister(
    GPRegister reg, const AssemblyBlock* block) const
{
    for (GPRegister r : implicitReadGPs)
    {
        if (r == reg)
        {
            return 0;
        }
    }
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeTableEntry* entry
                = tableEntry->getEntry(args, block, this, err);
            if (entry)
            {
                for (GPRegister r : entry->getImpliedReadGPRegs())
                {
                    if (r == reg)
                    {
                        return 1;
                    }
                }
                int index = 0;
                for (const OperationArgument* arg : args)
                {
                    OperandRW rw = entry->getOperandRW(index);
                    if (rw == READ || rw == READWRITE)
                    {
                        if (arg->asGPRegisterArgument()
                            && arg->asGPRegisterArgument()->getRegister()
                                   == reg)
                        {
                            return 1;
                        }
                    }
                    if (arg->asMemoryAccessArgument()
                        && arg->asMemoryAccessArgument()->usesRegister(reg))
                    {
                        return 1;
                    }
                    index++;
                }
            }
        }
    }
    return 0;
}

bool Framework::Assembly::Instruction::readsFromRegister(
    FPRegister reg, const AssemblyBlock* block) const
{
    for (FPRegister r : implicitReadFPs)
    {
        if (r == reg)
        {
            return 0;
        }
    }
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeTableEntry* entry
                = tableEntry->getEntry(args, block, this, err);
            if (entry)
            {
                for (FPRegister r : entry->getImpliedReadFPRegs())
                {
                    if (r == reg)
                    {
                        return 1;
                    }
                }
                int index = 0;
                for (const OperationArgument* arg : args)
                {
                    OperandRW rw = entry->getOperandRW(index);
                    if (rw == READ || rw == READWRITE)
                    {
                        if (arg->asFPRegisterArgument()
                            && arg->asFPRegisterArgument()->getRegister()
                                   == reg)
                        {
                            return 1;
                        }
                    }
                    index++;
                }
            }
        }
    }
    return 0;
}

bool Framework::Assembly::Instruction::isReplacementPossible(
    GPRegister oldReg, GPRegister newReg, const AssemblyBlock* block) const
{
    for (GPRegister r : implicitReadGPs)
    {
        if (r == oldReg)
        {
            return 0;
        }
    }
    for (GPRegister r : implicitWriteGPs)
    {
        if (r == oldReg)
        {
            return 0;
        }
    }
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeTableEntry* entry
                = tableEntry->getEntry(args, block, this, err);
            if (entry)
            {
                for (GPRegister r : entry->getImpliedReadGPRegs())
                {
                    if (r == oldReg)
                    {
                        return 0;
                    }
                }
                for (GPRegister r : entry->getImpliedWriteGPRegs())
                {
                    if (r == oldReg)
                    {
                        return 0;
                    }
                }
            }
        }
    }
    if (this->readsFromRegister(newReg, block)
        || this->writesToRegister(newReg, block))
    {
        return 0;
    }
    if (newReg == RBP || newReg == RSI || newReg == RDI)
    {
        if (oldReg == RBP || oldReg == RSI || oldReg == RDI)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    if (newReg >= R8)
    {
        return oldReg >= R8;
    }
    return oldReg < R8;
}

bool Framework::Assembly::Instruction::isReplacementPossible(
    FPRegister oldReg, FPRegister newReg, const AssemblyBlock* block) const
{
    for (FPRegister r : implicitReadFPs)
    {
        if (r == oldReg)
        {
            return 0;
        }
    }
    for (FPRegister r : implicitWriteFPs)
    {
        if (r == oldReg)
        {
            return 0;
        }
    }
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeTableEntry* entry
                = tableEntry->getEntry(args, block, this, err);
            if (entry)
            {
                for (FPRegister r : entry->getImpliedReadFPRegs())
                {
                    if (r == oldReg)
                    {
                        return 0;
                    }
                }
                for (FPRegister r : entry->getImpliedWriteFPRegs())
                {
                    if (r == oldReg)
                    {
                        return 0;
                    }
                }
            }
        }
    }
    if (this->readsFromRegister(newReg, block)
        || this->writesToRegister(newReg, block))
    {
        return 0;
    }
    return 1;
}

void Framework::Assembly::Instruction::replaceRegister(
    GPRegister oldReg, GPRegister newReg)
{
    for (auto arg : args)
    {
        arg->replaceRegister(oldReg, newReg);
    }
}

void Framework::Assembly::Instruction::replaceRegister(
    FPRegister oldReg, FPRegister newReg)
{
    for (auto arg : args)
    {
        arg->replaceRegister(oldReg, newReg);
    }
}

void Framework::Assembly::Instruction::addJumpLabelPrefix(Text labelPrefix)
{
    for (auto arg : args)
    {
        arg->addJumpLabelPrefix(labelPrefix);
    }
}

void Framework::Assembly::Instruction::compile(
    StreamWriter* byteCodeWriter, const AssemblyBlock* block) const
{
    if (op == NOP)
    {
        return;
    }
    Framework::Text err;
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            MachineCodeInstruction instr
                = tableEntry->getInstruction(args, block, this, err);
            if (err.getLength())
            {
                throw err;
            }
            instr.write(*byteCodeWriter);
            return;
        }
    }
    err.append() << "Failed to compile instruction: operation code " << (int)op
                 << " not found in translation table. args: \n";
    for (auto arg : args)
    {
        err.append() << "  " << typeid(*arg).name() << "\n";
    }
    throw err;
}

bool Framework::Assembly::Instruction::isValid(const AssemblyBlock* block) const
{
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            tableEntry->getInstruction(args, block, this, err);
            return err.getLength() == 0;
        }
    }
    return false;
}

int Framework::Assembly::Instruction::compiledSize(
    const AssemblyBlock* block) const
{
    __intializeMachineCodeTranslationTable();
    for (OperationCodeTable* tableEntry :
        OperationCodeTable::machineCodeTranslationTable)
    {
        if (tableEntry->getOperation() == op)
        {
            Framework::Text err;
            MachineCodeInstruction instr
                = tableEntry->getInstruction(args, block, this, err);
            if (err.getLength())
            {
                throw err;
            }
            return instr.calculateSize();
        }
    }
    return 0;
}

Framework::Assembly::Operation
Framework::Assembly::Instruction::getOperation() const
{
    return op;
}

bool Framework::Assembly::Instruction::definesLabel(Text label) const
{
    return op == NOP && args.size() == 1 && args.at(0)->asJumpTargetArgument()
        && args.at(0)->asJumpTargetArgument()->getLabel().istGleich(label);
}

const std::vector<Framework::Assembly::OperationArgument*>&
Framework::Assembly::Instruction::getArguments() const
{
    return args;
}

Framework::Assembly::AssemblyBlock::AssemblyBlock()
    : inlineIndex(0),
      compiledCode(0)
{}

Framework::Assembly::AssemblyBlock::~AssemblyBlock()
{
    if (compiledCode != 0)
    {
        // Free the compiled code memory
        VirtualFree(compiledCode, 0, MEM_RELEASE);
    }
}

void Framework::Assembly::AssemblyBlock::addInstruction(Instruction* instr)
{
    instructions.add(instr);
}

void Framework::Assembly::AssemblyBlock::defineJumpTarget(Text name)
{
    instructions.add(new Instruction(NOP, {new JumpTargetArgument(name)}));
}

void Framework::Assembly::AssemblyBlock::addJump(
    Operation jumpOp, Text targetName)
{
    instructions.add(
        new Instruction(jumpOp, {new JumpTargetArgument(targetName)}));
}

void Framework::Assembly::AssemblyBlock::addAddition(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(ADD,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addAddition(
    GPRegister target, char value, GPRegisterPart part)
{
    instructions.add(new Instruction(ADD,
        {new GPRegisterArgument(target, part), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addAddition(
    GPRegister target, int value, GPRegisterPart part)
{
    instructions.add(new Instruction(ADD,
        {new GPRegisterArgument(target, part), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addAddition(
    FPRegister target, FPRegister source, FPDataType type, FPRegisterPart part)
{
    Operation op = NOP;
    switch (type)
    {
    case SINGLE_FLOAT:
        op = ADDSS;
        break;
    case SINGLE_DOUBLE:
        op = ADDSD;
        break;
    case PACKED_FLOAT:
        op = ADDPS;
        break;
    case PACKED_DOUBLE:
        op = ADDPD;
        break;
    }
    instructions.add(new Instruction(op,
        {new FPRegisterArgument(target, part),
            new FPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addSubtraction(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(SUB,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addSubtraction(
    FPRegister target, FPRegister source, FPDataType type, FPRegisterPart part)
{
    Operation op = NOP;
    switch (type)
    {
    case SINGLE_FLOAT:
        op = SUBSS;
        break;
    case SINGLE_DOUBLE:
        op = SUBSD;
        break;
    case PACKED_FLOAT:
        op = SUBPS;
        break;
    case PACKED_DOUBLE:
        op = SUBPD;
        break;
    }
    instructions.add(new Instruction(op,
        {new FPRegisterArgument(target, part),
            new FPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addMultiplication(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(IMUL,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addMultiplication(
    FPRegister target, FPRegister source, FPDataType type, FPRegisterPart part)
{
    Operation op = NOP;
    switch (type)
    {
    case SINGLE_FLOAT:
        op = MULSS;
        break;
    case SINGLE_DOUBLE:
        op = MULSD;
        break;
    case PACKED_FLOAT:
        op = MULPS;
        break;
    case PACKED_DOUBLE:
        op = MULPD;
        break;
    }
    instructions.add(new Instruction(op,
        {new FPRegisterArgument(target, part),
            new FPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addDivision(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(DIV,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addDivision(
    FPRegister target, FPRegister source, FPDataType type, FPRegisterPart part)
{
    Operation op = NOP;
    switch (type)
    {
    case SINGLE_FLOAT:
        op = DIVSS;
        break;
    case SINGLE_DOUBLE:
        op = DIVSD;
        break;
    case PACKED_FLOAT:
        op = DIVPS;
        break;
    case PACKED_DOUBLE:
        op = DIVPD;
        break;
    }
    instructions.add(new Instruction(op,
        {new FPRegisterArgument(target, part),
            new FPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addTest(
    GPRegister r1, GPRegister r2, GPRegisterPart part)
{
    instructions.add(new Instruction(TEST,
        {new GPRegisterArgument(r1, part), new GPRegisterArgument(r2, part)}));
}

void Framework::Assembly::AssemblyBlock::addCompare(
    GPRegister r1, GPRegister r2, GPRegisterPart part)
{
    instructions.add(new Instruction(CMP,
        {new GPRegisterArgument(r1, part), new GPRegisterArgument(r2, part)}));
}

void Framework::Assembly::AssemblyBlock::addCompare(GPRegister r1, char value)
{
    instructions.add(new Instruction(CMP,
        {new GPRegisterArgument(r1, LOWER8), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addCompare(GPRegister r1, short value)
{
    instructions.add(new Instruction(CMP,
        {new GPRegisterArgument(r1, LOWER16), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addCompare(GPRegister r1, int value)
{
    instructions.add(new Instruction(CMP,
        {new GPRegisterArgument(r1, LOWER32), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addCompare(
    FPRegister r1, FPRegister r2, FPDataType type)
{
    Operation op = NOP;
    switch (type)
    {
    case SINGLE_FLOAT:
        op = COMISS;
        break;
    case SINGLE_DOUBLE:
        op = COMISD;
        break;
    }
    if (op != NOP)
    {
        instructions.add(new Instruction(op,
            {new FPRegisterArgument(r1, FPRegisterPart::X),
                new FPRegisterArgument(r2, FPRegisterPart::X)}));
    }
}

void Framework::Assembly::AssemblyBlock::addAnd(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(AND,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addOr(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(OR,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    char* valueAddress, GPRegister target)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target),
            new ConstantArgument(reinterpret_cast<__int64>(valueAddress))}));
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, LOWER8),
            new MemoryAccessArgument(MemoryBlockSize::BYTE, target)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    short* valueAddress, GPRegister target)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target),
            new ConstantArgument(reinterpret_cast<__int64>(valueAddress))}));
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, LOWER16),
            new MemoryAccessArgument(MemoryBlockSize::WORD, target)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    int* valueAddress, GPRegister target)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target),
            new ConstantArgument(reinterpret_cast<__int64>(valueAddress))}));
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, LOWER32),
            new MemoryAccessArgument(MemoryBlockSize::DWORD, target)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    __int64* valueAddress, GPRegister target)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target),
            new ConstantArgument(reinterpret_cast<__int64>(valueAddress))}));
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target),
            new MemoryAccessArgument(MemoryBlockSize::QWORD, target)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    GPRegister addressRegister,
    GPRegister target,
    GPRegisterPart targetPart,
    int offset)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, targetPart),
            new MemoryAccessArgument(
                (targetPart == LOWER8 || targetPart == HIGHER8)
                    ? MemoryBlockSize::BYTE
                    : (targetPart == LOWER16
                              ? MemoryBlockSize::WORD
                              : (targetPart == LOWER32
                                        ? MemoryBlockSize::DWORD
                                        : MemoryBlockSize::QWORD)),
                addressRegister,
                true,
                offset)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    float* valueAddress, FPRegister target, GPRegister temp)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(temp),
            new ConstantArgument(reinterpret_cast<__int64>(valueAddress))}));
    instructions.add(new Instruction(MOVSS,
        {new FPRegisterArgument(target),
            new MemoryAccessArgument(MemoryBlockSize::DWORD, temp)}));
}

void Framework::Assembly::AssemblyBlock::addLoadValue(
    double* valueAddress, FPRegister target, GPRegister temp)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(temp),
            new ConstantArgument(reinterpret_cast<__int64>(valueAddress))}));
    instructions.add(new Instruction(MOVSD,
        {new FPRegisterArgument(target),
            new MemoryAccessArgument(MemoryBlockSize::QWORD, temp)}));
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    GPRegister target, char value)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, LOWER8), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    GPRegister target, short value)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, LOWER16),
            new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    GPRegister target, int value)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, LOWER32),
            new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    GPRegister target, __int64 value)
{
    instructions.add(new Instruction(
        MOV, {new GPRegisterArgument(target), new ConstantArgument(value)}));
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    FPRegister target, float value, GPRegister temp)
{
    int data = *reinterpret_cast<int*>(&value);
    addMoveValue(temp, data);
    addPush(temp);
    instructions.add(new Instruction(MOVSS,
        {new FPRegisterArgument(target, X),
            new MemoryAccessArgument(MemoryBlockSize::DWORD, RSP)}));
    addPop(temp);
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    FPRegister target, double value, GPRegister temp)
{
    __int64 data = *reinterpret_cast<__int64*>(&value);
    addMoveValue(temp, data);
    addPush(temp);
    instructions.add(new Instruction(MOVSD,
        {new FPRegisterArgument(target, X),
            new MemoryAccessArgument(MemoryBlockSize::QWORD, RSP)}));
    addPop(temp);
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    GPRegister target, GPRegister source, GPRegisterPart part)
{
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(target, part),
            new GPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addMoveValue(
    FPRegister target, FPRegister source, FPDataType type, FPRegisterPart part)
{
    Operation op = NOP;
    switch (type)
    {
    case SINGLE_FLOAT:
        op = MOVSS;
        break;
    case SINGLE_DOUBLE:
        op = MOVSD;
        break;
    case PACKED_FLOAT:
        op = MOVUPS;
        break;
    case PACKED_DOUBLE:
        op = MOVUPD;
        break;
    }
    instructions.add(new Instruction(op,
        {new FPRegisterArgument(target, part),
            new FPRegisterArgument(source, part)}));
}

void Framework::Assembly::AssemblyBlock::addConversion(GPRegister target,
    FPRegister source,
    FPDataType type,
    GPRegisterPart targetPart,
    bool round)
{
    Operation op = NOP;
    if (type == SINGLE_DOUBLE)
    {
        op = round ? CVTSD2SI : CVTTSD2SI;
    }
    else if (type == SINGLE_FLOAT)
    {
        op = round ? CVTSS2SI : CVTTSS2SI;
    }
    instructions.add(new Instruction(op,
        {new GPRegisterArgument(target, targetPart),
            new FPRegisterArgument(source, X)}));
}

void Framework::Assembly::AssemblyBlock::addConversion(FPRegister target,
    GPRegister source,
    FPDataType targetType,
    GPRegisterPart sourcePart)
{
    Operation op = NOP;
    if (targetType == SINGLE_DOUBLE)
    {
        op = CVTSI2SD;
    }
    else if (targetType == SINGLE_FLOAT)
    {
        op = CVTSI2SS;
    }
    instructions.add(new Instruction(op,
        {new FPRegisterArgument(target, X),
            new GPRegisterArgument(source, sourcePart)}));
}

void Framework::Assembly::AssemblyBlock::addCall(void* functionAddress,
    FuncReturnType returnType,
    std::initializer_list<GPRegister> gpParams,
    std::initializer_list<FPRegister> fpParams,
    GPRegister temp,
    GPRegister bpTemp)
{
    if (isVolatile(bpTemp) || bpTemp == RSP)
    {
        throw "Temporary register for base pointer must be a non-volatile "
              "register (not RAX, RCX, RDX, R8, R9, R10, R11) and not RSP";
    }
    // enshure calling conventions
    // save stack pointer value to bpTemp
    addMoveValue(bpTemp, RSP);
    // align stack pointer to 16 bytes
    instructions.add(new Instruction(
        AND, {new GPRegisterArgument(RSP), new ConstantArgument(-16)}));
    // allocate shadow space
    instructions.add(new Instruction(
        SUB, {new GPRegisterArgument(RSP), new ConstantArgument(32)}));

    // load function address into temp register
    instructions.add(new Instruction(MOV,
        {new GPRegisterArgument(temp),
            new ConstantArgument(reinterpret_cast<__int64>(functionAddress))}));
    // call the function
    if (returnType == INT_VALUE)
    {
        instructions.add(new Instruction(CALL,
            {new GPRegisterArgument(temp)},
            gpParams,
            fpParams,
            {RAX},
            {}));
    }
    else if (returnType == FLOAT_VALUE)
    {
        instructions.add(new Instruction(CALL,
            {new GPRegisterArgument(temp)},
            gpParams,
            fpParams,
            {},
            {MM0}));
    }
    else
    {
        instructions.add(new Instruction(
            CALL, {new GPRegisterArgument(temp)}, gpParams, fpParams, {}, {}));
    }
    // restore stack pointer
    addMoveValue(RSP, bpTemp);
}

void Framework::Assembly::AssemblyBlock::addReturn()
{
    instructions.add(new Instruction(RET, {}));
}

void Framework::Assembly::AssemblyBlock::addPush(
    GPRegister reg, GPRegisterPart part)
{
    GPRegisterPart pushPart = part;
    if (part == LOWER8 || part == HIGHER8)
    {
        pushPart = LOWER16;
    }
    if (part == LOWER32)
    {
        pushPart = FULL64;
    }
    instructions.add(
        new Instruction(PUSH, {new GPRegisterArgument(reg, pushPart)}));
}

void Framework::Assembly::AssemblyBlock::addPop(
    GPRegister reg, GPRegisterPart part)
{
    GPRegisterPart popPart = part;
    if (part == LOWER8 || part == HIGHER8)
    {
        popPart = LOWER16;
    }
    if (part == LOWER32)
    {
        popPart = FULL64;
    }
    instructions.add(
        new Instruction(POP, {new GPRegisterArgument(reg, popPart)}));
}

void Framework::Assembly::AssemblyBlock::addPush(
    FPRegister reg, FPDataType type, FPRegisterPart part)
{
    MemoryBlockSize size;
    int bytes;
    Operation moveOp;
    switch (type)
    {
    case SINGLE_DOUBLE:
        moveOp = MOVSD;
        bytes = 8;
        size = MemoryBlockSize::QWORD;
        part = X;
        break;
    case SINGLE_FLOAT:
        moveOp = MOVSS;
        bytes = 4;
        size = MemoryBlockSize::DWORD;
        part = X;
        break;
    case PACKED_DOUBLE:
        moveOp = MOVUPD;
        bytes = part == X ? 16 : 32;
        size = part == X ? MemoryBlockSize::M128 : MemoryBlockSize::M256;
    case PACKED_FLOAT:
        moveOp = MOVUPS;
        bytes = part == X ? 16 : 32;
        size = part == X ? MemoryBlockSize::M128 : MemoryBlockSize::M256;
    }
    instructions.add(new Instruction(
        SUB, {new GPRegisterArgument(RSP), new ConstantArgument(bytes)}));
    instructions.add(new Instruction(moveOp,
        {new MemoryAccessArgument(size, RSP),
            new FPRegisterArgument(reg, part)}));
}

void Framework::Assembly::AssemblyBlock::addPop(
    FPRegister reg, FPDataType type, FPRegisterPart part)
{
    addPop(instructions, reg, type, part);
}

void Framework::Assembly::AssemblyBlock::addPop(
    RCArray<Instruction>& instructionList,
    FPRegister reg,
    FPDataType type,
    FPRegisterPart part)
{
    MemoryBlockSize size;
    int bytes;
    Operation moveOp;
    switch (type)
    {
    case SINGLE_DOUBLE:
        moveOp = MOVSD;
        bytes = 8;
        size = MemoryBlockSize::QWORD;
        part = X;
        break;
    case SINGLE_FLOAT:
        moveOp = MOVSS;
        bytes = 4;
        size = MemoryBlockSize::DWORD;
        part = X;
        break;
    case PACKED_DOUBLE:
        moveOp = MOVUPD;
        bytes = part == X ? 16 : 32;
        size = part == X ? MemoryBlockSize::M128 : MemoryBlockSize::M256;
    case PACKED_FLOAT:
        moveOp = MOVUPS;
        bytes = part == X ? 16 : 32;
        size = part == X ? MemoryBlockSize::M128 : MemoryBlockSize::M256;
    }
    instructionList.add(new Instruction(moveOp,
        {new FPRegisterArgument(reg, part),
            new MemoryAccessArgument(size, RSP)}));
    instructionList.add(new Instruction(
        ADD, {new GPRegisterArgument(RSP), new ConstantArgument(bytes)}));
}

void Framework::Assembly::AssemblyBlock::addBlock(AssemblyBlock* block,
    std::initializer_list<GPRegister> preservedGPRegisters,
    std::initializer_list<FPRegister> preservedFPRegisters,
    std::initializer_list<FPDataType> preservedFPDataTypes,
    GPRegister* blockResultGpReg,
    FPRegister* blockResultFpReg)
{
    std::vector<FPDataType> fpTypes(preservedFPDataTypes);
    bool containsCall = false;
    for (const auto& instr : block->instructions)
    {
        if (instr->getOperation() == CALL)
        {
            containsCall = true; // volatile registers that should be preserved
                                 // needs to be pushed to the stack
            break;
        }
    }
    RCArray<Instruction> tempInstructions;
    for (GPRegister preservedReg : preservedGPRegisters)
    {
        if (block->writesToRegister(preservedReg))
        {
            bool replaced = false;
            for (int i = 0; i < 16; i++)
            {
                if (i == 4 || i == 5 || preservedReg == RSP
                    || preservedReg == RBP)
                {
                    continue; // Skip RSP and RBP (stack counter register)
                }
                if (!containsCall
                    || (isVolatile(preservedReg)
                        == isVolatile((Framework::Assembly::GPRegister)i)))
                { // call inside the block -> only replace volatile with
                  // volatile and non volatile with non volatile registers
                    bool found = false;
                    for (GPRegister r : preservedGPRegisters)
                    {
                        if (r == (GPRegister)i)
                        {
                            found = true;
                            break;
                        }
                    }
                    if (found)
                    {
                        continue;
                    }
                    GPRegister newReg = (GPRegister)i;
                    if (block->isReplacementPossible(preservedReg, newReg))
                    {
                        if (blockResultGpReg)
                        {
                            if (preservedReg == *blockResultGpReg)
                            {
                                *blockResultGpReg = newReg;
                            }
                        }
                        replaced = true;
                        block->replaceRegister(preservedReg, newReg);
                        break;
                    }
                }
            }
            if (!replaced)
            {
                addPush(preservedReg);
                tempInstructions.add(
                    new Instruction(
                        POP, {new GPRegisterArgument(preservedReg)}),
                    0);
            }
        }
    }
    int index = 0;
    for (FPRegister preservedReg : preservedFPRegisters)
    {
        if (block->writesToRegister(preservedReg))
        {
            bool replaced = false;
            for (int i = 0; i < __FP_REGISTER_COUNT; i++)
            {
                if (!containsCall
                    || (isVolatile(preservedReg) == isVolatile((FPRegister)i)))
                { // call inside the block -> only replace volatile with
                  // volatile and non volatile with non volatile registers
                    bool found = false;
                    for (FPRegister r : preservedFPRegisters)
                    {
                        if (r == (FPRegister)i)
                        {
                            found = true;
                            break;
                        }
                    }
                    if (found)
                    {
                        continue;
                    }
                    FPRegister newReg = (FPRegister)i;
                    if (block->isReplacementPossible(preservedReg, newReg))
                    {
                        if (blockResultFpReg)
                        {
                            if (preservedReg == *blockResultFpReg)
                            {
                                *blockResultFpReg = newReg;
                            }
                        }
                        replaced = true;
                        block->replaceRegister(preservedReg, newReg);
                        break;
                    }
                }
            }
            if (!replaced)
            {
                // TODO: search for last instruction that wrote to preservedReg
                // to find its data type
                addPush(preservedReg, fpTypes[index], Y);
                addPop(tempInstructions, preservedReg, fpTypes[index], Y);
            }
        }
        index++;
    }
    index = 0;
    Text prefix = "inlined_";
    prefix.append() << inlineIndex++ << "_";
    block->addJumpLabelPrefix(prefix);
    bool returnFound = false;
    for (const auto& instr : block->instructions)
    {
        if (instr->getOperation() == RET)
        {
            if (index != block->instructions.getEintragAnzahl() - 1)
            {
                returnFound = true;
                instructions.add(new Instruction(
                    JMP, {new JumpTargetArgument(Text("after_") + prefix)}));
            }
        }
        else
        {
            instructions.add(dynamic_cast<Instruction*>(instr->getThis()));
        }
        index++;
    }
    if (returnFound)
    {
        defineJumpTarget(Text("after_") + prefix);
    }
    for (const auto& instr : tempInstructions)
    {
        instructions.add(dynamic_cast<Instruction*>(instr->getThis()));
    }
}

bool Framework::Assembly::AssemblyBlock::writesToRegister(GPRegister reg) const
{
    for (const auto& instr : instructions)
    {
        if (instr->writesToRegister(reg, this))
        {
            return true;
        }
    }
    return false;
}

bool Framework::Assembly::AssemblyBlock::writesToRegister(FPRegister reg) const
{
    for (const auto& instr : instructions)
    {
        if (instr->writesToRegister(reg, this))
        {
            return true;
        }
    }
    return false;
}

bool Framework::Assembly::AssemblyBlock::readsFromRegister(GPRegister reg) const
{
    for (const auto& instr : instructions)
    {
        if (instr->readsFromRegister(reg, this))
        {
            return true;
        }
    }
    return false;
}

bool Framework::Assembly::AssemblyBlock::readsFromRegister(FPRegister reg) const
{
    for (const auto& instr : instructions)
    {
        if (instr->readsFromRegister(reg, this))
        {
            return true;
        }
    }
    return false;
}

bool Framework::Assembly::AssemblyBlock::isReplacementPossible(
    GPRegister oldReg, GPRegister newReg) const
{
    for (const auto& instr : instructions)
    {
        if (!instr->isReplacementPossible(oldReg, newReg, this))
        {
            return false;
        }
    }
    return true;
}

bool Framework::Assembly::AssemblyBlock::isReplacementPossible(
    FPRegister oldReg, FPRegister newReg) const
{
    for (const auto& instr : instructions)
    {
        if (!instr->isReplacementPossible(oldReg, newReg, this))
        {
            return false;
        }
    }
    return true;
}

void Framework::Assembly::AssemblyBlock::replaceRegister(
    GPRegister oldReg, GPRegister newReg)
{
    for (const auto& instr : instructions)
    {
        instr->replaceRegister(oldReg, newReg);
    }
}

void Framework::Assembly::AssemblyBlock::replaceRegister(
    FPRegister oldReg, FPRegister newReg)
{
    for (const auto& instr : instructions)
    {
        instr->replaceRegister(oldReg, newReg);
    }
}

void Framework::Assembly::AssemblyBlock::addJumpLabelPrefix(Text labelPrefix)
{
    for (const auto& instr : instructions)
    {
        instr->addJumpLabelPrefix(labelPrefix);
    }
}

const Framework::RCArray<Framework::Assembly::Instruction>&
Framework::Assembly::AssemblyBlock::getInstructions() const
{
    return instructions;
}

void Framework::Assembly::AssemblyBlock::optimize()
{
    RCArray<Instruction> optimizedInstructions;
    for (int index = 0; index < instructions.getEintragAnzahl(); index++)
    {
        Instruction* curr = instructions.z(index);
        if (index < instructions.getEintragAnzahl() - 1
            && curr->getOperation() == MOV && curr->getArguments().size() == 2
            && curr->getArguments().at(0)->asGPRegisterArgument()
            && curr->getArguments().at(1)->asMemoryAccessArgument())
        {
            GPRegister target = curr->getArguments()
                                    .at(0)
                                    ->asGPRegisterArgument()
                                    ->getRegister();
            GPRegisterPart part
                = curr->getArguments().at(0)->asGPRegisterArgument()->getPart();
            Instruction* next = instructions.z(index + 1);
            if (!next->writesToRegister(target, this)
                && next->getArguments().size() == 2
                && next->getArguments().at(1)->asGPRegisterArgument()
                && next->getArguments()
                           .at(1)
                           ->asGPRegisterArgument()
                           ->getRegister()
                       == target
                && next->getArguments().at(1)->asGPRegisterArgument()->getPart()
                       == part)
            {
                Instruction* replacement = new Instruction(next->getOperation(),
                    {next->getArguments().at(0), curr->getArguments().at(1)});
                if (replacement->isValid(this))
                {
                    optimizedInstructions.add(replacement);
                    index++;
                    continue;
                }
                replacement->release();
            }
        }
        optimizedInstructions.add(dynamic_cast<Instruction*>(curr->getThis()));
    }
    instructions.leeren();
    for (Instruction* instr : optimizedInstructions)
    {
        instructions.add(dynamic_cast<Instruction*>(instr->getThis()));
    }
}

void* Framework::Assembly::AssemblyBlock::compile()
{
    if (compiledCode != 0)
    {
        return compiledCode;
    }
    InMemoryBuffer buffer;
    int index = 0;
    // check non-volatile registers
    RCArray<Instruction> restoreInstructions;
    for (GPRegister nvReg : {RBX, RBP, RSI, RDI, R12, R13, R14, R15})
    {
        if (writesToRegister(nvReg))
        {
            Instruction pushInstr(
                PUSH, {new GPRegisterArgument(nvReg, FULL64)});
            pushInstr.compile(&buffer, this);
            restoreInstructions.add(
                new Instruction(POP, {new GPRegisterArgument(nvReg, FULL64)}),
                0);
        }
    }
    for (FPRegister nvReg :
        {MM6, MM7, MM8, MM9, MM10, MM11, MM12, MM13, MM14, MM15})
    {
        if (writesToRegister(nvReg))
        {
            Instruction subInst(
                SUB, {new GPRegisterArgument(RSP), new ConstantArgument(32)});
            subInst.compile(&buffer, this);
            Instruction pushInstr(MOVUPD,
                {new MemoryAccessArgument(MemoryBlockSize::M256, RSP),
                    new FPRegisterArgument(nvReg, Y)});
            pushInstr.compile(&buffer, this);
            restoreInstructions.add(new Instruction(MOVUPD,
                {new FPRegisterArgument(nvReg, Y),
                    new MemoryAccessArgument(MemoryBlockSize::M256, RSP)}));
            restoreInstructions.add(new Instruction(
                ADD, {new GPRegisterArgument(RSP), new ConstantArgument(32)}));
        }
    }
    // replace return instructions with jumps to the end
    if (restoreInstructions.getEintragAnzahl() > 0)
    {
        bool needed = false;
        for (int index = 0; index < instructions.getEintragAnzahl(); index++)
        {
            if (instructions.z(index)->getOperation() == RET)
            {
                if (index < instructions.getEintragAnzahl() - 1)
                {
                    needed = true;
                    instructions.set(
                        new Instruction(JMP,
                            {new JumpTargetArgument(
                                Text("_restore_non_volatile_registers"))}),
                        index);
                }
                else
                {
                    // remove last RET instruction, will be added after non
                    // volatile registers were restored from the stack
                    instructions.remove(index);
                }
            }
        }
        if (needed)
        {
            defineJumpTarget(Text("_restore_non_volatile_registers"));
        }
    }
    // compile instructions
    for (const auto& instr : instructions)
    {
        instr->compile(&buffer, this);
    }
    // restore non-volatile registers
    for (const auto& instr : restoreInstructions)
    {
        instr->compile(&buffer, this);
    }
    // add final RET instruction
    Instruction retInstr(RET, {});
    retInstr.compile(&buffer, this);
    int totalSize = (int)buffer.getSize();
    // Allocate executable memory
    compiledCode = VirtualAlloc(nullptr, totalSize, MEM_COMMIT, PAGE_READWRITE);
    if (compiledCode == nullptr)
    {
        throw std::runtime_error("Failed to allocate executable memory.");
    }
    // Write the compiled code into the allocated memory
    buffer.lese((char*)compiledCode, totalSize);
    DWORD dummy;
    VirtualProtect(compiledCode, totalSize, PAGE_EXECUTE_READ, &dummy);
    return compiledCode;
}