///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// ShaderBinary.cpp                                                          //
// Copyright (C) Microsoft Corporation. All rights reserved.                 //
// This file is distributed under the University of Illinois Open Source     //
// License. See LICENSE.TXT for details.                                     //
//                                                                           //
// Vertex shader binary format parsing and encoding.                         //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

// HLSL change start
#include "ShaderBinaryIncludes.h"
// HLSL change end

/*==========================================================================;
 *
 *  D3D10ShaderBinary namespace
 *
 ***************************************************************************/

namespace D3D10ShaderBinary
{

BOOL IsOpCodeValid(D3D10_SB_OPCODE_TYPE OpCode)
{
    return OpCode < D3D10_SB_NUM_OPCODES;
}

UINT GetNumInstructionOperands(D3D10_SB_OPCODE_TYPE OpCode)
{
    if (IsOpCodeValid(OpCode))
        return g_InstructionInfo[OpCode].m_NumOperands;
    else
        throw E_FAIL;
}

CInstructionInfo g_InstructionInfo[D3D10_SB_NUM_OPCODES];

void InitInstructionInfo()
{
#define SET(OpCode, Name, NumOperands, PrecMask, OpClass) \
    (g_InstructionInfo[OpCode].Set(NumOperands, Name, OpClass, PrecMask))

    SET (D3D10_SB_OPCODE_ADD, "add",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_AND, "and",                                                 3, 0x06, D3D10_SB_BIT_OP);
    SET (D3D10_SB_OPCODE_BREAK, "break",                                             0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_BREAKC, "breakc",                                           1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_CALL, "call",                                               1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_CALLC, "callc",                                             2, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_CONTINUE, "continue",                                       0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_CONTINUEC, "continuec",                                     1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_CASE, "case",                                               1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_CUT, "cut",                                                 0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_DEFAULT, "default",                                         0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_DISCARD, "discard",                                         1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_DIV, "div",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_DP2, "dp2",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_DP3, "dp3",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_DP4, "dp4",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_ELSE, "else",                                               0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_EMIT, "emit",                                               0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_EMITTHENCUT, "emit_then_cut",                               0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_ENDIF, "endif",                                             0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_ENDLOOP, "endloop",                                         0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_ENDSWITCH, "endswitch",                                     0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_EQ, "eq",                                                   3, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_EXP, "exp",                                                 2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_FRC, "frc",                                                 2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_FTOI, "ftoi",                                               2, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_FTOU, "ftou",                                               2, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_GE, "ge",                                                   3, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_DERIV_RTX, "deriv_rtx",                                     2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_DERIV_RTY, "deriv_rty",                                     2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_IADD, "iadd",                                               3, 0x06, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_IF, "if",                                                   1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_IEQ, "ieq",                                                 3, 0x00, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_IGE, "ige",                                                 3, 0x00, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_ILT, "ilt",                                                 3, 0x00, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_IMAD, "imad",                                               4, 0x0e, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_IMAX, "imax",                                               3, 0x06, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_IMIN, "imin",                                               3, 0x06, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_IMUL, "imul",                                               4, 0x0c, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_INE, "ine",                                                 3, 0x00, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_INEG, "ineg",                                               2, 0x02, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_ISHL, "ishl",                                               3, 0x02, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_ISHR, "ishr",                                               3, 0x02, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_ITOF, "itof",                                               2, 0x00, D3D10_SB_INT_OP);
    SET (D3D10_SB_OPCODE_LABEL, "label",                                             1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_LD, "ld",                                                   3, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_LD_MS, "ldms",                                              4, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_LOG, "log",                                                 2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_LOOP, "loop",                                               0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_LT, "lt",                                                   3, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_MAD, "mad",                                                 4, 0x0e, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_MAX, "max",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_MIN, "min",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_MOV, "mov",                                                 2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_MOVC, "movc",                                               4, 0x0c, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_MUL, "mul",                                                 3, 0x06, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_NE, "ne",                                                   3, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_NOP, "nop",                                                 0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_NOT, "not",                                                 2, 0x02, D3D10_SB_BIT_OP);
    SET (D3D10_SB_OPCODE_OR, "or",                                                   3, 0x06, D3D10_SB_BIT_OP);
    SET (D3D10_SB_OPCODE_RESINFO, "resinfo",                                         3, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_RET, "ret",                                                 0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_RETC, "retc",                                               1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_ROUND_NE, "round_ne",                                       2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_ROUND_NI, "round_ni",                                       2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_ROUND_PI, "round_pi",                                       2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_ROUND_Z, "round_z",                                         2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_RSQ, "rsq",                                                 2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_SAMPLE, "sample",                                           4, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_SAMPLE_B, "sample_b",                                       5, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_SAMPLE_L, "sample_l",                                       5, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_SAMPLE_D, "sample_d",                                       6, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_SAMPLE_C, "sample_c",                                       5, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_SAMPLE_C_LZ, "sample_c_lz",                                 5, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_SB_OPCODE_SQRT, "sqrt",                                               2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_SWITCH, "switch",                                           1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_SINCOS, "sincos",                                           3, 0x04, D3D10_SB_FLOAT_OP);
    SET (D3D10_SB_OPCODE_UDIV, "udiv",                                               4, 0x0c, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_ULT, "ult",                                                 3, 0x00, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_UGE, "uge",                                                 3, 0x00, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_UMAX, "umax",                                               3, 0x06, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_UMIN, "umin",                                               3, 0x06, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_UMUL, "umul",                                               4, 0x0c, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_UMAD, "umad",                                               4, 0x0e, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_USHR, "ushr",                                               3, 0x02, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_UTOF, "utof",                                               2, 0x00, D3D10_SB_UINT_OP);
    SET (D3D10_SB_OPCODE_XOR, "xor",                                                 3, 0x06, D3D10_SB_BIT_OP);
    SET (D3D10_SB_OPCODE_RESERVED0, "jmp",                                           0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D10_SB_OPCODE_DCL_INPUT, "dcl_input",                                     1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_OUTPUT, "dcl_output",                                   1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INPUT_SGV, "dcl_input_sgv",                             1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INPUT_PS_SGV, "dcl_input_ps_sgv",                       1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE, "dcl_inputprimitive",               0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, "dcl_outputtopology",     0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, "dcl_maxout",                  0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INPUT_PS, "dcl_input_ps",                               1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER, "dcl_constantbuffer",                  1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_SAMPLER, "dcl_sampler",                                 1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_RESOURCE, "dcl_resource",                               1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INPUT_SIV, "dcl_input_siv",                             1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INPUT_PS_SIV, "dcl_input_ps_siv",                       1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_OUTPUT_SIV, "dcl_output_siv",                           1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_OUTPUT_SGV, "dcl_output_sgv",                           1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_TEMPS, "dcl_temps",                                     0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP, "dcl_indexableTemp",                    0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_INDEX_RANGE, "dcl_indexrange",                          1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS, "dcl_globalFlags",                        0, 0x00, D3D10_SB_DCL_OP);

    SET (D3D10_1_SB_OPCODE_SAMPLE_INFO, "sampleinfo",                                2, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_1_SB_OPCODE_SAMPLE_POS, "samplepos",                                  3, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_1_SB_OPCODE_GATHER4, "gather4",                                       4, 0x00, D3D10_SB_TEX_OP);
    SET (D3D10_1_SB_OPCODE_LOD, "lod",                                               4, 0x00, D3D10_SB_TEX_OP);

    SET (D3D11_SB_OPCODE_EMIT_STREAM, "emit_stream",                                 1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D11_SB_OPCODE_CUT_STREAM, "cut_stream",                                   1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D11_SB_OPCODE_EMITTHENCUT_STREAM, "emit_then_cut_stream",                 1, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D11_SB_OPCODE_INTERFACE_CALL, "fcall",                                    1, 0x00, D3D10_SB_FLOW_OP);

    SET (D3D11_SB_OPCODE_DCL_STREAM, "dcl_stream",                                   1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_FUNCTION_BODY, "dcl_function_body",                     0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_FUNCTION_TABLE, "dcl_function_table",                   0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_INTERFACE, "dcl_interface",                             0, 0x00, D3D10_SB_DCL_OP);

    SET (D3D11_SB_OPCODE_BUFINFO, "bufinfo",                                         2, 0x00, D3D10_SB_TEX_OP);
    SET (D3D11_SB_OPCODE_DERIV_RTX_COARSE, "deriv_rtx_coarse",                       2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_DERIV_RTX_FINE, "deriv_rtx_fine",                           2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_DERIV_RTY_COARSE, "deriv_rty_coarse",                       2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_DERIV_RTY_FINE, "deriv_rty_fine",                           2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_GATHER4_C, "gather4_c",                                     5, 0x00, D3D10_SB_TEX_OP);
    SET (D3D11_SB_OPCODE_GATHER4_PO, "gather4_po",                                   5, 0x00, D3D10_SB_TEX_OP);
    SET (D3D11_SB_OPCODE_GATHER4_PO_C, "gather4_po_c",                               6, 0x00, D3D10_SB_TEX_OP);
    SET (D3D11_SB_OPCODE_RCP, "rcp",                                                 2, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_F32TOF16, "f32tof16",                                       2, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_F16TOF32, "f16tof32",                                       2, 0x00, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_UADDC, "uaddc",                                             4, 0x0c, D3D10_SB_UINT_OP);
    SET (D3D11_SB_OPCODE_USUBB, "usubb",                                             4, 0x0c, D3D10_SB_UINT_OP);
    SET (D3D11_SB_OPCODE_COUNTBITS, "countbits",                                     2, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_FIRSTBIT_HI, "firstbit_hi",                                 2, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_FIRSTBIT_LO, "firstbit_lo",                                 2, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_FIRSTBIT_SHI, "firstbit_shi",                               2, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_UBFE, "ubfe",                                               4, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_IBFE, "ibfe",                                               4, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_BFI, "bfi",                                                 5, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_BFREV, "bfrev",                                             2, 0x02, D3D10_SB_BIT_OP);
    SET (D3D11_SB_OPCODE_SWAPC, "swapc",                                             5, 0x02, D3D10_SB_FLOAT_OP);

    SET (D3D11_SB_OPCODE_HS_DECLS, "hs_decls",                                       0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_HS_CONTROL_POINT_PHASE, "hs_control_point_phase",           0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_HS_FORK_PHASE, "hs_fork_phase",                             0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_HS_JOIN_PHASE, "hs_join_phase",                             0, 0x00, D3D10_SB_DCL_OP);

    SET (D3D11_SB_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, "dcl_input_control_point_count",   0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, "dcl_output_control_point_count", 0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_TESS_DOMAIN, "dcl_tessellator_domain",                        0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_TESS_PARTITIONING, "dcl_tessellator_partitioning",            0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, "dcl_tessellator_output_primitive",    0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR, "dcl_hs_max_tessfactor",                   0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, "dcl_hs_fork_phase_instance_count", 0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, "dcl_hs_join_phase_instance_count", 0, 0x00, D3D10_SB_DCL_OP);

    SET (D3D11_SB_OPCODE_DCL_THREAD_GROUP, "dcl_thread_group",                       0, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, "dcl_uav_typed",           1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, "dcl_uav_raw",               1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, "dcl_uav_structured", 1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, "dcl_tgsm_raw",         1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, "dcl_tgsm_structured", 1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_RESOURCE_RAW, "dcl_resource_raw",                       1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED, "dcl_resource_structured",         1, 0x00, D3D10_SB_DCL_OP);
    SET (D3D11_SB_OPCODE_LD_UAV_TYPED, "ld_uav_typed",                               3, 0x00, D3D11_SB_MEM_OP);    
    SET (D3D11_SB_OPCODE_STORE_UAV_TYPED, "store_uav_typed",                         3, 0x00, D3D11_SB_MEM_OP);
    SET (D3D11_SB_OPCODE_LD_RAW, "ld_raw",                                           3, 0x00, D3D11_SB_MEM_OP);
    SET (D3D11_SB_OPCODE_STORE_RAW, "store_raw",                                     3, 0x00, D3D11_SB_MEM_OP);
    SET (D3D11_SB_OPCODE_LD_STRUCTURED, "ld_structured",                             4, 0x00, D3D11_SB_MEM_OP);
    SET (D3D11_SB_OPCODE_STORE_STRUCTURED, "store_structured",                       4, 0x00, D3D11_SB_MEM_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_AND, "atomic_and",                                   3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_OR, "atomic_or",                                     3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_XOR, "atomic_xor",                                   3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_CMP_STORE, "atomic_cmp_store",                       4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_IADD, "atomic_iadd",                                 3, 0x00, D3D11_SB_ATOMIC_OP); 
    SET (D3D11_SB_OPCODE_ATOMIC_IMAX, "atomic_imax",                                 3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_IMIN, "atomic_imin",                                 3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_UMAX, "atomic_umax",                                 3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_ATOMIC_UMIN, "atomic_umin",                                 3, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_ALLOC, "imm_atomic_alloc",                       2, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_CONSUME, "imm_atomic_consume",                   2, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_IADD, "imm_atomic_iadd",                         4, 0x00, D3D11_SB_ATOMIC_OP);  
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_AND, "imm_atomic_and",                           4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_OR, "imm_atomic_or",                             4, 0x00, D3D11_SB_ATOMIC_OP);  
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_XOR, "imm_atomic_xor",                           4, 0x00, D3D11_SB_ATOMIC_OP);  
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_EXCH, "imm_atomic_exch",                         4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_CMP_EXCH, "imm_atomic_cmp_exch",                 5, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_IMAX, "imm_atomic_imax",                         4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_IMIN, "imm_atomic_imin",                         4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_UMAX, "imm_atomic_umax",                         4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_IMM_ATOMIC_UMIN, "imm_atomic_umin",                         4, 0x00, D3D11_SB_ATOMIC_OP);
    SET (D3D11_SB_OPCODE_SYNC, "sync",                                               0, 0x00, D3D10_SB_FLOW_OP);
    SET (D3D11_SB_OPCODE_EVAL_SNAPPED, "eval_snapped",                               3, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_EVAL_SAMPLE_INDEX, "eval_sample_index",                     3, 0x02, D3D10_SB_FLOAT_OP);
    SET (D3D11_SB_OPCODE_EVAL_CENTROID, "eval_centroid",                             2, 0x02, D3D10_SB_FLOAT_OP);

    SET (D3D11_SB_OPCODE_DCL_GS_INSTANCE_COUNT, "dcl_gsinstances",                   0, 0x00, D3D10_SB_DCL_OP);

    SET (D3D11_SB_OPCODE_DADD, "dadd",                                               3, 0x06, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DMAX, "dmax",                                               3, 0x06, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DMIN, "dmin",                                               3, 0x06, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DMUL, "dmul",                                               3, 0x06, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DEQ, "deq",                                                 3, 0x00, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DGE, "dge",                                                 3, 0x00, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DLT, "dlt",                                                 3, 0x00, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DNE, "dne",                                                 3, 0x00, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DMOV, "dmov",                                               2, 0x02, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DMOVC, "dmovc",                                             4, 0x0c, D3D11_SB_DOUBLE_OP);
    SET (D3D11_SB_OPCODE_DTOF, "dtof",                                               2, 0x02, D3D11_SB_DOUBLE_TO_FLOAT_OP);
    SET (D3D11_SB_OPCODE_FTOD, "ftod",                                               2, 0x00, D3D11_SB_FLOAT_TO_DOUBLE_OP);

    SET (D3D11_SB_OPCODE_ABORT, "abort",                                             0, 0x00, D3D11_SB_DEBUG_OP);
    SET (D3D11_SB_OPCODE_DEBUG_BREAK, "debug_break",                                 0, 0x00, D3D11_SB_DEBUG_OP);

    SET (D3D11_1_SB_OPCODE_DDIV, "ddiv",                                             3, 0x06, D3D11_SB_DOUBLE_OP);
    SET (D3D11_1_SB_OPCODE_DFMA, "dfma",                                             4, 0x0e, D3D11_SB_DOUBLE_OP);
    SET (D3D11_1_SB_OPCODE_DRCP, "drcp",                                             2, 0x02, D3D11_SB_DOUBLE_OP);

    SET (D3D11_1_SB_OPCODE_MSAD, "msad",                                             4, 0x0e, D3D10_SB_UINT_OP);

    SET (D3D11_1_SB_OPCODE_DTOI, "dtoi",                                             2, 0x00, D3D11_SB_DOUBLE_OP);
    SET (D3D11_1_SB_OPCODE_DTOU, "dtou",                                             2, 0x00, D3D11_SB_DOUBLE_OP);
    SET (D3D11_1_SB_OPCODE_ITOD, "itod",                                             2, 0x00, D3D10_SB_INT_OP);
    SET (D3D11_1_SB_OPCODE_UTOD, "utod",                                             2, 0x00, D3D10_SB_UINT_OP);

    SET (D3DWDDM1_3_SB_OPCODE_GATHER4_FEEDBACK,"gather4_s",                          5, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_GATHER4_C_FEEDBACK,"gather4_c_s",                      6, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_GATHER4_PO_FEEDBACK,"gather4_po_s",                    6, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_GATHER4_PO_C_FEEDBACK,"gather4_po_c_s",                7, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_LD_FEEDBACK,"ld_s",                                    4, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_LD_MS_FEEDBACK,"ldms_s",                               5, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_LD_UAV_TYPED_FEEDBACK,"ld_uav_typed_s",                4, 0x00, D3D11_SB_MEM_OP);
    SET (D3DWDDM1_3_SB_OPCODE_LD_RAW_FEEDBACK,"ld_raw_s",                            4, 0x00, D3D11_SB_MEM_OP);
    SET (D3DWDDM1_3_SB_OPCODE_LD_STRUCTURED_FEEDBACK,"ld_structured_s",              5, 0x00, D3D11_SB_MEM_OP);
    SET (D3DWDDM1_3_SB_OPCODE_SAMPLE_L_FEEDBACK,"sample_l_s",                        6, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK,"sample_c_lz_s",                  6, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_SAMPLE_CLAMP_FEEDBACK, "sample_cl_s",                  6, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_SAMPLE_B_CLAMP_FEEDBACK, "sample_b_cl_s",              7, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_SAMPLE_D_CLAMP_FEEDBACK,"sample_d_cl_s",               8, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK,"sample_c_cl_s",               7, 0x00, D3D10_SB_TEX_OP);
    SET (D3DWDDM1_3_SB_OPCODE_CHECK_ACCESS_FULLY_MAPPED, "check_access_fully_mapped",2, 0x00, D3D10_SB_TEX_OP);
}

//*****************************************************************************
//
//  CShaderCodeParser
//
//*****************************************************************************

void CShaderCodeParser::SetShader(CONST CShaderToken* pBuffer)
{
    m_pShaderCode = (CShaderToken*)pBuffer;
    m_pShaderEndToken = (CShaderToken*)pBuffer + pBuffer[1];
    // First OpCode token
    m_pCurrentToken = (CShaderToken*)&pBuffer[2];
}

D3D10_SB_TOKENIZED_PROGRAM_TYPE CShaderCodeParser::ShaderType()
{
    return (D3D10_SB_TOKENIZED_PROGRAM_TYPE)DECODE_D3D10_SB_TOKENIZED_PROGRAM_TYPE(*m_pShaderCode);
}

UINT CShaderCodeParser::CurrentTokenOffset()
{
    return (UINT)(m_pCurrentToken - m_pShaderCode);
}

void CShaderCodeParser::SetCurrentTokenOffset(UINT Offset)
{
    m_pCurrentToken = m_pShaderCode + Offset;
}

UINT CShaderCodeParser::ShaderLengthInTokens()
{
    return m_pShaderCode[1];
}

UINT CShaderCodeParser::ShaderMinorVersion()
{
    return DECODE_D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION(m_pShaderCode[0]);
}

UINT CShaderCodeParser::ShaderMajorVersion()
{
    return DECODE_D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION(m_pShaderCode[0]);
}

void CShaderCodeParser::ParseIndex(COperandIndex* pOperandIndex, D3D10_SB_OPERAND_INDEX_REPRESENTATION IndexType)
{
    switch (IndexType)
    {
    case D3D10_SB_OPERAND_INDEX_IMMEDIATE32:
        pOperandIndex->m_RegIndex = *m_pCurrentToken++;
        pOperandIndex->m_ComponentName = D3D10_SB_4_COMPONENT_X;
        pOperandIndex->m_RelRegType = D3D10_SB_OPERAND_TYPE_IMMEDIATE32;
        break;
    case D3D10_SB_OPERAND_INDEX_IMMEDIATE64:
        pOperandIndex->m_RegIndexA[0] = *m_pCurrentToken++;
        pOperandIndex->m_RegIndexA[1] = *m_pCurrentToken++;
        pOperandIndex->m_ComponentName = D3D10_SB_4_COMPONENT_X;
        pOperandIndex->m_RelRegType = D3D10_SB_OPERAND_TYPE_IMMEDIATE64;
        break;
    case D3D10_SB_OPERAND_INDEX_RELATIVE:
        {
            COperand operand;
            ParseOperand(&operand);
            pOperandIndex->m_RelIndex = operand.m_Index[0].m_RegIndex;
            pOperandIndex->m_RelIndex1 = operand.m_Index[1].m_RegIndex;
            pOperandIndex->m_RelRegType = operand.m_Type;
            pOperandIndex->m_IndexDimension = operand.m_IndexDimension;
            pOperandIndex->m_ComponentName = operand.m_ComponentName;
            pOperandIndex->m_MinPrecision = operand.m_MinPrecision;
            break;
        }
    case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE:
        {
            pOperandIndex->m_RegIndex = *m_pCurrentToken++;
            COperand operand;
            ParseOperand(&operand);
            pOperandIndex->m_RelIndex = operand.m_Index[0].m_RegIndex;
            pOperandIndex->m_RelIndex1 = operand.m_Index[1].m_RegIndex;
            pOperandIndex->m_RelRegType = operand.m_Type;
            pOperandIndex->m_IndexDimension = operand.m_IndexDimension;
            pOperandIndex->m_ComponentName = operand.m_ComponentName;
            pOperandIndex->m_MinPrecision = operand.m_MinPrecision;
        }
        break;
    default:
        throw E_FAIL;
    }
}

void CShaderCodeParser::ParseOperand(COperandBase* pOperand)
{
    CShaderToken Token = *m_pCurrentToken++;

    pOperand->m_Type = DECODE_D3D10_SB_OPERAND_TYPE(Token);
    pOperand->m_NumComponents = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(Token);
    pOperand->m_bExtendedOperand = DECODE_IS_D3D10_SB_OPERAND_EXTENDED(Token);

    UINT NumComponents = 0;
    switch (pOperand->m_NumComponents)
    {
    case D3D10_SB_OPERAND_1_COMPONENT:   NumComponents = 1; break;
    case D3D10_SB_OPERAND_4_COMPONENT:   NumComponents = 4; break;
    }

    switch (pOperand->m_Type)
    {
    case D3D10_SB_OPERAND_TYPE_IMMEDIATE32:
    case D3D10_SB_OPERAND_TYPE_IMMEDIATE64:
        break;
    default:
        {
            if (pOperand->m_NumComponents == D3D10_SB_OPERAND_4_COMPONENT)
            {
                // Component selection mode
                pOperand->m_ComponentSelection = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(Token);
                switch(pOperand->m_ComponentSelection)
                {
                case D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE:
                    pOperand->m_WriteMask = DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(Token);
                    break;
                case D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE:
                    pOperand->m_Swizzle[0] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(Token, 0);
                    pOperand->m_Swizzle[1] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(Token, 1);
                    pOperand->m_Swizzle[2] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(Token, 2);
                    pOperand->m_Swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(Token, 3);
                    break;
                case D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE:
                {
                    D3D10_SB_4_COMPONENT_NAME Component = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(Token);
                    pOperand->m_Swizzle[0] = static_cast<BYTE>(Component);
                    pOperand->m_Swizzle[1] = static_cast<BYTE>(Component);
                    pOperand->m_Swizzle[2] = static_cast<BYTE>(Component);
                    pOperand->m_Swizzle[3] = static_cast<BYTE>(Component);
                    pOperand->m_ComponentName = Component;
                    break;
                }
                default:
                    throw E_FAIL;
                }
            }
            pOperand->m_IndexDimension = DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(Token);
            if (pOperand->m_IndexDimension != D3D10_SB_OPERAND_INDEX_0D)
            {
                UINT NumDimensions = pOperand->m_IndexDimension;
                // Index representation
                for (UINT i=0; i < NumDimensions; i++)
                {
                    pOperand->m_IndexType[i] = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(i, Token);
                }
            }
            break;
        }
    }

    // Extended operand
    if (pOperand->m_bExtendedOperand)
    {
        Token = *m_pCurrentToken++;
        pOperand->m_ExtendedOperandType = DECODE_D3D10_SB_EXTENDED_OPERAND_TYPE(Token);
        if (pOperand->m_ExtendedOperandType == D3D10_SB_EXTENDED_OPERAND_MODIFIER)
        {
            pOperand->m_Modifier = DECODE_D3D10_SB_OPERAND_MODIFIER(Token);
            pOperand->m_MinPrecision = DECODE_D3D11_SB_OPERAND_MIN_PRECISION(Token);
            pOperand->m_Nonuniform = DECODE_D3D12_SB_OPERAND_NON_UNIFORM(Token);
        }
    }

    switch( pOperand->m_Type )
    {
    case D3D10_SB_OPERAND_TYPE_IMMEDIATE32:
    case D3D10_SB_OPERAND_TYPE_IMMEDIATE64:
        for (UINT i=0 ; i < NumComponents; i++)
        {
            pOperand->m_Value[i] = *m_pCurrentToken++;
        }
        break;
    }

    // Operand indices
    if (pOperand->m_IndexDimension != D3D10_SB_OPERAND_INDEX_0D)
    {
        const UINT NumDimensions = pOperand->m_IndexDimension;
        // Index representation
        for (UINT i=0; i < NumDimensions; i++)
        {
            ParseIndex(&pOperand->m_Index[i], pOperand->m_IndexType[i]);
        }
    }
}

void CShaderCodeParser::ParseInstruction(CInstruction* pInstruction)
{
    pInstruction->Clear(true);
    CShaderToken* pStart = m_pCurrentToken;
    CShaderToken Token = *m_pCurrentToken++;
    pInstruction->m_OpCode = DECODE_D3D10_SB_OPCODE_TYPE(Token);
    pInstruction->m_PreciseMask = DECODE_D3D11_SB_INSTRUCTION_PRECISE_VALUES(Token); 
    pInstruction->m_bSaturate = DECODE_IS_D3D10_SB_INSTRUCTION_SATURATE_ENABLED(Token); 
    UINT InstructionLength = DECODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(Token);
    pInstruction->m_NumOperands = GetNumInstructionOperands(pInstruction->m_OpCode);
    BOOL b51PlusShader = (ShaderMajorVersion() > 5 || (ShaderMajorVersion() == 5 && ShaderMinorVersion() > 0));
    BOOL bExtended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(Token);
    if( bExtended && (
        (pInstruction->m_OpCode == D3D11_SB_OPCODE_DCL_INTERFACE)||
        (pInstruction->m_OpCode == D3D11_SB_OPCODE_DCL_FUNCTION_TABLE)))
    {
        pInstruction->m_ExtendedOpCodeCount = 1;
    #pragma prefast (suppress : __WARNING_LOCALDECLHIDESLOCAL, "This uses the same variable name for continuity.")
        CShaderToken Token = *m_pCurrentToken++;
        // these instructions may be longer than can fit in the normal instructionlength field
        InstructionLength = (UINT)(Token);
    }
    else
    {
        pInstruction->m_ExtendedOpCodeCount = 0;
        for(int i = 0; i < (bExtended ? D3D11_SB_MAX_SIMULTANEOUS_EXTENDED_OPCODES : 0); i++)
        {   
            pInstruction->m_ExtendedOpCodeCount++;
    #pragma prefast (suppress : __WARNING_LOCALDECLHIDESLOCAL, "This uses the same variable name for continuity.")
            CShaderToken Token = *m_pCurrentToken++;
            bExtended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(Token);
            pInstruction->m_OpCodeEx[i] = DECODE_D3D10_SB_EXTENDED_OPCODE_TYPE(Token);
            switch(pInstruction->m_OpCodeEx[i])
            {
            case D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS:
                {
                    pInstruction->m_TexelOffset[0] = (INT8)DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U, Token);
                    pInstruction->m_TexelOffset[1] = (INT8)DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V, Token);
                    pInstruction->m_TexelOffset[2] = (INT8)DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W, Token);
                    for(UINT i = 0;i < 3;i++)
                    {
                        if(pInstruction->m_TexelOffset[i] & 0x8)
                            pInstruction->m_TexelOffset[i] |= 0xfffffff0;
                    }
                    break;
                }
                break;
            case D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM:
                {
                    pInstruction->m_ResourceDimEx = DECODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION(Token);
                    pInstruction->m_ResourceDimStructureStrideEx = DECODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION_STRUCTURE_STRIDE(Token);
                }
                break;
            case D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE:
                {
                    for(UINT j = 0; j < 4; j++)
                    {
                        pInstruction->m_ResourceReturnTypeEx[j] = DECODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(Token,j);
                    }
                }
                break;
            }
            if( !bExtended )
            {
                break;
            }
        }
    }
    switch (pInstruction->m_OpCode)
    {
    case D3D10_SB_OPCODE_CUSTOMDATA:
        pInstruction->m_PreciseMask = 0;
        pInstruction->m_bSaturate = false;
        pInstruction->m_NumOperands = 0;

        // not bothering to keep custom-data for now. TODO: store
        pInstruction->m_CustomData.Type = DECODE_D3D10_SB_CUSTOMDATA_CLASS(Token);
        InstructionLength = *m_pCurrentToken;
        if (*m_pCurrentToken <2)
        {
            InstructionLength = 2;
            pInstruction->m_CustomData.pData = 0;
            pInstruction->m_CustomData.DataSizeInBytes = 0;
        }
        else
        {
            pInstruction->m_CustomData.DataSizeInBytes = (*m_pCurrentToken-2)*4;
            pInstruction->m_CustomData.pData = malloc((*m_pCurrentToken - 2)*sizeof(UINT));
            if( NULL == pInstruction->m_CustomData.pData )
            {
                throw E_OUTOFMEMORY;
            }
            memcpy(pInstruction->m_CustomData.pData, m_pCurrentToken+1, (*m_pCurrentToken - 2)*4);

            switch(pInstruction->m_CustomData.Type)
            {
            case D3D11_SB_CUSTOMDATA_SHADER_MESSAGE:
                {
                    CShaderMessage* pMessage = &pInstruction->m_CustomData.ShaderMessage;
                    UINT Length = pInstruction->m_CustomData.DataSizeInBytes / 4;
                    UINT* pData = (UINT*)pInstruction->m_CustomData.pData;

                    ZeroMemory(pMessage, sizeof(*pMessage));
                    
                    if (Length < 6)
                    {
                        break;
                    }

                    UINT StrChars = pData[2];
                    // Add one for the terminator and then round up.
                    UINT StrWords = (StrChars + sizeof(DWORD)) / sizeof(DWORD);
                    UINT NumOperands = pData[3];
                    UINT OpLength = pData[4];

                    // Enforce some basic sanity size limits.
                    if (OpLength >= 0x10000 ||
                        NumOperands >= 0x1000 ||
                        StrWords >= 0x10000 ||
                        Length < 5 + OpLength + StrWords)
                    {
                        break;
                    }

                    UINT* pOpEnd = &pData[5 + OpLength];

                    pMessage->pOperands = (COperand*)malloc(NumOperands * sizeof(COperand));
                    if (!pMessage->pOperands)
                    {
                        throw E_OUTOFMEMORY;
                    }

                    CONST CShaderToken* pOperands = (CShaderToken*)&pData[5];
                    for (UINT i = 0; i < NumOperands; i++)
                    {
                        if (pOperands >= pOpEnd)
                        {
                            break;
                        }

                        pMessage->pOperands[i].Clear();                        
                        pOperands = ParseOperandAt(&pMessage->pOperands[i],
                                                   pOperands,
                                                   pOpEnd);
                    }
                    if (pOperands != pOpEnd)
                    {
                        free(pMessage->pOperands);
                        pMessage->pOperands = NULL;
                        break;
                    }
                    
                    // Now that we're sure everything is valid we can
                    // fill in the message info.
                    pMessage->MessageID = (D3D11_SB_SHADER_MESSAGE_ID)pData[0];
                    pMessage->FormatStyle = (D3D11_SB_SHADER_MESSAGE_FORMAT)pData[1];
                    pMessage->pFormatString = (PCSTR)pOpEnd;
                    pMessage->NumOperands = NumOperands;
                    break;
                }
            case D3D10_SB_CUSTOMDATA_COMMENT:
                {
                    // Guarantee that the C string comment is Null-terminated
                    *((LPSTR)pInstruction->m_CustomData.pData + pInstruction->m_CustomData.DataSizeInBytes - 1) = '\0';
                    break;
                }
            }
        }      
        break;
    case D3D11_SB_OPCODE_DCL_FUNCTION_BODY:
        pInstruction->m_FunctionBodyDecl.FunctionBodyNumber = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        break;
    case D3D11_SB_OPCODE_DCL_FUNCTION_TABLE:
        pInstruction->m_FunctionTableDecl.FunctionTableNumber = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        pInstruction->m_FunctionTableDecl.TableLength = (UINT)(*m_pCurrentToken);

        // opcode
        // instruction length if extended instruction
        // table ID
        // table length
        // data
        assert(InstructionLength == (3 + (bExtended?1:0) + pInstruction->m_FunctionTableDecl.TableLength));

        pInstruction->m_FunctionTableDecl.pFunctionIdentifiers =
            (UINT*) malloc(pInstruction->m_FunctionTableDecl.TableLength*sizeof(UINT));

        if( NULL == pInstruction->m_FunctionTableDecl.pFunctionIdentifiers )
        {
            throw E_OUTOFMEMORY;
        }

        m_pCurrentToken++;

        memcpy(pInstruction->m_FunctionTableDecl.pFunctionIdentifiers, m_pCurrentToken,
               pInstruction->m_FunctionTableDecl.TableLength*sizeof(UINT));
        break;
    case D3D11_SB_OPCODE_DCL_INTERFACE:
        pInstruction->m_InterfaceDecl.bDynamicallyIndexed = DECODE_D3D11_SB_INTERFACE_INDEXED_BIT(Token);
        pInstruction->m_InterfaceDecl.InterfaceNumber = (WORD)(*m_pCurrentToken);
        m_pCurrentToken++;
        pInstruction->m_InterfaceDecl.ExpectedTableSize = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        // there's a limit of 64k types, so that gives a max length on this table.
        pInstruction->m_InterfaceDecl.TableLength = DECODE_D3D11_SB_INTERFACE_TABLE_LENGTH(*m_pCurrentToken);
        // this puts a limit on the size of interface arrays at 64k
        pInstruction->m_InterfaceDecl.ArrayLength = DECODE_D3D11_SB_INTERFACE_ARRAY_LENGTH(*m_pCurrentToken);

        // opcode
        // instruction length if extended instruction
        // interface ID
        // table size
        // num types/array length
        // data
        assert(InstructionLength == (4 + (bExtended?1:0) + pInstruction->m_InterfaceDecl.TableLength));

        pInstruction->m_InterfaceDecl.pFunctionTableIdentifiers =
            (UINT*) malloc(pInstruction->m_InterfaceDecl.TableLength*sizeof(UINT));

        if( NULL == pInstruction->m_InterfaceDecl.pFunctionTableIdentifiers )
        {
            throw E_OUTOFMEMORY;
        }

        m_pCurrentToken++;

        memcpy(pInstruction->m_InterfaceDecl.pFunctionTableIdentifiers, m_pCurrentToken,
               pInstruction->m_InterfaceDecl.TableLength*sizeof(UINT));
        break;
    case D3D11_SB_OPCODE_INTERFACE_CALL:
        pInstruction->m_InterfaceCall.FunctionIndex = *m_pCurrentToken++;
        pInstruction->m_InterfaceCall.pInterfaceOperand =
            pInstruction->m_Operands;
        ParseOperand(pInstruction->m_InterfaceCall.pInterfaceOperand);
        break;
    case D3D10_SB_OPCODE_DCL_RESOURCE:
        pInstruction->m_ResourceDecl.Dimension = DECODE_D3D10_SB_RESOURCE_DIMENSION(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_ResourceDecl.ReturnType[0] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 0);
        pInstruction->m_ResourceDecl.ReturnType[1] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 1);
        pInstruction->m_ResourceDecl.ReturnType[2] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 2);
        pInstruction->m_ResourceDecl.ReturnType[3] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 3);
        pInstruction->m_ResourceDecl.SampleCount = DECODE_D3D10_SB_RESOURCE_SAMPLE_COUNT(Token);
        m_pCurrentToken++;
        pInstruction->m_ResourceDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_ResourceDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;

    case D3D10_SB_OPCODE_DCL_SAMPLER:
        pInstruction->m_SamplerDecl.SamplerMode = DECODE_D3D10_SB_SAMPLER_MODE(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_SamplerDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_SamplerDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;

    case D3D11_SB_OPCODE_DCL_STREAM:
        ParseOperand(&pInstruction->m_Operands[0]);
        break;

    case D3D10_SB_OPCODE_DCL_TEMPS:
        pInstruction->m_TempsDecl.NumTemps = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP:
        pInstruction->m_IndexableTempDecl.IndexableTempNumber = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        pInstruction->m_IndexableTempDecl.NumRegisters  = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        switch( min( 4u, max( 1u, (UINT)(*m_pCurrentToken) ) ) )
        {
        case 1:
            pInstruction->m_IndexableTempDecl.Mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_X;
            break;
        case 2:
            pInstruction->m_IndexableTempDecl.Mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_X |
                                                     D3D10_SB_OPERAND_4_COMPONENT_MASK_Y;
            break;
        case 3:
            pInstruction->m_IndexableTempDecl.Mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_X |
                                                     D3D10_SB_OPERAND_4_COMPONENT_MASK_Y |
                                                     D3D10_SB_OPERAND_4_COMPONENT_MASK_Z;
            break;
        case 4:
            pInstruction->m_IndexableTempDecl.Mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_ALL;
            break;
        }
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_INPUT:
    case D3D10_SB_OPCODE_DCL_OUTPUT:
        ParseOperand(&pInstruction->m_Operands[0]);
        break;

    case D3D10_SB_OPCODE_DCL_INPUT_SIV:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_InputDeclSIV.Name = DECODE_D3D10_SB_NAME(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_INPUT_SGV:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_InputDeclSIV.Name = DECODE_D3D10_SB_NAME(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_INPUT_PS:
        pInstruction->m_InputPSDecl.InterpolationMode = DECODE_D3D10_SB_INPUT_INTERPOLATION_MODE(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        break;

    case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV:
        pInstruction->m_InputPSDeclSIV.InterpolationMode = DECODE_D3D10_SB_INPUT_INTERPOLATION_MODE(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_InputPSDeclSIV.Name = DECODE_D3D10_SB_NAME(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV:
        pInstruction->m_InputPSDeclSGV.InterpolationMode = DECODE_D3D10_SB_INPUT_INTERPOLATION_MODE(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_InputPSDeclSGV.Name = DECODE_D3D10_SB_NAME(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_OUTPUT_SIV:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_OutputDeclSIV.Name = DECODE_D3D10_SB_NAME(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_OUTPUT_SGV:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_OutputDeclSGV.Name = DECODE_D3D10_SB_NAME(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_INDEX_RANGE:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_IndexRangeDecl.RegCount = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER:
        pInstruction->m_ConstantBufferDecl.AccessPattern = DECODE_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_ConstantBufferDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_ConstantBufferDecl.Size = (UINT)(*m_pCurrentToken++);
            pInstruction->m_ConstantBufferDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        else
        {
            pInstruction->m_ConstantBufferDecl.Size = pInstruction->m_Operands[0].m_Index[1].m_RegIndex;
        }
        break;

    case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:
        pInstruction->m_OutputTopologyDecl.Topology = DECODE_D3D10_SB_GS_OUTPUT_PRIMITIVE_TOPOLOGY(Token);
        break;

    case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE:
        pInstruction->m_InputPrimitiveDecl.Primitive = DECODE_D3D10_SB_GS_INPUT_PRIMITIVE(Token);
        break;

    case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT:
        pInstruction->m_GSMaxOutputVertexCountDecl.MaxOutputVertexCount = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D11_SB_OPCODE_DCL_GS_INSTANCE_COUNT:
        pInstruction->m_GSInstanceCountDecl.InstanceCount = (UINT)(*m_pCurrentToken);
        m_pCurrentToken++;
        break;

    case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS:
        pInstruction->m_GlobalFlagsDecl.Flags = DECODE_D3D10_SB_GLOBAL_FLAGS(Token);
        break;

    case D3D11_SB_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT:
        pInstruction->m_InputControlPointCountDecl.InputControlPointCount = DECODE_D3D11_SB_INPUT_CONTROL_POINT_COUNT(Token);
        break;

    case D3D11_SB_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT:
        pInstruction->m_OutputControlPointCountDecl.OutputControlPointCount = DECODE_D3D11_SB_OUTPUT_CONTROL_POINT_COUNT(Token);
        break;

    case D3D11_SB_OPCODE_DCL_TESS_DOMAIN:
        pInstruction->m_TessellatorDomainDecl.TessellatorDomain = DECODE_D3D11_SB_TESS_DOMAIN(Token);
        break;

    case D3D11_SB_OPCODE_DCL_TESS_PARTITIONING:
        pInstruction->m_TessellatorPartitioningDecl.TessellatorPartitioning = DECODE_D3D11_SB_TESS_PARTITIONING(Token);
        break;

    case D3D11_SB_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE:
        pInstruction->m_TessellatorOutputPrimitiveDecl.TessellatorOutputPrimitive = DECODE_D3D11_SB_TESS_OUTPUT_PRIMITIVE(Token);
        break;

    case D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR:
        pInstruction->m_HSMaxTessFactorDecl.MaxTessFactor = *(float*)m_pCurrentToken;
        m_pCurrentToken++;
        break;

    case D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
        pInstruction->m_HSForkPhaseInstanceCountDecl.InstanceCount = *(UINT*)m_pCurrentToken;
        m_pCurrentToken++;
        break;
    case D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT:
        pInstruction->m_HSJoinPhaseInstanceCountDecl.InstanceCount = *(UINT*)m_pCurrentToken;
        m_pCurrentToken++;
        break;
    case D3D11_SB_OPCODE_DCL_THREAD_GROUP:
        pInstruction->m_ThreadGroupDecl.x = *(UINT*)m_pCurrentToken++;
        pInstruction->m_ThreadGroupDecl.y = *(UINT*)m_pCurrentToken++;
        pInstruction->m_ThreadGroupDecl.z = *(UINT*)m_pCurrentToken++;
        break;
    case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED:
        pInstruction->m_TypedUAVDecl.Dimension = DECODE_D3D10_SB_RESOURCE_DIMENSION(Token);
        pInstruction->m_TypedUAVDecl.Flags = DECODE_D3D11_SB_RESOURCE_FLAGS(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_TypedUAVDecl.ReturnType[0] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 0);
        pInstruction->m_TypedUAVDecl.ReturnType[1] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 1);
        pInstruction->m_TypedUAVDecl.ReturnType[2] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 2);
        pInstruction->m_TypedUAVDecl.ReturnType[3] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*m_pCurrentToken, 3);
        m_pCurrentToken++;
        pInstruction->m_TypedUAVDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_TypedUAVDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;
    case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
        pInstruction->m_RawUAVDecl.Flags = DECODE_D3D11_SB_RESOURCE_FLAGS(Token);
        ParseOperand(&pInstruction->m_Operands[0]);       
        pInstruction->m_RawUAVDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_RawUAVDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;
    case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
        pInstruction->m_StructuredUAVDecl.Flags = DECODE_D3D11_SB_RESOURCE_FLAGS(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_StructuredUAVDecl.ByteStride = *(UINT*)m_pCurrentToken++;
        pInstruction->m_StructuredUAVDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_StructuredUAVDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;
    case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_RawTGSMDecl.ByteCount = *(UINT*)m_pCurrentToken++;
        break;
    case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED:
        ParseOperand(&pInstruction->m_Operands[0]);
        pInstruction->m_StructuredTGSMDecl.StructByteStride = *(UINT*)m_pCurrentToken++;
        pInstruction->m_StructuredTGSMDecl.StructCount = *(UINT*)m_pCurrentToken++;
        break;
    case D3D11_SB_OPCODE_DCL_RESOURCE_RAW:
        ParseOperand(&pInstruction->m_Operands[0]);       
        pInstruction->m_RawSRVDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_RawSRVDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;
    case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED:
        ParseOperand(&pInstruction->m_Operands[0]);       
        pInstruction->m_StructuredSRVDecl.ByteStride = *(UINT*)m_pCurrentToken++;
        pInstruction->m_StructuredSRVDecl.Space = 0;
        if(b51PlusShader)
        {
            pInstruction->m_StructuredSRVDecl.Space = (UINT)(*m_pCurrentToken++);
        }
        break;
    case D3D11_SB_OPCODE_SYNC:
        {
            DWORD flags = DECODE_D3D11_SB_SYNC_FLAGS(Token);
            pInstruction->m_SyncFlags.bThreadsInGroup = (flags & D3D11_SB_SYNC_THREADS_IN_GROUP) ? true : false;
            pInstruction->m_SyncFlags.bThreadGroupSharedMemory = (flags & D3D11_SB_SYNC_THREAD_GROUP_SHARED_MEMORY) ? true : false;
            pInstruction->m_SyncFlags.bUnorderedAccessViewMemoryGroup = (flags & D3D11_SB_SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP ) ? true : false;
            pInstruction->m_SyncFlags.bUnorderedAccessViewMemoryGlobal = (flags & D3D11_SB_SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL ) ? true : false;
        }
        break;
    case D3D10_SB_OPCODE_RESINFO:
        pInstruction->m_ResInfoReturnType = DECODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        ParseOperand(&pInstruction->m_Operands[1]);
        ParseOperand(&pInstruction->m_Operands[2]);
        break;

    case D3D10_1_SB_OPCODE_SAMPLE_INFO:
        pInstruction->m_InstructionReturnType = DECODE_D3D10_SB_INSTRUCTION_RETURN_TYPE(Token);
        ParseOperand(&pInstruction->m_Operands[0]);
        ParseOperand(&pInstruction->m_Operands[1]);
        break;

    case D3D10_SB_OPCODE_IF:
    case D3D10_SB_OPCODE_BREAKC:
    case D3D10_SB_OPCODE_CONTINUEC:
    case D3D10_SB_OPCODE_RETC:
    case D3D10_SB_OPCODE_DISCARD:
        pInstruction->SetTest(DECODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(Token));
        ParseOperand(&pInstruction->m_Operands[0]);
        break;
    case D3D10_SB_OPCODE_CALLC:
        pInstruction->SetTest(DECODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(Token));
        ParseOperand(&pInstruction->m_Operands[0]);
        ParseOperand(&pInstruction->m_Operands[1]);
        break;
    default:
        {
          
            for (UINT i=0; i < pInstruction->m_NumOperands; i++)
            {
                ParseOperand(&pInstruction->m_Operands[i]);
            }
            break;
        }
    }
    m_pCurrentToken = pStart + InstructionLength;
}

// ****************************************************************************
//
// class CShaderAsm
//
// ****************************************************************************

void CShaderAsm::EmitOperand(const COperandBase& operand)
{
    CShaderToken Token = ENCODE_D3D10_SB_OPERAND_TYPE(operand.m_Type) |
                            ENCODE_D3D10_SB_OPERAND_NUM_COMPONENTS(operand.m_NumComponents) |
                            ENCODE_D3D10_SB_OPERAND_EXTENDED(operand.m_bExtendedOperand);

    BOOL bProcessOperandIndices = FALSE;
    if (!(operand.m_Type == D3D10_SB_OPERAND_TYPE_IMMEDIATE32 ||
          operand.m_Type == D3D10_SB_OPERAND_TYPE_IMMEDIATE64))
    {
        Token |= ENCODE_D3D10_SB_OPERAND_INDEX_DIMENSION(operand.m_IndexDimension);
        if (operand.m_NumComponents == D3D10_SB_OPERAND_4_COMPONENT)
        {
            // Component selection mode
            Token |= ENCODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(operand.m_ComponentSelection);
            switch(operand.m_ComponentSelection)
            {
            case D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE:
                Token |= ENCODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(operand.m_WriteMask );
                break;
            case D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE:
                Token |= ENCODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE(operand.m_Swizzle[0],
                                                                operand.m_Swizzle[1],
                                                                operand.m_Swizzle[2],
                                                                operand.m_Swizzle[3]);
                break;
            case D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE:
            {
                Token |= ENCODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(operand.m_ComponentName);
                break;
            }
            default:
                throw E_FAIL;
            }
        }

        UINT NumDimensions = operand.m_IndexDimension;
        if (NumDimensions > 0)
        {
            bProcessOperandIndices = TRUE;
            // Encode index representation
            for (UINT i=0; i < NumDimensions; i++)
            {
                Token |= ENCODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(i, operand.m_IndexType[i]);
            }
        }
        FUNC(Token);
    }

    // Extended operand
    if (operand.m_bExtendedOperand)
    {
        Token = ENCODE_D3D10_SB_EXTENDED_OPERAND_TYPE(operand.m_ExtendedOperandType);
        if (operand.m_ExtendedOperandType == D3D10_SB_EXTENDED_OPERAND_MODIFIER)
        {
            Token |= ENCODE_D3D10_SB_EXTENDED_OPERAND_MODIFIER(operand.m_Modifier);
            Token |= ENCODE_D3D11_SB_OPERAND_MIN_PRECISION(operand.m_MinPrecision);
            Token |= ENCODE_D3D12_SB_OPERAND_NON_UNIFORM(operand.m_Nonuniform);
        }
        FUNC(Token);
    }

    if( operand.m_Type == D3D10_SB_OPERAND_TYPE_IMMEDIATE32 ||
        operand.m_Type == D3D10_SB_OPERAND_TYPE_IMMEDIATE64)
    {
        FUNC(Token);
        UINT n = 0;
        if (operand.m_NumComponents == D3D10_SB_OPERAND_4_COMPONENT)
            n = 4;
        else 
        if (operand.m_NumComponents == D3D10_SB_OPERAND_1_COMPONENT)
            n = 1;
        else
        {
            throw E_FAIL;
        }
        for (UINT i=0 ; i < n; i++)
        {
            FUNC(operand.m_Value[i]);
        }
    }

    // Operand indices
    if (bProcessOperandIndices)
    {
        const UINT NumDimensions = operand.m_IndexDimension;
        // Encode index representation
        for (UINT i=0; i < NumDimensions; i++)
        {
            switch (operand.m_IndexType[i])
            {
            case D3D10_SB_OPERAND_INDEX_IMMEDIATE32:
                FUNC(operand.m_Index[i].m_RegIndex);
                break;
            case D3D10_SB_OPERAND_INDEX_IMMEDIATE64:
                FUNC(operand.m_Index[i].m_RegIndexA[0]);
                FUNC(operand.m_Index[i].m_RegIndexA[1]);
                break;
            case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE:
                FUNC(operand.m_Index[i].m_RegIndex);
                // Fall through
            case D3D10_SB_OPERAND_INDEX_RELATIVE:
                {
                    D3D10_SB_OPERAND_TYPE RelRegType = operand.m_Index[i].m_RelRegType;
                    if( operand.m_Index[i].m_IndexDimension == D3D10_SB_OPERAND_INDEX_2D )
                    {
                        EmitOperand(COperand2D(RelRegType,
                                               operand.m_Index[i].m_RelIndex,
                                               operand.m_Index[i].m_RelIndex1,
                                               operand.m_Index[i].m_ComponentName,
                                               operand.m_Index[i].m_MinPrecision));
                    }
                    else
                    {
                        EmitOperand(COperand4(RelRegType,
                                              operand.m_Index[i].m_RelIndex,
                                              operand.m_Index[i].m_ComponentName,
                                              operand.m_Index[i].m_MinPrecision));
                    }
                }
                break;
            default:
                throw E_FAIL;
            }
        }
    }
}
//-----------------------------------------------------------------------------
void CShaderAsm::EmitInstruction(const CInstruction& instruction)
{
    UINT  OpCode;

    if(instruction.m_OpCode == D3D10_SB_OPCODE_CUSTOMDATA)
    {
        OPCODE(D3D10_SB_OPCODE_CUSTOMDATA);
        FUNC(instruction.m_CustomData.DataSizeInBytes/4 + 2);
        for(UINT i = 0;i < instruction.m_CustomData.DataSizeInBytes/4; i++)
            FUNC(((UINT*)instruction.m_CustomData.pData)[i]);


        ENDINSTRUCTION();
        return;
    }

    OpCode = ENCODE_D3D10_SB_OPCODE_TYPE(instruction.m_OpCode) | ENCODE_D3D10_SB_OPCODE_EXTENDED(instruction.m_ExtendedOpCodeCount > 0 ? true : false);
    switch (instruction.m_OpCode)
    {
    case D3D10_SB_OPCODE_IF:
    case D3D10_SB_OPCODE_BREAKC:
    case D3D10_SB_OPCODE_CALLC:
    case D3D10_SB_OPCODE_CONTINUEC:
    case D3D10_SB_OPCODE_RETC:
    case D3D10_SB_OPCODE_DISCARD:
        OpCode |= ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(instruction.Test());
        break;       
    case D3D10_SB_OPCODE_RESINFO:
        OpCode |= ENCODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(instruction.m_ResInfoReturnType);
        break;
    case D3D10_1_SB_OPCODE_SAMPLE_INFO:
        OpCode |= ENCODE_D3D10_SB_INSTRUCTION_RETURN_TYPE(instruction.m_InstructionReturnType);
        break;
    case D3D11_SB_OPCODE_SYNC:
        OpCode |= ENCODE_D3D11_SB_SYNC_FLAGS(
                  ( instruction.m_SyncFlags.bThreadsInGroup ? D3D11_SB_SYNC_THREADS_IN_GROUP : 0 ) |
                  ( instruction.m_SyncFlags.bThreadGroupSharedMemory ? D3D11_SB_SYNC_THREAD_GROUP_SHARED_MEMORY : 0 ) |
                  ( instruction.m_SyncFlags.bUnorderedAccessViewMemoryGlobal ? D3D11_SB_SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL : 0 ) |
                  ( instruction.m_SyncFlags.bUnorderedAccessViewMemoryGroup ? D3D11_SB_SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP : 0 ) );
        break;
    };
    OpCode |= ENCODE_D3D10_SB_INSTRUCTION_SATURATE(instruction.m_bSaturate);
    OpCode |= ENCODE_D3D11_SB_INSTRUCTION_PRECISE_VALUES(instruction.m_PreciseMask);
    OPCODE(OpCode);
    
    for(UINT i = 0; i < min(instruction.m_ExtendedOpCodeCount,(UINT)D3D11_SB_MAX_SIMULTANEOUS_EXTENDED_OPCODES); i++)
    {
        UINT  Extended = ENCODE_D3D10_SB_EXTENDED_OPCODE_TYPE(instruction.m_OpCodeEx[i]);
        switch( instruction.m_OpCodeEx[i] )
        {
        case D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS:
            {
                Extended |= ENCODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U, instruction.m_TexelOffset[0]);
                Extended |= ENCODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V, instruction.m_TexelOffset[1]);
                Extended |= ENCODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W, instruction.m_TexelOffset[2]);
            }
            break;
        case D3D11_SB_EXTENDED_OPCODE_RESOURCE_DIM:
            {
                Extended |= ENCODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION(instruction.m_ResourceDimEx) |
                    ENCODE_D3D11_SB_EXTENDED_RESOURCE_DIMENSION_STRUCTURE_STRIDE(instruction.m_ResourceDimStructureStrideEx);
            }
            break;
        case D3D11_SB_EXTENDED_OPCODE_RESOURCE_RETURN_TYPE:
            {
                for(UINT j = 0; j < 4; j++)
                {
                    Extended |= ENCODE_D3D11_SB_EXTENDED_RESOURCE_RETURN_TYPE(instruction.m_ResourceReturnTypeEx[j],j);
                }
            }
            break;
        }
        Extended |= ENCODE_D3D10_SB_OPCODE_EXTENDED((i + 1 < instruction.m_ExtendedOpCodeCount) ? true : false);
        FUNC(Extended);
    }
    for (UINT i=0; i < instruction.m_NumOperands; i++)
    {
        EmitOperand(instruction.m_Operands[i]);
    }
    ENDINSTRUCTION();
}

//*****************************************************************************
//
//  CInstruction
//
//*****************************************************************************
BOOL CInstruction::Disassemble( __out_ecount(StringSize) LPSTR pString, UINT StringSize)
{
    StringCchCopyA(pString, StringSize, g_InstructionInfo[m_OpCode].m_Name);
    return TRUE;
}


}; // name space D3D10ShaderBinary

// End of file : ShaderBinary.cpp
