mojoshader.c
branchtrunk
changeset 36 5ea7c5f6cf2d
parent 35 5749d174b537
child 38 506f3ba0957a
equal deleted inserted replaced
35:5749d174b537 36:5ea7c5f6cf2d
       
     1 /**
       
     2  * MojoShader; generate shader programs from bytecode of compiled
       
     3  *  Direct3D shaders.
       
     4  *
       
     5  * Please see the file LICENSE.txt in the source's root directory.
       
     6  *
       
     7  *  This file written by Ryan C. Gordon.
       
     8  */
       
     9 
       
    10 // !!! FIXME: I keep changing coding styles for symbols and typedefs.
       
    11 
       
    12 // !!! FIXME: do DEF* and DCL_* opcodes have to come before instructions?
       
    13 // !!! FIXME:  my reading of the msdn spec suggests no.
       
    14 
       
    15 // Shader bytecode format is described at MSDN:
       
    16 //  http://msdn2.microsoft.com/en-us/library/ms800307.aspx
       
    17 
       
    18 #include <stdio.h>
       
    19 #include <string.h>
       
    20 #include <stdlib.h>
       
    21 #include <stdint.h>
       
    22 #include <stdarg.h>
       
    23 #include <assert.h>
       
    24 
       
    25 #include "mojoshader.h"
       
    26 
       
    27 // This is the highest shader version we currently support.
       
    28 
       
    29 #define MAX_SHADER_MAJOR 3
       
    30 #define MAX_SHADER_MINOR 0
       
    31 
       
    32 
       
    33 // You get all the profiles unless you go out of your way to disable them.
       
    34 
       
    35 #ifndef SUPPORT_PROFILE_D3D
       
    36 #define SUPPORT_PROFILE_D3D 1
       
    37 #endif
       
    38 
       
    39 #ifndef SUPPORT_PROFILE_GLSL
       
    40 #define SUPPORT_PROFILE_GLSL 1
       
    41 #endif
       
    42 
       
    43 
       
    44 // Get basic wankery out of the way here...
       
    45 
       
    46 typedef unsigned int uint;  // this is a printf() helper. don't use for code.
       
    47 typedef uint8_t uint8;
       
    48 typedef uint32_t uint32;
       
    49 typedef int32_t int32;
       
    50 
       
    51 #ifdef __GNUC__
       
    52 #define ISPRINTF(x,y) __attribute__((format (printf, x, y)))
       
    53 #else
       
    54 #define ISPRINTF(x,y)
       
    55 #endif
       
    56 
       
    57 #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
       
    58 
       
    59 
       
    60 // Byteswap magic...
       
    61 
       
    62 #if ((defined __GNUC__) && (defined __POWERPC__))
       
    63     static inline uint32 SWAP32(uint32 x)
       
    64     {
       
    65         __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (x) : "r" (&x));
       
    66         return x;
       
    67     } // SWAP32
       
    68 #elif defined(__POWERPC__)
       
    69     static inline uint32 SWAP32(uint32 x)
       
    70     {
       
    71         return ( (((x) >> 24) & 0x000000FF) | (((x) >>  8) & 0x0000FF00) |
       
    72                  (((x) <<  8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) );
       
    73     } // SWAP32
       
    74 #else
       
    75 #   define SWAP32(x) (x)
       
    76 #endif
       
    77 
       
    78 
       
    79 // Shader model version magic.
       
    80 static inline uint32 ver_ui32(const uint8 major, const uint8 minor)
       
    81 {
       
    82     return ( (((uint32) major) << 16) | (((minor) == 0xFF) ? 0 : (minor)) );
       
    83 } // version_ui32
       
    84 
       
    85 #define SHADER_VERSION_SUPPORTED(maj, min) \
       
    86     (ver_ui32(maj, min) <= ver_ui32(MAX_SHADER_MAJOR, MAX_SHADER_MINOR))
       
    87 
       
    88 
       
    89 // predeclare.
       
    90 typedef struct Context Context;
       
    91 
       
    92 // one emit function for each opcode in each profile.
       
    93 typedef void (*emit_function)(Context *ctx);
       
    94 
       
    95 // one emit function for comments in each profile.
       
    96 typedef void (*emit_comment)(Context *ctx, const char *str);
       
    97 
       
    98 // one emit function for starting output in each profile.
       
    99 typedef void (*emit_start)(Context *ctx);
       
   100 
       
   101 // one emit function for ending output in each profile.
       
   102 typedef void (*emit_end)(Context *ctx);
       
   103 
       
   104 // one args function for each possible sequence of opcode arguments.
       
   105 typedef int (*args_function)(Context *ctx);
       
   106 
       
   107 // one state function for each opcode where we have state machine updates.
       
   108 typedef int (*state_function)(Context *ctx);
       
   109 
       
   110 typedef struct
       
   111 {
       
   112     const char *name;
       
   113     emit_start start_emitter;
       
   114     emit_end end_emitter;
       
   115     emit_comment comment_emitter;
       
   116 } Profile;
       
   117 
       
   118 
       
   119 typedef enum
       
   120 {
       
   121     SHADER_TYPE_UNKNOWN = -1,
       
   122     SHADER_TYPE_PIXEL,
       
   123     SHADER_TYPE_VERTEX,
       
   124     SHADER_TYPE_TOTAL
       
   125 } ShaderType;
       
   126 
       
   127 typedef enum
       
   128 {
       
   129     REGISTER_TYPE_TEMP = 0,
       
   130     REGISTER_TYPE_INPUT = 1,
       
   131     REGISTER_TYPE_CONST = 2,
       
   132     REGISTER_TYPE_ADDR = 3,
       
   133     REGISTER_TYPE_TEXTURE = 3,  // ALSO 3!
       
   134     REGISTER_TYPE_RASTOUT = 4,
       
   135     REGISTER_TYPE_ATTROUT = 5,
       
   136     REGISTER_TYPE_TEXCRDOUT = 6,
       
   137     REGISTER_TYPE_OUTPUT =  6, // ALSO 6!
       
   138     REGISTER_TYPE_CONSTINT =  7,
       
   139     REGISTER_TYPE_COLOROUT =  8,
       
   140     REGISTER_TYPE_DEPTHOUT =  9,
       
   141     REGISTER_TYPE_SAMPLER = 10,
       
   142     REGISTER_TYPE_CONST2 = 11,
       
   143     REGISTER_TYPE_CONST3 = 12,
       
   144     REGISTER_TYPE_CONST4 = 13,
       
   145     REGISTER_TYPE_CONSTBOOL = 14,
       
   146     REGISTER_TYPE_LOOP = 15,
       
   147     REGISTER_TYPE_TEMPFLOAT16 = 16,
       
   148     REGISTER_TYPE_MISCTYPE = 17,
       
   149     REGISTER_TYPE_LABEL = 18,
       
   150     REGISTER_TYPE_PREDICATE = 19,
       
   151     REGISTER_TYPE_MAX = 19
       
   152 } RegisterType;
       
   153 
       
   154 typedef enum
       
   155 {
       
   156     RASTOUT_TYPE_POSITION = 0,
       
   157     RASTOUT_TYPE_FOG = 1,
       
   158     RASTOUT_TYPE_POINT_SIZE = 2,
       
   159     RASTOUT_TYPE_MAX = 2
       
   160 } RastOutType;
       
   161 
       
   162 typedef enum
       
   163 {
       
   164     MISCTYPE_TYPE_POSITION = 0,
       
   165     MISCTYPE_TYPE_FACE = 1,
       
   166     MISCTYPE_TYPE_MAX = 1
       
   167 } MiscTypeType;
       
   168 
       
   169 typedef enum
       
   170 {
       
   171     DECLUSAGE_POSITION = 0,
       
   172     DECLUSAGE_BLENDWEIGHT = 1,
       
   173     DECLUSAGE_BLENDINDICES = 2,
       
   174     DECLUSAGE_NORMAL = 3,
       
   175     DECLUSAGE_PSIZE = 4,
       
   176     DECLUSAGE_TEXCOORD = 5,
       
   177     DECLUSAGE_TANGENT = 6,
       
   178     DECLUSAGE_BINORMAL = 7,
       
   179     DECLUSAGE_TESSFACTOR = 8,
       
   180     DECLUSAGE_POSITIONT = 9,
       
   181     DECLUSAGE_COLOR = 10,
       
   182     DECLUSAGE_FOG = 11,
       
   183     DECLUSAGE_DEPTH = 12,
       
   184     DECLUSAGE_SAMPLE = 13
       
   185 } DeclUsageType;
       
   186 
       
   187 typedef enum
       
   188 {
       
   189     TEXTURE_TYPE_2D = 2,
       
   190     TEXTURE_TYPE_CUBE = 3,
       
   191     TEXTURE_TYPE_VOLUME = 4,
       
   192 } TextureType;
       
   193 
       
   194 
       
   195 // A simple linked list of strings, so we can build the final output without
       
   196 //  realloc()ing for each new line, and easily insert lines into the middle
       
   197 //  of the output without much trouble.
       
   198 typedef struct OutputList
       
   199 {
       
   200     char *str;
       
   201     struct OutputList *next;
       
   202 } OutputList;
       
   203 
       
   204 
       
   205 // result modifiers.
       
   206 #define MOD_SATURATE 0x01
       
   207 #define MOD_PP 0x02
       
   208 #define MOD_CENTROID 0x04
       
   209 
       
   210 // source modifiers.
       
   211 typedef enum
       
   212 {
       
   213     SRCMOD_NONE,
       
   214     SRCMOD_NEGATE,
       
   215     SRCMOD_BIAS,
       
   216     SRCMOD_BIASNEGATE,
       
   217     SRCMOD_SIGN,
       
   218     SRCMOD_SIGNNEGATE,
       
   219     SRCMOD_COMPLEMENT,
       
   220     SRCMOD_X2,
       
   221     SRCMOD_X2NEGATE,
       
   222     SRCMOD_DZ,
       
   223     SRCMOD_DW,
       
   224     SRCMOD_ABS,
       
   225     SRCMOD_ABSNEGATE,
       
   226     SRCMOD_NOT,
       
   227     SRCMOD_TOTAL
       
   228 } SourceMod;
       
   229 
       
   230 
       
   231 typedef struct
       
   232 {
       
   233     const uint32 *token;   // this is the unmolested token in the stream.
       
   234     int regnum;
       
   235     int relative;
       
   236     int writemask;   // xyzw or rgba (all four, not split out).
       
   237     int writemask0;  // x or red
       
   238     int writemask1;  // y or green
       
   239     int writemask2;  // z or blue
       
   240     int writemask3;  // w or alpha
       
   241     int result_mod;
       
   242     int result_shift;
       
   243     int regtype;
       
   244 } DestArgInfo;
       
   245 
       
   246 typedef struct
       
   247 {
       
   248     const uint32 *token;   // this is the unmolested token in the stream.
       
   249     int regnum;
       
   250     int relative;
       
   251     int swizzle;  // xyzw (all four, not split out).
       
   252     int swizzle_x;
       
   253     int swizzle_y;
       
   254     int swizzle_z;
       
   255     int swizzle_w;
       
   256     int src_mod;
       
   257     int regtype;
       
   258 } SourceArgInfo;
       
   259 
       
   260 
       
   261 #define SCRATCH_BUFFER_SIZE 256
       
   262 #define SCRATCH_BUFFERS 10
       
   263 
       
   264 // Context...this is state that changes as we parse through a shader...
       
   265 struct Context
       
   266 {
       
   267     MOJOSHADER_malloc malloc;
       
   268     MOJOSHADER_free free;
       
   269     const uint32 *tokens;
       
   270     uint32 tokencount;
       
   271     OutputList output;
       
   272     OutputList *output_tail;
       
   273     int output_len; // total strlen; prevents walking the list just to malloc.
       
   274     const char *endline;
       
   275     int endline_len;
       
   276     const char *failstr;
       
   277     char scratch[SCRATCH_BUFFERS][SCRATCH_BUFFER_SIZE];
       
   278     int scratchidx;  // current scratch buffer.
       
   279     int profileid;
       
   280     const Profile *profile;
       
   281     ShaderType shader_type;
       
   282     uint32 major_ver;
       
   283     uint32 minor_ver;
       
   284     DestArgInfo dest_args[1];
       
   285     SourceArgInfo source_args[4];
       
   286     uint32 dwords[4];
       
   287     uint32 instruction_count;
       
   288     uint32 instruction_controls;
       
   289 };
       
   290 
       
   291 
       
   292 static inline char *get_scratch_buffer(Context *ctx)
       
   293 {
       
   294     ctx->scratchidx = (ctx->scratchidx + 1) % SCRATCH_BUFFERS;
       
   295     return ctx->scratch[ctx->scratchidx];
       
   296 } // get_scratch_buffer
       
   297 
       
   298 
       
   299 // Special-case return values from the parsing pipeline...
       
   300 #define FAIL (-1)
       
   301 #define END_OF_STREAM (-2)
       
   302 
       
   303 static const char *out_of_mem_string = "Out of memory";
       
   304 static inline int out_of_memory(Context *ctx)
       
   305 {
       
   306     if (ctx->failstr == NULL)
       
   307         ctx->failstr = out_of_mem_string;  // fail() would call malloc().
       
   308     return FAIL;
       
   309 } // out_of_memory
       
   310 
       
   311 
       
   312 static int failf(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
       
   313 static int failf(Context *ctx, const char *fmt, ...)
       
   314 {
       
   315     if (ctx->failstr == NULL)  // don't change existing error.
       
   316     {
       
   317         char *scratch = get_scratch_buffer(ctx);
       
   318         va_list ap;
       
   319         va_start(ap, fmt);
       
   320         const int len = vsnprintf(scratch,SCRATCH_BUFFER_SIZE,fmt,ap);
       
   321         va_end(ap);
       
   322 
       
   323         char *failstr = (char *) ctx->malloc(len + 1);
       
   324         if (failstr == NULL)
       
   325             out_of_memory(ctx);
       
   326         else
       
   327         {
       
   328             // see comments about scratch buffer overflow in output_line().
       
   329             if (len < SCRATCH_BUFFER_SIZE)
       
   330                 strcpy(failstr, scratch);  // copy it over.
       
   331             else
       
   332             {
       
   333                 va_start(ap, fmt);
       
   334                 vsnprintf(failstr, len + 1, fmt, ap);  // rebuild it.
       
   335                 va_end(ap);
       
   336             } // else
       
   337             ctx->failstr = failstr;
       
   338         } // else
       
   339     } // if
       
   340 
       
   341     return FAIL;
       
   342 } // failf
       
   343 
       
   344 
       
   345 static inline int fail(Context *ctx, const char *reason)
       
   346 {
       
   347     return failf(ctx, "%s", reason);
       
   348 } // fail
       
   349 
       
   350 
       
   351 static int output_line(Context *ctx, const char *fmt, ...) ISPRINTF(2,3);
       
   352 static int output_line(Context *ctx, const char *fmt, ...)
       
   353 {
       
   354     if (ctx->failstr != NULL)
       
   355         return FAIL;  // we failed previously, don't go on...
       
   356 
       
   357     OutputList *item = (OutputList *) ctx->malloc(sizeof (OutputList));
       
   358     if (item == NULL)
       
   359         return out_of_memory(ctx);
       
   360 
       
   361     char *scratch = get_scratch_buffer(ctx);
       
   362     va_list ap;
       
   363     va_start(ap, fmt);
       
   364     const int len = vsnprintf(scratch, SCRATCH_BUFFER_SIZE, fmt, ap);
       
   365     va_end(ap);
       
   366 
       
   367     item->str = (char *) ctx->malloc(len + 1);
       
   368     if (item->str == NULL)
       
   369     {
       
   370         free(item);
       
   371         return out_of_memory(ctx);
       
   372     } // if
       
   373 
       
   374     // If we overflowed our scratch buffer, that's okay. We were going to
       
   375     //  allocate anyhow...the scratch buffer just lets us avoid a second
       
   376     //  run of vsnprintf().
       
   377     if (len < SCRATCH_BUFFER_SIZE)
       
   378         strcpy(item->str, scratch);  // copy it over.
       
   379     else
       
   380     {
       
   381         va_start(ap, fmt);
       
   382         vsnprintf(item->str, len + 1, fmt, ap);  // rebuild it.
       
   383         va_end(ap);
       
   384     } // else
       
   385 
       
   386     item->next = NULL;
       
   387     ctx->output_tail->next = item;
       
   388     ctx->output_tail = item;
       
   389     ctx->output_len += len + ctx->endline_len;
       
   390     return 0;
       
   391 } // output_line
       
   392 
       
   393 
       
   394 
       
   395 // if SUPPORT_PROFILE_* isn't defined, we assume an implicit desire to support.
       
   396 #define AT_LEAST_ONE_PROFILE 0
       
   397 
       
   398 #if !SUPPORT_PROFILE_D3D
       
   399 #define PROFILE_EMITTER_D3D(op)
       
   400 #else
       
   401 #undef AT_LEAST_ONE_PROFILE
       
   402 #define AT_LEAST_ONE_PROFILE 1
       
   403 #define PROFILE_EMITTER_D3D(op) emit_D3D_##op,
       
   404 
       
   405 static const char *get_D3D_register_string(Context *ctx,
       
   406                                            RegisterType regtype,
       
   407                                            int regnum, char *regnum_str,
       
   408                                            size_t regnum_size)
       
   409 {
       
   410     const char *retval = NULL;
       
   411     int has_number = 1;
       
   412 
       
   413     switch (regtype)
       
   414     {
       
   415         case REGISTER_TYPE_TEMP:
       
   416             retval = "r";
       
   417             break;
       
   418 
       
   419         case REGISTER_TYPE_INPUT:
       
   420             retval = "v";
       
   421             break;
       
   422 
       
   423         case REGISTER_TYPE_CONST:
       
   424             retval = "c";
       
   425             break;
       
   426 
       
   427         case REGISTER_TYPE_CONST2:
       
   428             retval = "c";
       
   429             regnum += 2048;
       
   430             break;
       
   431 
       
   432         case REGISTER_TYPE_CONST3:
       
   433             retval = "c";
       
   434             regnum += 4096;
       
   435             break;
       
   436 
       
   437         case REGISTER_TYPE_CONST4:
       
   438             retval = "c";
       
   439             regnum += 6144;
       
   440             break;
       
   441 
       
   442         case REGISTER_TYPE_ADDR:  // (or REGISTER_TYPE_TEXTURE, same value.)
       
   443             retval = (ctx->shader_type == SHADER_TYPE_VERTEX) ? "a" : "t";
       
   444             break;
       
   445 
       
   446         case REGISTER_TYPE_RASTOUT:
       
   447             switch ((RastOutType) regnum)
       
   448             {
       
   449                 case RASTOUT_TYPE_POSITION: retval = "oPos"; break;
       
   450                 case RASTOUT_TYPE_FOG: retval = "oFog"; break;
       
   451                 case RASTOUT_TYPE_POINT_SIZE: retval = "oPts"; break;
       
   452             } // switch
       
   453             has_number = 0;
       
   454             break;
       
   455 
       
   456         case REGISTER_TYPE_ATTROUT:
       
   457             retval = "oD";
       
   458             break;
       
   459 
       
   460         case REGISTER_TYPE_TEXCRDOUT: // (or REGISTER_TYPE_OUTPUT, same value.)
       
   461             if ((ctx->shader_type==SHADER_TYPE_VERTEX) && (ctx->major_ver>=3))
       
   462                 retval = "o";
       
   463             else
       
   464                 retval = "oT";
       
   465             break;
       
   466 
       
   467         case REGISTER_TYPE_CONSTINT:
       
   468             retval = "i";
       
   469             break;
       
   470 
       
   471         case REGISTER_TYPE_COLOROUT:
       
   472             retval = "oC";
       
   473             break;
       
   474 
       
   475         case REGISTER_TYPE_DEPTHOUT:
       
   476             retval = "oDepth";
       
   477             has_number = 0;
       
   478             break;
       
   479 
       
   480         case REGISTER_TYPE_SAMPLER:
       
   481             retval = "s";
       
   482             break;
       
   483 
       
   484         case REGISTER_TYPE_CONSTBOOL:
       
   485             retval = "b";
       
   486             break;
       
   487 
       
   488         case REGISTER_TYPE_LOOP:
       
   489             retval = "aL";
       
   490             has_number = 0;
       
   491             break;
       
   492 
       
   493         // !!! FIXME: don't know what the asm string is for this..
       
   494         // case REGISTER_TYPE_TEMPFLOAT16:
       
   495 
       
   496         case REGISTER_TYPE_MISCTYPE:
       
   497             switch ((MiscTypeType) regnum)
       
   498             {
       
   499                 case MISCTYPE_TYPE_POSITION: retval = "vPos"; break;
       
   500                 case MISCTYPE_TYPE_FACE: retval = "vFace"; break;
       
   501             } // switch
       
   502             has_number = 0;
       
   503             break;
       
   504 
       
   505         case REGISTER_TYPE_LABEL:
       
   506             retval = "l";
       
   507             break;
       
   508 
       
   509         case REGISTER_TYPE_PREDICATE:
       
   510             retval = "p";
       
   511             break;
       
   512     } // switch
       
   513 
       
   514     if (has_number)
       
   515         snprintf(regnum_str, regnum_size, "%u", (uint) regnum);
       
   516     else
       
   517         regnum_str[0] = '\0';
       
   518 
       
   519     return retval;
       
   520 } // get_D3D_register_string
       
   521 
       
   522 
       
   523 static char *make_D3D_destarg_string(Context *ctx, const int idx)
       
   524 {
       
   525     if (idx >= STATICARRAYLEN(ctx->dest_args))
       
   526     {
       
   527         fail(ctx, "Too many destination args");
       
   528         return "";
       
   529     } // if
       
   530 
       
   531     const DestArgInfo *arg = &ctx->dest_args[idx];
       
   532 
       
   533     const char *result_shift_str = "";
       
   534     switch (arg->result_shift)
       
   535     {
       
   536         case 0x1: result_shift_str = "_x2"; break;
       
   537         case 0x2: result_shift_str = "_x4"; break;
       
   538         case 0x3: result_shift_str = "_x8"; break;
       
   539         case 0xD: result_shift_str = "_d8"; break;
       
   540         case 0xE: result_shift_str = "_d4"; break;
       
   541         case 0xF: result_shift_str = "_d2"; break;
       
   542     } // switch
       
   543 
       
   544     const char *sat_str = (arg->result_mod & MOD_SATURATE) ? "_sat" : "";
       
   545     const char *pp_str = (arg->result_mod & MOD_PP) ? "_pp" : "";
       
   546     const char *cent_str = (arg->result_mod & MOD_CENTROID) ? "_centroid" : "";
       
   547 
       
   548     char regnum_str[16];
       
   549     const char *regtype_str = get_D3D_register_string(ctx,
       
   550                                         (RegisterType) arg->regtype,
       
   551                                         arg->regnum, regnum_str,
       
   552                                         sizeof (regnum_str));
       
   553     if (regtype_str == NULL)
       
   554     {
       
   555         fail(ctx, "Unknown destination register type.");
       
   556         return "";
       
   557     } // if
       
   558 
       
   559     char writemask_str[6];
       
   560     int i = 0;
       
   561     if (arg->writemask != 0xF)  // 0xF == 1111. No explicit mask.
       
   562     {
       
   563         writemask_str[i++] = '.';
       
   564         if (arg->writemask0) writemask_str[i++] = 'x';
       
   565         if (arg->writemask1) writemask_str[i++] = 'y';
       
   566         if (arg->writemask2) writemask_str[i++] = 'z';
       
   567         if (arg->writemask3) writemask_str[i++] = 'w';
       
   568     } // if
       
   569     writemask_str[i] = '\0';
       
   570     assert(i < sizeof (writemask_str));
       
   571 
       
   572     // may turn out something like "_x2_sat_pp_centroid r0.xyzw" ...
       
   573     char *retval = get_scratch_buffer(ctx);
       
   574     snprintf(retval, SCRATCH_BUFFER_SIZE, "%s%s%s%s %s%s%s",
       
   575              result_shift_str, sat_str, pp_str, cent_str,
       
   576              regtype_str, regnum_str, writemask_str);
       
   577     return retval;
       
   578 } // make_D3D_destarg_string
       
   579 
       
   580 
       
   581 static char *make_D3D_sourcearg_string(Context *ctx, const int idx)
       
   582 {
       
   583     if (idx >= STATICARRAYLEN(ctx->source_args))
       
   584     {
       
   585         fail(ctx, "Too many source args");
       
   586         return "";
       
   587     } // if
       
   588 
       
   589     const SourceArgInfo *arg = &ctx->source_args[idx];
       
   590 
       
   591     const char *premod_str = "";
       
   592     const char *postmod_str = "";
       
   593     switch ((SourceMod) arg->src_mod)
       
   594     {
       
   595         case SRCMOD_NEGATE:
       
   596             premod_str = "-";
       
   597             break;
       
   598 
       
   599         case SRCMOD_BIASNEGATE:
       
   600             premod_str = "-";
       
   601             // fall through.
       
   602         case SRCMOD_BIAS:
       
   603             postmod_str = "_bias";
       
   604             break;
       
   605 
       
   606         case SRCMOD_SIGNNEGATE:
       
   607             premod_str = "-";
       
   608             // fall through.
       
   609         case SRCMOD_SIGN:
       
   610             postmod_str = "_bx2";
       
   611             break;
       
   612 
       
   613         case SRCMOD_COMPLEMENT:
       
   614             premod_str = "1-";
       
   615             break;
       
   616 
       
   617         case SRCMOD_X2NEGATE:
       
   618             premod_str = "-";
       
   619             // fall through.
       
   620         case SRCMOD_X2:
       
   621             postmod_str = "_x2";
       
   622             break;
       
   623 
       
   624         case SRCMOD_DZ:
       
   625             postmod_str = "_dz";
       
   626             break;
       
   627 
       
   628         case SRCMOD_DW:
       
   629             postmod_str = "_dw";
       
   630             break;
       
   631 
       
   632         case SRCMOD_ABSNEGATE:
       
   633             premod_str = "-";
       
   634             // fall through.
       
   635         case SRCMOD_ABS:
       
   636             postmod_str = "_abs";
       
   637             break;
       
   638 
       
   639         case SRCMOD_NOT:
       
   640             premod_str = "!";
       
   641             break;
       
   642     } // switch
       
   643 
       
   644 
       
   645     char regnum_str[16];
       
   646     const char *regtype_str = get_D3D_register_string(ctx,
       
   647                                         (RegisterType) arg->regtype,
       
   648                                         arg->regnum, regnum_str,
       
   649                                         sizeof (regnum_str));
       
   650 
       
   651     if (regtype_str == NULL)
       
   652     {
       
   653         fail(ctx, "Unknown source register type.");
       
   654         return "";
       
   655     } // if
       
   656 
       
   657     char swizzle_str[6];
       
   658     int i = 0;
       
   659     if (arg->swizzle != 0xE4)  // 0xE4 == 11100100 ... 3 2 1 0. No swizzle.
       
   660     {
       
   661         static const char channel[] = { 'x', 'y', 'z', 'w' };
       
   662         swizzle_str[i++] = '.';
       
   663         swizzle_str[i++] = channel[arg->swizzle_x];
       
   664         swizzle_str[i++] = channel[arg->swizzle_y];
       
   665         swizzle_str[i++] = channel[arg->swizzle_z];
       
   666         swizzle_str[i++] = channel[arg->swizzle_w];
       
   667 
       
   668         // .xyzz is the same as .xyz, .z is the same as .zzzz, etc.
       
   669         while (swizzle_str[i-1] == swizzle_str[i-2])
       
   670             i--;
       
   671     } // if
       
   672     swizzle_str[i] = '\0';
       
   673     assert(i < sizeof (swizzle_str));
       
   674 
       
   675     char *retval = get_scratch_buffer(ctx);
       
   676     snprintf(retval, SCRATCH_BUFFER_SIZE, "%s%s%s%s",
       
   677              premod_str, regtype_str, postmod_str, swizzle_str);
       
   678     return retval;
       
   679 } // make_D3D_sourcearg_string
       
   680 
       
   681 
       
   682 static void emit_D3D_start(Context *ctx)
       
   683 {
       
   684     const uint major = (uint) ctx->major_ver;
       
   685     const uint minor = (uint) ctx->minor_ver;
       
   686     const char *shadertype_str = NULL;
       
   687     char minor_str[16];
       
   688 
       
   689     if (minor == 0xFF)
       
   690         strcpy(minor_str, "sw");
       
   691     else if (minor == 0x1)  // apparently this is "vs_2_x". Weird.
       
   692         strcpy(minor_str, "x");
       
   693     else
       
   694         snprintf(minor_str, sizeof (minor_str), "%u", (uint) minor);
       
   695 
       
   696     if (ctx->shader_type == SHADER_TYPE_PIXEL)
       
   697         shadertype_str = "ps";
       
   698     else if (ctx->shader_type == SHADER_TYPE_VERTEX)
       
   699         shadertype_str = "vs";
       
   700     else
       
   701     {
       
   702         failf(ctx, "Shader type %u unsupported in this profile.",
       
   703               (uint) ctx->shader_type);
       
   704         return;
       
   705     } // else
       
   706 
       
   707     output_line(ctx, "%s_%u_%s", shadertype_str, major, minor_str);
       
   708 } // emit_D3D_start
       
   709 
       
   710 
       
   711 static void emit_D3D_end(Context *ctx)
       
   712 {
       
   713     output_line(ctx, "end");
       
   714 } // emit_D3D_end
       
   715 
       
   716 
       
   717 static void emit_D3D_comment(Context *ctx, const char *str)
       
   718 {
       
   719     output_line(ctx, "; %s", str);
       
   720 } // emit_D3D_comment
       
   721 
       
   722 
       
   723 static void emit_D3D_RESERVED(Context *ctx)
       
   724 {
       
   725     // do nothing; fails in the state machine.
       
   726 } // emit_D3D_RESERVED
       
   727 
       
   728 
       
   729 // Generic D3D opcode emitters. A list of macros generate all the entry points
       
   730 //  that call into these...
       
   731 
       
   732 static char *lowercase(char *dst, const char *src)
       
   733 {
       
   734     int i = 0;
       
   735     do
       
   736     {
       
   737         const char ch = src[i];
       
   738         dst[i] = (((ch >= 'A') && (ch <= 'Z')) ? (ch - ('A' - 'a')) : ch);
       
   739     } while (src[i++]);
       
   740     return dst;
       
   741 } // lowercase
       
   742 
       
   743 
       
   744 static void emit_D3D_opcode_d(Context *ctx, const char *opcode)
       
   745 {
       
   746     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
   747     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   748     output_line(ctx, "%s%s", opcode, dst0);
       
   749 } // emit_D3D_opcode_d
       
   750 
       
   751 
       
   752 static void emit_D3D_opcode_s(Context *ctx, const char *opcode)
       
   753 {
       
   754     const char *src0 = make_D3D_destarg_string(ctx, 0);
       
   755     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   756     output_line(ctx, "%s %s", opcode, src0);
       
   757 } // emit_D3D_opcode_s
       
   758 
       
   759 
       
   760 static void emit_D3D_opcode_ss(Context *ctx, const char *opcode)
       
   761 {
       
   762     const char *src0 = make_D3D_sourcearg_string(ctx, 0);
       
   763     const char *src1 = make_D3D_sourcearg_string(ctx, 1);
       
   764     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   765     output_line(ctx, "%s %s, %s", opcode, src0, src1);
       
   766 } // emit_D3D_opcode_s
       
   767 
       
   768 
       
   769 static void emit_D3D_opcode_ds(Context *ctx, const char *opcode)
       
   770 {
       
   771     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
   772     const char *src0 = make_D3D_sourcearg_string(ctx, 0);
       
   773     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   774     output_line(ctx, "%s%s, %s", opcode, dst0, src0);
       
   775 } // emit_D3D_opcode_ds
       
   776 
       
   777 
       
   778 static void emit_D3D_opcode_dss(Context *ctx, const char *opcode)
       
   779 {
       
   780     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
   781     const char *src0 = make_D3D_sourcearg_string(ctx, 0);
       
   782     const char *src1 = make_D3D_sourcearg_string(ctx, 1);
       
   783     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   784     output_line(ctx, "%s%s, %s, %s", opcode, dst0, src0, src1);
       
   785 } // emit_D3D_opcode_dss
       
   786 
       
   787 
       
   788 static void emit_D3D_opcode_dsss(Context *ctx, const char *opcode)
       
   789 {
       
   790     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
   791     const char *src0 = make_D3D_sourcearg_string(ctx, 0);
       
   792     const char *src1 = make_D3D_sourcearg_string(ctx, 1);
       
   793     const char *src2 = make_D3D_sourcearg_string(ctx, 2);
       
   794     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   795     output_line(ctx, "%s%s, %s, %s, %s", opcode, dst0, src0, src1, src2);
       
   796 } // emit_D3D_opcode_dsss
       
   797 
       
   798 
       
   799 static void emit_D3D_opcode_dssss(Context *ctx, const char *opcode)
       
   800 {
       
   801     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
   802     const char *src0 = make_D3D_sourcearg_string(ctx, 0);
       
   803     const char *src1 = make_D3D_sourcearg_string(ctx, 1);
       
   804     const char *src2 = make_D3D_sourcearg_string(ctx, 2);
       
   805     const char *src3 = make_D3D_sourcearg_string(ctx, 3);
       
   806     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   807     output_line(ctx,"%s%s, %s, %s, %s, %s",opcode,dst0,src0,src1,src2,src3);
       
   808 } // emit_D3D_opcode_dssss
       
   809 
       
   810 
       
   811 static void emit_D3D_opcode(Context *ctx, const char *opcode)
       
   812 {
       
   813     opcode = lowercase(get_scratch_buffer(ctx), opcode);
       
   814     output_line(ctx, "%s", opcode);
       
   815 } // emit_D3D_opcode_dssss
       
   816 
       
   817 
       
   818 #define EMIT_D3D_OPCODE_FUNC(op) \
       
   819     static void emit_D3D_##op(Context *ctx) { \
       
   820         emit_D3D_opcode(ctx, #op); \
       
   821     }
       
   822 #define EMIT_D3D_OPCODE_D_FUNC(op) \
       
   823     static void emit_D3D_##op(Context *ctx) { \
       
   824         emit_D3D_opcode_d(ctx, #op); \
       
   825     }
       
   826 #define EMIT_D3D_OPCODE_S_FUNC(op) \
       
   827     static void emit_D3D_##op(Context *ctx) { \
       
   828         emit_D3D_opcode_s(ctx, #op); \
       
   829     }
       
   830 #define EMIT_D3D_OPCODE_SS_FUNC(op) \
       
   831     static void emit_D3D_##op(Context *ctx) { \
       
   832         emit_D3D_opcode_ss(ctx, #op); \
       
   833     }
       
   834 #define EMIT_D3D_OPCODE_DS_FUNC(op) \
       
   835     static void emit_D3D_##op(Context *ctx) { \
       
   836         emit_D3D_opcode_ds(ctx, #op); \
       
   837     }
       
   838 #define EMIT_D3D_OPCODE_DSS_FUNC(op) \
       
   839     static void emit_D3D_##op(Context *ctx) { \
       
   840         emit_D3D_opcode_dss(ctx, #op); \
       
   841     }
       
   842 #define EMIT_D3D_OPCODE_DSSS_FUNC(op) \
       
   843     static void emit_D3D_##op(Context *ctx) { \
       
   844         emit_D3D_opcode_dsss(ctx, #op); \
       
   845     }
       
   846 #define EMIT_D3D_OPCODE_DSSSS_FUNC(op) \
       
   847     static void emit_D3D_##op(Context *ctx) { \
       
   848         emit_D3D_opcode_dssss(ctx, #op); \
       
   849     }
       
   850 
       
   851 EMIT_D3D_OPCODE_FUNC(NOP)
       
   852 EMIT_D3D_OPCODE_DS_FUNC(MOV)
       
   853 EMIT_D3D_OPCODE_DSS_FUNC(ADD)
       
   854 EMIT_D3D_OPCODE_DSS_FUNC(SUB)
       
   855 EMIT_D3D_OPCODE_DSSS_FUNC(MAD)
       
   856 EMIT_D3D_OPCODE_DSS_FUNC(MUL)
       
   857 EMIT_D3D_OPCODE_DS_FUNC(RCP)
       
   858 EMIT_D3D_OPCODE_DS_FUNC(RSQ)
       
   859 EMIT_D3D_OPCODE_DSS_FUNC(DP3)
       
   860 EMIT_D3D_OPCODE_DSS_FUNC(DP4)
       
   861 EMIT_D3D_OPCODE_DSS_FUNC(MIN)
       
   862 EMIT_D3D_OPCODE_DSS_FUNC(MAX)
       
   863 EMIT_D3D_OPCODE_DSS_FUNC(SLT)
       
   864 EMIT_D3D_OPCODE_DSS_FUNC(SGE)
       
   865 EMIT_D3D_OPCODE_DS_FUNC(EXP)
       
   866 EMIT_D3D_OPCODE_DS_FUNC(LOG)
       
   867 EMIT_D3D_OPCODE_DS_FUNC(LIT)
       
   868 EMIT_D3D_OPCODE_DSS_FUNC(DST)
       
   869 EMIT_D3D_OPCODE_DSSS_FUNC(LRP)
       
   870 EMIT_D3D_OPCODE_DS_FUNC(FRC)
       
   871 EMIT_D3D_OPCODE_DSS_FUNC(M4X4)
       
   872 EMIT_D3D_OPCODE_DSS_FUNC(M4X3)
       
   873 EMIT_D3D_OPCODE_DSS_FUNC(M3X4)
       
   874 EMIT_D3D_OPCODE_DSS_FUNC(M3X3)
       
   875 EMIT_D3D_OPCODE_DSS_FUNC(M3X2)
       
   876 EMIT_D3D_OPCODE_S_FUNC(CALL)
       
   877 EMIT_D3D_OPCODE_SS_FUNC(CALLNZ)
       
   878 EMIT_D3D_OPCODE_SS_FUNC(LOOP)
       
   879 EMIT_D3D_OPCODE_FUNC(RET)
       
   880 EMIT_D3D_OPCODE_FUNC(ENDLOOP)
       
   881 EMIT_D3D_OPCODE_S_FUNC(LABEL)
       
   882 EMIT_D3D_OPCODE_DSS_FUNC(POW)
       
   883 EMIT_D3D_OPCODE_DSS_FUNC(CRS)
       
   884 EMIT_D3D_OPCODE_DSSS_FUNC(SGN)
       
   885 EMIT_D3D_OPCODE_DS_FUNC(ABS)
       
   886 EMIT_D3D_OPCODE_DS_FUNC(NRM)
       
   887 EMIT_D3D_OPCODE_DS_FUNC(SINCOS)
       
   888 EMIT_D3D_OPCODE_S_FUNC(REP)
       
   889 EMIT_D3D_OPCODE_FUNC(ENDREP)
       
   890 EMIT_D3D_OPCODE_S_FUNC(IF)
       
   891 EMIT_D3D_OPCODE_FUNC(ELSE)
       
   892 EMIT_D3D_OPCODE_FUNC(ENDIF)
       
   893 EMIT_D3D_OPCODE_FUNC(BREAK)
       
   894 EMIT_D3D_OPCODE_DS_FUNC(MOVA)
       
   895 EMIT_D3D_OPCODE_FUNC(TEXCOORD) // !!! FIXME!
       
   896 EMIT_D3D_OPCODE_D_FUNC(TEXKILL)
       
   897 EMIT_D3D_OPCODE_FUNC(TEX) // !!! FIXME!
       
   898 EMIT_D3D_OPCODE_DS_FUNC(TEXBEM)
       
   899 EMIT_D3D_OPCODE_DS_FUNC(TEXBEML)
       
   900 EMIT_D3D_OPCODE_DS_FUNC(TEXREG2AR)
       
   901 EMIT_D3D_OPCODE_DS_FUNC(TEXREG2GB)
       
   902 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X2PAD)
       
   903 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X2TEX)
       
   904 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3PAD)
       
   905 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3TEX)
       
   906 EMIT_D3D_OPCODE_DSS_FUNC(TEXM3X3SPEC)
       
   907 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3VSPEC)
       
   908 EMIT_D3D_OPCODE_DS_FUNC(EXPP)
       
   909 EMIT_D3D_OPCODE_DS_FUNC(LOGP)
       
   910 EMIT_D3D_OPCODE_DSSS_FUNC(CND)
       
   911 EMIT_D3D_OPCODE_DS_FUNC(TEXREG2RGB)
       
   912 EMIT_D3D_OPCODE_DS_FUNC(TEXDP3TEX)
       
   913 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X2DEPTH)
       
   914 EMIT_D3D_OPCODE_DS_FUNC(TEXDP3)
       
   915 EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3)
       
   916 EMIT_D3D_OPCODE_D_FUNC(TEXDEPTH)
       
   917 EMIT_D3D_OPCODE_DSSS_FUNC(CMP)
       
   918 EMIT_D3D_OPCODE_DSS_FUNC(BEM)
       
   919 EMIT_D3D_OPCODE_DSSS_FUNC(DP2ADD)
       
   920 EMIT_D3D_OPCODE_DS_FUNC(DSX)
       
   921 EMIT_D3D_OPCODE_DS_FUNC(DSY)
       
   922 EMIT_D3D_OPCODE_DSSSS_FUNC(TEXLDD)
       
   923 EMIT_D3D_OPCODE_DSS_FUNC(TEXLDL)
       
   924 EMIT_D3D_OPCODE_S_FUNC(BREAKP)
       
   925 
       
   926 // special cases for comparison opcodes...
       
   927 static const char *get_D3D_comparison_string(Context *ctx)
       
   928 {
       
   929     static const char *comps[] = {
       
   930         "", "_gt", "_eq", "_ge", "_lt", "_ne", "_le"
       
   931     };
       
   932 
       
   933     if (ctx->instruction_controls >= STATICARRAYLEN(comps))
       
   934     {
       
   935         fail(ctx, "unknown comparison control");
       
   936         return "";
       
   937     } // if
       
   938 
       
   939     return comps[ctx->instruction_controls];
       
   940 } // get_D3D_comparison_string
       
   941 
       
   942 static void emit_D3D_BREAKC(Context *ctx)
       
   943 {
       
   944     char op[16];
       
   945     snprintf(op, sizeof (op), "break%s", get_D3D_comparison_string(ctx));
       
   946     emit_D3D_opcode_ss(ctx, op);
       
   947 } // emit_D3D_BREAKC
       
   948 
       
   949 static void emit_D3D_IFC(Context *ctx)
       
   950 {
       
   951     char op[16];
       
   952     snprintf(op, sizeof (op), "if%s", get_D3D_comparison_string(ctx));
       
   953     emit_D3D_opcode_ss(ctx, op);
       
   954 } // emit_D3D_IFC
       
   955 
       
   956 static void emit_D3D_SETP(Context *ctx)
       
   957 {
       
   958     char op[16];
       
   959     snprintf(op, sizeof (op), "setp%s", get_D3D_comparison_string(ctx));
       
   960     emit_D3D_opcode_dss(ctx, op);
       
   961 } // emit_D3D_SETP
       
   962 
       
   963 // !!! FIXME: this is sort of nasty.
       
   964 static void floatstr(Context *ctx, char *buf, size_t bufsize, float f)
       
   965 {
       
   966     const size_t len = snprintf(buf, bufsize, "%f", f);
       
   967     if (len >= bufsize)
       
   968         fail(ctx, "BUG: internal buffer is too small");
       
   969     else
       
   970     {
       
   971         char *end = buf + len;
       
   972         char *ptr = strchr(buf, '.');
       
   973         if (ptr == NULL)
       
   974             return;  // done.
       
   975 
       
   976         while (--end != ptr)
       
   977         {
       
   978             if (*end != '0')
       
   979             {
       
   980                 end++;
       
   981                 break;
       
   982             } // if
       
   983         } // while
       
   984         *end = '\0';  // chop extra '0' or all decimal places off.
       
   985     } // else
       
   986 } // floatstr
       
   987 
       
   988 static void emit_D3D_DEF(Context *ctx)
       
   989 {
       
   990     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
   991     const float *val = (const float *) ctx->dwords; // !!! FIXME: could be int?
       
   992     char val0[32];
       
   993     char val1[32];
       
   994     char val2[32];
       
   995     char val3[32];
       
   996     floatstr(ctx, val0, sizeof (val0), val[0]);
       
   997     floatstr(ctx, val1, sizeof (val1), val[1]);
       
   998     floatstr(ctx, val2, sizeof (val2), val[2]);
       
   999     floatstr(ctx, val3, sizeof (val3), val[3]);
       
  1000     output_line(ctx, "def%s, %s, %s, %s, %s", dst0, val0, val1, val2, val3);
       
  1001 } // emit_D3D_DEF
       
  1002 
       
  1003 static void emit_D3D_DEFI(Context *ctx)
       
  1004 {
       
  1005     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
  1006     const int32 *x = (const int32 *) ctx->dwords;
       
  1007     output_line(ctx, "defi%s, %d, %d, %d, %d", dst0,
       
  1008                 (int) x[0], (int) x[1], (int) x[2], (int) x[3]);
       
  1009 } // emit_D3D_DEFI
       
  1010 
       
  1011 static void emit_D3D_DEFB(Context *ctx)
       
  1012 {
       
  1013     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
  1014     output_line(ctx, "defb%s, %s", dst0, ctx->dwords[0] ? "true" : "false");
       
  1015 } // emit_D3D_DEFB
       
  1016 
       
  1017 
       
  1018 static void emit_D3D_DCL(Context *ctx)
       
  1019 {
       
  1020     const char *dst0 = make_D3D_destarg_string(ctx, 0);
       
  1021     const DestArgInfo *arg = &ctx->dest_args[0];
       
  1022     const char *usage_str = "";
       
  1023     char index_str[16] = { '\0' };
       
  1024 
       
  1025     if (ctx->shader_type == SHADER_TYPE_VERTEX)
       
  1026     {
       
  1027         static const char *usagestrs[] = {
       
  1028             "_position", "_blendweight", "_blendindices", "_normal",
       
  1029             "_psize", "_texcoord", "_tangent", "_binormal", "_tessfactor",
       
  1030             "_positiont", "_color", "_fog", "_depth", "_sample"
       
  1031         };
       
  1032 
       
  1033         const uint32 usage = ctx->dwords[0];
       
  1034         const uint32 index = ctx->dwords[1];
       
  1035 
       
  1036         if (usage >= STATICARRAYLEN(usagestrs))
       
  1037         {
       
  1038             fail(ctx, "unknown DCL usage");
       
  1039             return;
       
  1040         } // if
       
  1041 
       
  1042         usage_str = usagestrs[usage];
       
  1043 
       
  1044         if (index != 0)
       
  1045             snprintf(index_str, sizeof (index_str), "%u", (uint) index);
       
  1046     } // if
       
  1047 
       
  1048     else if (arg->regtype == REGISTER_TYPE_SAMPLER)
       
  1049     {
       
  1050         switch ((const TextureType) ctx->dwords[0])
       
  1051         {
       
  1052             case TEXTURE_TYPE_2D: usage_str = "_2d"; break;
       
  1053             case TEXTURE_TYPE_CUBE: usage_str = "_cube"; break;
       
  1054             case TEXTURE_TYPE_VOLUME: usage_str = "_volume"; break;
       
  1055             default: fail(ctx, "unknown sampler texture type"); return;
       
  1056         } // switch
       
  1057     } // else if
       
  1058 
       
  1059     output_line(ctx, "dcl%s%s%s", usage_str, index_str, dst0);
       
  1060 } // emit_D3D_DCL
       
  1061 
       
  1062 
       
  1063 #undef EMIT_D3D_OPCODE_FUNC
       
  1064 #undef EMIT_D3D_OPCODE_D_FUNC
       
  1065 #undef EMIT_D3D_OPCODE_S_FUNC
       
  1066 #undef EMIT_D3D_OPCODE_SS_FUNC
       
  1067 #undef EMIT_D3D_OPCODE_DS_FUNC
       
  1068 #undef EMIT_D3D_OPCODE_DSS_FUNC
       
  1069 #undef EMIT_D3D_OPCODE_DSSS_FUNC
       
  1070 #undef EMIT_D3D_OPCODE_DSSSS_FUNC
       
  1071 
       
  1072 #endif  // SUPPORT_PROFILE_D3D
       
  1073 
       
  1074 
       
  1075 
       
  1076 #if !SUPPORT_PROFILE_GLSL
       
  1077 #define PROFILE_EMITTER_GLSL(op)
       
  1078 #else
       
  1079 #undef AT_LEAST_ONE_PROFILE
       
  1080 #define AT_LEAST_ONE_PROFILE 1
       
  1081 #define PROFILE_EMITTER_GLSL(op) emit_GLSL_##op,
       
  1082 
       
  1083 static void emit_GLSL_start(Context *ctx)
       
  1084 {
       
  1085     const uint major = (uint) ctx->major_ver;
       
  1086     const uint minor = (uint) ctx->minor_ver;
       
  1087     if (ctx->shader_type == SHADER_TYPE_PIXEL)
       
  1088         output_line(ctx, "// Pixel shader, version %u.%u", major, minor);
       
  1089     else if (ctx->shader_type == SHADER_TYPE_VERTEX)
       
  1090         output_line(ctx, "// Vertex shader, version %u.%u", major, minor);
       
  1091     else
       
  1092     {
       
  1093         failf(ctx, "Shader type %u unsupported in this profile.",
       
  1094               (uint) ctx->shader_type);
       
  1095     } // else
       
  1096 
       
  1097     output_line(ctx, "void main() {");
       
  1098 } // emit_GLSL_start
       
  1099 
       
  1100 static void emit_GLSL_end(Context *ctx)
       
  1101 {
       
  1102     output_line(ctx, "}");
       
  1103 } // emit_GLSL_end
       
  1104 
       
  1105 static void emit_GLSL_comment(Context *ctx, const char *str)
       
  1106 {
       
  1107     output_line(ctx, "// %s", str);
       
  1108 } // emit_GLSL_comment
       
  1109 
       
  1110 static void emit_GLSL_NOP(Context *ctx)
       
  1111 {
       
  1112     // no-op is a no-op.  :)
       
  1113 } // emit_GLSL_NOP
       
  1114 
       
  1115 static void emit_GLSL_MOV(Context *ctx)
       
  1116 {
       
  1117     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1118 } // emit_GLSL_MOV
       
  1119 
       
  1120 static void emit_GLSL_ADD(Context *ctx)
       
  1121 {
       
  1122     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1123 } // emit_GLSL_ADD
       
  1124 
       
  1125 static void emit_GLSL_SUB(Context *ctx)
       
  1126 {
       
  1127     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1128 } // emit_GLSL_SUB
       
  1129 
       
  1130 static void emit_GLSL_MAD(Context *ctx)
       
  1131 {
       
  1132     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1133 } // emit_GLSL_MAD
       
  1134 
       
  1135 static void emit_GLSL_MUL(Context *ctx)
       
  1136 {
       
  1137     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1138 } // emit_GLSL_MUL
       
  1139 
       
  1140 static void emit_GLSL_RCP(Context *ctx)
       
  1141 {
       
  1142     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1143 } // emit_GLSL_RCP
       
  1144 
       
  1145 static void emit_GLSL_RSQ(Context *ctx)
       
  1146 {
       
  1147     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1148 } // emit_GLSL_RSQ
       
  1149 
       
  1150 static void emit_GLSL_DP3(Context *ctx)
       
  1151 {
       
  1152     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1153 } // emit_GLSL_DP3
       
  1154 
       
  1155 static void emit_GLSL_DP4(Context *ctx)
       
  1156 {
       
  1157     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1158 } // emit_GLSL_DP4
       
  1159 
       
  1160 static void emit_GLSL_MIN(Context *ctx)
       
  1161 {
       
  1162     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1163 } // emit_GLSL_MIN
       
  1164 
       
  1165 static void emit_GLSL_MAX(Context *ctx)
       
  1166 {
       
  1167     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1168 } // emit_GLSL_MAX
       
  1169 
       
  1170 static void emit_GLSL_SLT(Context *ctx)
       
  1171 {
       
  1172     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1173 } // emit_GLSL_SLT
       
  1174 
       
  1175 static void emit_GLSL_SGE(Context *ctx)
       
  1176 {
       
  1177     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1178 } // emit_GLSL_SGE
       
  1179 
       
  1180 static void emit_GLSL_EXP(Context *ctx)
       
  1181 {
       
  1182     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1183 } // emit_GLSL_EXP
       
  1184 
       
  1185 static void emit_GLSL_LOG(Context *ctx)
       
  1186 {
       
  1187     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1188 } // emit_GLSL_LOG
       
  1189 
       
  1190 static void emit_GLSL_LIT(Context *ctx)
       
  1191 {
       
  1192     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1193 } // emit_GLSL_LIT
       
  1194 
       
  1195 static void emit_GLSL_DST(Context *ctx)
       
  1196 {
       
  1197     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1198 } // emit_GLSL_DST
       
  1199 
       
  1200 static void emit_GLSL_LRP(Context *ctx)
       
  1201 {
       
  1202     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1203 } // emit_GLSL_LRP
       
  1204 
       
  1205 static void emit_GLSL_FRC(Context *ctx)
       
  1206 {
       
  1207     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1208 } // emit_GLSL_FRC
       
  1209 
       
  1210 static void emit_GLSL_M4X4(Context *ctx)
       
  1211 {
       
  1212     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1213 } // emit_GLSL_M4X4
       
  1214 
       
  1215 static void emit_GLSL_M4X3(Context *ctx)
       
  1216 {
       
  1217     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1218 } // emit_GLSL_M4X3
       
  1219 
       
  1220 static void emit_GLSL_M3X4(Context *ctx)
       
  1221 {
       
  1222     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1223 } // emit_GLSL_M3X4
       
  1224 
       
  1225 static void emit_GLSL_M3X3(Context *ctx)
       
  1226 {
       
  1227     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1228 } // emit_GLSL_M3X3
       
  1229 
       
  1230 static void emit_GLSL_M3X2(Context *ctx)
       
  1231 {
       
  1232     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1233 } // emit_GLSL_M3X2
       
  1234 
       
  1235 static void emit_GLSL_CALL(Context *ctx)
       
  1236 {
       
  1237     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1238 } // emit_GLSL_CALL
       
  1239 
       
  1240 static void emit_GLSL_CALLNZ(Context *ctx)
       
  1241 {
       
  1242     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1243 } // emit_GLSL_CALLNZ
       
  1244 
       
  1245 static void emit_GLSL_LOOP(Context *ctx)
       
  1246 {
       
  1247     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1248 } // emit_GLSL_LOOP
       
  1249 
       
  1250 static void emit_GLSL_RET(Context *ctx)
       
  1251 {
       
  1252     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1253 } // emit_GLSL_RET
       
  1254 
       
  1255 static void emit_GLSL_ENDLOOP(Context *ctx)
       
  1256 {
       
  1257     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1258 } // emit_GLSL_ENDLOOP
       
  1259 
       
  1260 static void emit_GLSL_LABEL(Context *ctx)
       
  1261 {
       
  1262     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1263 } // emit_GLSL_LABEL
       
  1264 
       
  1265 static void emit_GLSL_DCL(Context *ctx)
       
  1266 {
       
  1267     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1268 } // emit_GLSL_DCL
       
  1269 
       
  1270 static void emit_GLSL_POW(Context *ctx)
       
  1271 {
       
  1272     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1273 } // emit_GLSL_POW
       
  1274 
       
  1275 static void emit_GLSL_CRS(Context *ctx)
       
  1276 {
       
  1277     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1278 } // emit_GLSL_CRS
       
  1279 
       
  1280 static void emit_GLSL_SGN(Context *ctx)
       
  1281 {
       
  1282     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1283 } // emit_GLSL_SGN
       
  1284 
       
  1285 static void emit_GLSL_ABS(Context *ctx)
       
  1286 {
       
  1287     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1288 } // emit_GLSL_ABS
       
  1289 
       
  1290 static void emit_GLSL_NRM(Context *ctx)
       
  1291 {
       
  1292     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1293 } // emit_GLSL_NRM
       
  1294 
       
  1295 static void emit_GLSL_SINCOS(Context *ctx)
       
  1296 {
       
  1297     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1298 } // emit_GLSL_SINCOS
       
  1299 
       
  1300 static void emit_GLSL_REP(Context *ctx)
       
  1301 {
       
  1302     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1303 } // emit_GLSL_REP
       
  1304 
       
  1305 static void emit_GLSL_ENDREP(Context *ctx)
       
  1306 {
       
  1307     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1308 } // emit_GLSL_ENDREP
       
  1309 
       
  1310 static void emit_GLSL_IF(Context *ctx)
       
  1311 {
       
  1312     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1313 } // emit_GLSL_IF
       
  1314 
       
  1315 static void emit_GLSL_IFC(Context *ctx)
       
  1316 {
       
  1317     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1318 } // emit_GLSL_IFC
       
  1319 
       
  1320 static void emit_GLSL_ELSE(Context *ctx)
       
  1321 {
       
  1322     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1323 } // emit_GLSL_ELSE
       
  1324 
       
  1325 static void emit_GLSL_ENDIF(Context *ctx)
       
  1326 {
       
  1327     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1328 } // emit_GLSL_ENDIF
       
  1329 
       
  1330 static void emit_GLSL_BREAK(Context *ctx)
       
  1331 {
       
  1332     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1333 } // emit_GLSL_BREAK
       
  1334 
       
  1335 static void emit_GLSL_BREAKC(Context *ctx)
       
  1336 {
       
  1337     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1338 } // emit_GLSL_BREAKC
       
  1339 
       
  1340 static void emit_GLSL_MOVA(Context *ctx)
       
  1341 {
       
  1342     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1343 } // emit_GLSL_MOVA
       
  1344 
       
  1345 static void emit_GLSL_DEFB(Context *ctx)
       
  1346 {
       
  1347     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1348 } // emit_GLSL_DEFB
       
  1349 
       
  1350 static void emit_GLSL_DEFI(Context *ctx)
       
  1351 {
       
  1352     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1353 } // emit_GLSL_DEFI
       
  1354 
       
  1355 static void emit_GLSL_TEXCOORD(Context *ctx)
       
  1356 {
       
  1357     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1358 } // emit_GLSL_TEXCOORD
       
  1359 
       
  1360 static void emit_GLSL_TEXKILL(Context *ctx)
       
  1361 {
       
  1362     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1363 } // emit_GLSL_TEXKILL
       
  1364 
       
  1365 static void emit_GLSL_TEX(Context *ctx)
       
  1366 {
       
  1367     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1368 } // emit_GLSL_TEX
       
  1369 
       
  1370 static void emit_GLSL_TEXBEM(Context *ctx)
       
  1371 {
       
  1372     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1373 } // emit_GLSL_TEXBEM
       
  1374 
       
  1375 static void emit_GLSL_TEXBEML(Context *ctx)
       
  1376 {
       
  1377     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1378 } // emit_GLSL_TEXBEML
       
  1379 
       
  1380 static void emit_GLSL_TEXREG2AR(Context *ctx)
       
  1381 {
       
  1382     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1383 } // emit_GLSL_TEXREG2AR
       
  1384 
       
  1385 static void emit_GLSL_TEXREG2GB(Context *ctx)
       
  1386 {
       
  1387     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1388 } // emit_GLSL_TEXREG2GB
       
  1389 
       
  1390 static void emit_GLSL_TEXM3X2PAD(Context *ctx)
       
  1391 {
       
  1392     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1393 } // emit_GLSL_TEXM3X2PAD
       
  1394 
       
  1395 static void emit_GLSL_TEXM3X2TEX(Context *ctx)
       
  1396 {
       
  1397     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1398 } // emit_GLSL_TEXM3X2TEX
       
  1399 
       
  1400 static void emit_GLSL_TEXM3X3PAD(Context *ctx)
       
  1401 {
       
  1402     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1403 } // emit_GLSL_TEXM3X3PAD
       
  1404 
       
  1405 static void emit_GLSL_TEXM3X3TEX(Context *ctx)
       
  1406 {
       
  1407     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1408 } // emit_GLSL_TEXM3X3TEX
       
  1409 
       
  1410 static void emit_GLSL_TEXM3X3SPEC(Context *ctx)
       
  1411 {
       
  1412     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1413 } // emit_GLSL_TEXM3X3SPEC
       
  1414 
       
  1415 static void emit_GLSL_TEXM3X3VSPEC(Context *ctx)
       
  1416 {
       
  1417     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1418 } // emit_GLSL_TEXM3X3VSPEC
       
  1419 
       
  1420 static void emit_GLSL_EXPP(Context *ctx)
       
  1421 {
       
  1422     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1423 } // emit_GLSL_EXPP
       
  1424 
       
  1425 static void emit_GLSL_LOGP(Context *ctx)
       
  1426 {
       
  1427     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1428 } // emit_GLSL_LOGP
       
  1429 
       
  1430 static void emit_GLSL_CND(Context *ctx)
       
  1431 {
       
  1432     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1433 } // emit_GLSL_CND
       
  1434 
       
  1435 static void emit_GLSL_DEF(Context *ctx)
       
  1436 {
       
  1437     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1438 } // emit_GLSL_DEF
       
  1439 
       
  1440 static void emit_GLSL_TEXREG2RGB(Context *ctx)
       
  1441 {
       
  1442     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1443 } // emit_GLSL_TEXREG2RGB
       
  1444 
       
  1445 static void emit_GLSL_TEXDP3TEX(Context *ctx)
       
  1446 {
       
  1447     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1448 } // emit_GLSL_TEXDP3TEX
       
  1449 
       
  1450 static void emit_GLSL_TEXM3X2DEPTH(Context *ctx)
       
  1451 {
       
  1452     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1453 } // emit_GLSL_TEXM3X2DEPTH
       
  1454 
       
  1455 static void emit_GLSL_TEXDP3(Context *ctx)
       
  1456 {
       
  1457     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1458 } // emit_GLSL_TEXDP3
       
  1459 
       
  1460 static void emit_GLSL_TEXM3X3(Context *ctx)
       
  1461 {
       
  1462     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1463 } // emit_GLSL_TEXM3X3
       
  1464 
       
  1465 static void emit_GLSL_TEXDEPTH(Context *ctx)
       
  1466 {
       
  1467     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1468 } // emit_GLSL_TEXDEPTH
       
  1469 
       
  1470 static void emit_GLSL_CMP(Context *ctx)
       
  1471 {
       
  1472     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1473 } // emit_GLSL_CMP
       
  1474 
       
  1475 static void emit_GLSL_BEM(Context *ctx)
       
  1476 {
       
  1477     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1478 } // emit_GLSL_BEM
       
  1479 
       
  1480 static void emit_GLSL_DP2ADD(Context *ctx)
       
  1481 {
       
  1482     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1483 } // emit_GLSL_DP2ADD
       
  1484 
       
  1485 static void emit_GLSL_DSX(Context *ctx)
       
  1486 {
       
  1487     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1488 } // emit_GLSL_DSX
       
  1489 
       
  1490 static void emit_GLSL_DSY(Context *ctx)
       
  1491 {
       
  1492     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1493 } // emit_GLSL_DSY
       
  1494 
       
  1495 static void emit_GLSL_TEXLDD(Context *ctx)
       
  1496 {
       
  1497     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1498 } // emit_GLSL_TEXLDD
       
  1499 
       
  1500 static void emit_GLSL_SETP(Context *ctx)
       
  1501 {
       
  1502     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1503 } // emit_GLSL_SETP
       
  1504 
       
  1505 static void emit_GLSL_TEXLDL(Context *ctx)
       
  1506 {
       
  1507     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1508 } // emit_GLSL_TEXLDL
       
  1509 
       
  1510 static void emit_GLSL_BREAKP(Context *ctx)
       
  1511 {
       
  1512     fail(ctx, "unimplemented.");  // !!! FIXME
       
  1513 } // emit_GLSL_BREAKP
       
  1514 
       
  1515 static void emit_GLSL_RESERVED(Context *ctx)
       
  1516 {
       
  1517     // do nothing; fails in the state machine.
       
  1518 } // emit_GLSL_RESERVED
       
  1519 
       
  1520 #endif  // SUPPORT_PROFILE_GLSL
       
  1521 
       
  1522 
       
  1523 
       
  1524 #if !AT_LEAST_ONE_PROFILE
       
  1525 #error No profiles are supported. Fix your build.
       
  1526 #endif
       
  1527 
       
  1528 static const Profile profiles[] =
       
  1529 {
       
  1530 #if SUPPORT_PROFILE_D3D
       
  1531     { "d3d", emit_D3D_start, emit_D3D_end, emit_D3D_comment },
       
  1532 #endif
       
  1533 #if SUPPORT_PROFILE_GLSL
       
  1534     { "glsl", emit_GLSL_start, emit_GLSL_end, emit_GLSL_comment },
       
  1535 #endif
       
  1536 };
       
  1537 
       
  1538 // The PROFILE_EMITTER_* items MUST be in the same order as profiles[]!
       
  1539 #define PROFILE_EMITTERS(op) { \
       
  1540      PROFILE_EMITTER_D3D(op) \
       
  1541      PROFILE_EMITTER_GLSL(op) \
       
  1542 }
       
  1543 
       
  1544 
       
  1545 static int parse_destination_token(Context *ctx, DestArgInfo *info)
       
  1546 {
       
  1547     // !!! FIXME: recheck against the spec for ranges (like RASTOUT values, etc).
       
  1548 
       
  1549     if (ctx->failstr != NULL)
       
  1550         return FAIL;  // already failed elsewhere.
       
  1551 
       
  1552     if (ctx->tokencount == 0)
       
  1553         return fail(ctx, "Out of tokens in destination parameter");
       
  1554 
       
  1555     const uint32 token = SWAP32(*(ctx->tokens));
       
  1556     const int reserved1 = (int) ((token >> 14) & 0x3); // bits 14 through 15
       
  1557     const int reserved2 = (int) ((token >> 31) & 0x1); // bit 31
       
  1558 
       
  1559     info->token = ctx->tokens;
       
  1560     info->regnum = (int) (token & 0x7ff);  // bits 0 through 10
       
  1561     info->relative = (int) ((token >> 13) & 0x1); // bit 13
       
  1562     info->writemask = (int) ((token >> 16) & 0xF); // bits 16 through 19
       
  1563     info->writemask0 = (int) ((token >> 16) & 0x1); // bit 16
       
  1564     info->writemask1 = (int) ((token >> 17) & 0x1); // bit 17
       
  1565     info->writemask2 = (int) ((token >> 18) & 0x1); // bit 18
       
  1566     info->writemask3 = (int) ((token >> 19) & 0x1); // bit 19
       
  1567     info->result_mod = (int) ((token >> 20) & 0xF); // bits 20 through 23
       
  1568     info->result_shift = (int) ((token >> 24) & 0xF); // bits 24 through 27
       
  1569     info->regtype = (int) ((token >> 28) & 0x7) | ((token >> 8) & 0x18);  // bits 28-30, 11-12
       
  1570 
       
  1571     ctx->tokens++;  // swallow token for now, for multiple calls in a row.
       
  1572     ctx->tokencount--;  // swallow token for now, for multiple calls in a row.
       
  1573 
       
  1574     if (reserved1 != 0x0)
       
  1575         return fail(ctx, "Reserved bit #1 in destination token must be zero");
       
  1576 
       
  1577     if (reserved2 != 0x1)
       
  1578         return fail(ctx, "Reserved bit #2 in destination token must be one");
       
  1579 
       
  1580     if (info->relative)
       
  1581     {
       
  1582         if (ctx->shader_type != SHADER_TYPE_VERTEX)
       
  1583             return fail(ctx, "Relative addressing in non-vertex shader");
       
  1584         else if (ctx->major_ver < 3)
       
  1585             return fail(ctx, "Relative addressing in vertex shader version < 3.0");
       
  1586         return fail(ctx, "Relative addressing is unsupported");  // !!! FIXME
       
  1587     } // if
       
  1588 
       
  1589     const int s = info->result_shift;
       
  1590     if (s != 0)
       
  1591     {
       
  1592         if (ctx->shader_type != SHADER_TYPE_PIXEL)
       
  1593             return fail(ctx, "Result shift scale in non-pixel shader");
       
  1594         else if (ctx->major_ver >= 2)
       
  1595             return fail(ctx, "Result shift scale in pixel shader version >= 2.0");
       
  1596         else if ( ! (((s >= 1) && (s <= 3)) || ((s >= 0xD) && (s <= 0xF))) )
       
  1597             return fail(ctx, "Result shift scale isn't 1 to 3, or 13 to 15.");
       
  1598     } // if
       
  1599 
       
  1600     if (info->result_mod & MOD_SATURATE)  // Saturate (vertex shaders only)
       
  1601     {
       
  1602         if (ctx->shader_type != SHADER_TYPE_VERTEX)
       
  1603             return fail(ctx, "Saturate result mod in non-vertex shader");
       
  1604     } // if
       
  1605 
       
  1606     if (info->result_mod & MOD_PP)  // Partial precision (pixel shaders only)
       
  1607     {
       
  1608         if (ctx->shader_type != SHADER_TYPE_PIXEL)
       
  1609             return fail(ctx, "Partial precision result mod in non-pixel shader");
       
  1610     } // if
       
  1611 
       
  1612     if (info->result_mod & MOD_CENTROID)  // Centroid (pixel shaders only)
       
  1613     {
       
  1614         if (ctx->shader_type != SHADER_TYPE_PIXEL)
       
  1615             return fail(ctx, "Centroid result mod in non-pixel shader");
       
  1616     } // if
       
  1617 
       
  1618     if ((info->regtype < 0) || (info->regtype > REGISTER_TYPE_MAX))
       
  1619         return fail(ctx, "Register type is out of range");
       
  1620 
       
  1621     return 1;
       
  1622 } // parse_destination_token
       
  1623 
       
  1624 
       
  1625 static int parse_source_token(Context *ctx, SourceArgInfo *info)
       
  1626 {
       
  1627     if (ctx->failstr != NULL)
       
  1628         return FAIL;  // already failed elsewhere.
       
  1629 
       
  1630     if (ctx->tokencount == 0)
       
  1631         return fail(ctx, "Out of tokens in source parameter");
       
  1632 
       
  1633     const uint32 token = SWAP32(*(ctx->tokens));
       
  1634     const int reserved1 = (int) ((token >> 14) & 0x3); // bits 14 through 15
       
  1635     const int reserved2 = (int) ((token >> 31) & 0x1); // bit 31
       
  1636 
       
  1637     info->token = ctx->tokens;
       
  1638     info->regnum = (int) (token & 0x7ff);  // bits 0 through 10
       
  1639     info->relative = (int) ((token >> 13) & 0x1); // bit 13
       
  1640     info->swizzle = (int) ((token >> 16) & 0xFF); // bits 16 through 23
       
  1641     info->swizzle_x = (int) ((token >> 16) & 0x3); // bits 16 through 17
       
  1642     info->swizzle_y = (int) ((token >> 18) & 0x3); // bits 18 through 19
       
  1643     info->swizzle_z = (int) ((token >> 20) & 0x3); // bits 20 through 21
       
  1644     info->swizzle_w = (int) ((token >> 22) & 0x3); // bits 22 through 23
       
  1645     info->src_mod = (int) ((token >> 24) & 0xF); // bits 24 through 27
       
  1646     info->regtype = (int) ((token >> 28) & 0x7) | ((token >> 9) & 0x18);  // bits 28-30, 11-12
       
  1647 
       
  1648     ctx->tokens++;  // swallow token for now, for multiple calls in a row.
       
  1649     ctx->tokencount--;  // swallow token for now, for multiple calls in a row.
       
  1650 
       
  1651     if (reserved1 != 0x0)
       
  1652         return fail(ctx, "Reserved bits #1 in source token must be zero");
       
  1653 
       
  1654     if (reserved2 != 0x1)
       
  1655         return fail(ctx, "Reserved bit #2 in source token must be one");
       
  1656 
       
  1657     if (info->relative)
       
  1658     {
       
  1659         if ((ctx->shader_type == SHADER_TYPE_PIXEL) && (ctx->major_ver < 3))
       
  1660             return fail(ctx, "Relative addressing in pixel shader version < 3.0");
       
  1661         return fail(ctx, "Relative addressing is unsupported");  // !!! FIXME
       
  1662     } // if
       
  1663 
       
  1664     if ( ((SourceMod) info->src_mod) >= SRCMOD_TOTAL )
       
  1665         return fail(ctx, "Unknown source modifier");
       
  1666 
       
  1667     return 1;
       
  1668 } // parse_source_token
       
  1669 
       
  1670 
       
  1671 static int parse_args_NULL(Context *ctx)
       
  1672 {
       
  1673     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1674 } // parse_args_NULL
       
  1675 
       
  1676 
       
  1677 static int parse_args_DEF(Context *ctx)
       
  1678 {
       
  1679     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
       
  1680         return FAIL;
       
  1681 
       
  1682     switch ((RegisterType) ctx->dest_args[0].regtype)
       
  1683     {
       
  1684         case REGISTER_TYPE_CONST:
       
  1685         case REGISTER_TYPE_CONST2:
       
  1686         case REGISTER_TYPE_CONST3:
       
  1687         case REGISTER_TYPE_CONST4:
       
  1688             break;
       
  1689 
       
  1690         default:
       
  1691             return fail(ctx, "DEF token using invalid register");
       
  1692     } // switch
       
  1693 
       
  1694     // !!! FIXME: msdn says this can be float or int...how do we differentiate?
       
  1695     ctx->dwords[0] = SWAP32(ctx->tokens[0]);
       
  1696     ctx->dwords[1] = SWAP32(ctx->tokens[1]);
       
  1697     ctx->dwords[2] = SWAP32(ctx->tokens[2]);
       
  1698     ctx->dwords[3] = SWAP32(ctx->tokens[3]);
       
  1699     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1700 } // parse_args_DEF
       
  1701 
       
  1702 
       
  1703 static int parse_args_DEFI(Context *ctx)
       
  1704 {
       
  1705     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
       
  1706         return FAIL;
       
  1707 
       
  1708     if (((RegisterType) ctx->dest_args[0].regtype) != REGISTER_TYPE_CONSTINT)
       
  1709         return fail(ctx, "DEFI token using invalid register");
       
  1710 
       
  1711     ctx->dwords[0] = SWAP32(ctx->tokens[0]);
       
  1712     ctx->dwords[1] = SWAP32(ctx->tokens[1]);
       
  1713     ctx->dwords[2] = SWAP32(ctx->tokens[2]);
       
  1714     ctx->dwords[3] = SWAP32(ctx->tokens[3]);
       
  1715     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1716 } // parse_args_DEFI
       
  1717 
       
  1718 
       
  1719 static int parse_args_DEFB(Context *ctx)
       
  1720 {
       
  1721     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
       
  1722         return FAIL;
       
  1723 
       
  1724     if (((RegisterType) ctx->dest_args[0].regtype) != REGISTER_TYPE_CONSTBOOL)
       
  1725         return fail(ctx, "DEFB token using invalid register");
       
  1726 
       
  1727     ctx->dwords[0] = *(ctx->tokens) ? 1 : 0;
       
  1728     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1729 } // parse_args_DEFB
       
  1730 
       
  1731 
       
  1732 
       
  1733 static int parse_args_DCL(Context *ctx)
       
  1734 {
       
  1735     int unsupported = 0;
       
  1736     const uint32 token = SWAP32(*(ctx->tokens));
       
  1737     const DeclUsageType usage = (DeclUsageType)(token & 0xF);
       
  1738     const int reserved1 = (int) ((token >> 31) & 0x1); // bit 31
       
  1739     uint32 reserved_mask = 0x00000000;
       
  1740 
       
  1741     if (reserved1 != 0x1)
       
  1742         return fail(ctx, "Bit #31 in DCL token must be one");
       
  1743 
       
  1744     ctx->tokens++;
       
  1745     ctx->tokencount--;
       
  1746     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
       
  1747         return FAIL;
       
  1748 
       
  1749     const RegisterType regtype = (RegisterType) ctx->dest_args[0].regtype;
       
  1750     if ((ctx->shader_type == SHADER_TYPE_PIXEL) && (ctx->major_ver >= 3))
       
  1751     {
       
  1752         if (regtype == REGISTER_TYPE_INPUT)
       
  1753             reserved_mask = 0x7FFFFFFF;
       
  1754 
       
  1755         else if (regtype == REGISTER_TYPE_MISCTYPE)
       
  1756         {
       
  1757             const MiscTypeType mt = (MiscTypeType) ctx->dest_args[0].regnum;
       
  1758             if (mt == MISCTYPE_TYPE_POSITION)
       
  1759                 reserved_mask = 0x7FFFFFFF;
       
  1760             else if (mt == MISCTYPE_TYPE_FACE)
       
  1761             {
       
  1762                 reserved_mask = 0x7FFFFFFF;
       
  1763                 if (ctx->dest_args[0].writemask != 0xF)
       
  1764                     return fail(ctx, "DCL face writemask must be full");
       
  1765                 else if (ctx->dest_args[0].result_mod != 0)
       
  1766                     return fail(ctx, "DCL face result modifier must be zero");
       
  1767                 else if (ctx->dest_args[0].result_shift != 0)
       
  1768                     return fail(ctx, "DCL face shift scale must be zero");
       
  1769             } // else if
       
  1770             else
       
  1771             {
       
  1772                 unsupported = 1;
       
  1773             } // else
       
  1774         } // else if
       
  1775 
       
  1776         else if (regtype == REGISTER_TYPE_TEXTURE)
       
  1777         {
       
  1778             const uint32 usage = (token & 0xF);
       
  1779             const uint32 index = ((token >> 16) & 0xF);
       
  1780             if (usage == DECLUSAGE_TEXCOORD)
       
  1781             {
       
  1782                 if (index > 7)
       
  1783                     return fail(ctx, "DCL texcoord usage must have 0-7 index");
       
  1784             } // if
       
  1785             else if (usage == DECLUSAGE_COLOR)
       
  1786             {
       
  1787                 if (index != 0)
       
  1788                     return fail(ctx, "DCL color usage must have 0 index");
       
  1789             } // else if
       
  1790             else
       
  1791             {
       
  1792                 return fail(ctx, "Invalid DCL texture usage");
       
  1793             } // else
       
  1794 
       
  1795             reserved_mask = 0x7FF0FFE0;
       
  1796             ctx->dwords[0] = usage;
       
  1797             ctx->dwords[1] = index;
       
  1798         } // else if
       
  1799 
       
  1800         else if (regtype == REGISTER_TYPE_SAMPLER)
       
  1801         {
       
  1802             reserved_mask = 0x7FFFFFF;
       
  1803             ctx->dwords[0] = ((token >> 27) & 0xF);  // TextureType
       
  1804         } // else if
       
  1805 
       
  1806         else
       
  1807         {
       
  1808             unsupported = 1;
       
  1809         } // else
       
  1810     } // if
       
  1811 
       
  1812     else if ((ctx->shader_type == SHADER_TYPE_PIXEL) && (ctx->major_ver >= 2))
       
  1813     {
       
  1814         if (regtype == REGISTER_TYPE_INPUT)
       
  1815             reserved_mask = 0x7FFFFFFF;
       
  1816         else if (regtype == REGISTER_TYPE_TEXTURE)
       
  1817             reserved_mask = 0x7FFFFFFF;
       
  1818         else if (regtype == REGISTER_TYPE_SAMPLER)
       
  1819         {
       
  1820             reserved_mask = 0x7FFFFFF;
       
  1821             ctx->dwords[0] = ((token >> 27) & 0xF);  // TextureType
       
  1822         } // else if
       
  1823         else
       
  1824         {
       
  1825             unsupported = 1;
       
  1826         } // else
       
  1827     } // if
       
  1828 
       
  1829     else if ((ctx->shader_type == SHADER_TYPE_VERTEX) && (ctx->major_ver >= 3))
       
  1830     {
       
  1831         if ((regtype==REGISTER_TYPE_INPUT) || (regtype==REGISTER_TYPE_OUTPUT))
       
  1832         {
       
  1833             const uint32 usage = (token & 0xF);
       
  1834             const uint32 index = ((token >> 16) & 0xF);
       
  1835             reserved_mask = 0x7FF0FFE0;
       
  1836             ctx->dwords[0] = usage;
       
  1837             ctx->dwords[1] = index;
       
  1838         } // if
       
  1839         else
       
  1840         {
       
  1841             unsupported = 1;
       
  1842         } // else
       
  1843     } // else if
       
  1844 
       
  1845     else if ((ctx->shader_type == SHADER_TYPE_VERTEX) && (ctx->major_ver >= 2))
       
  1846     {
       
  1847         if (regtype == REGISTER_TYPE_INPUT)
       
  1848         {
       
  1849             const uint32 usage = (token & 0xF);
       
  1850             const uint32 index = ((token >> 16) & 0xF);
       
  1851             reserved_mask = 0x7FF0FFE0;
       
  1852             ctx->dwords[0] = usage;
       
  1853             ctx->dwords[1] = index;
       
  1854         } // if
       
  1855         else
       
  1856         {
       
  1857             unsupported = 1;
       
  1858         } // else
       
  1859     } // else if
       
  1860 
       
  1861     else
       
  1862     {
       
  1863         unsupported = 1;
       
  1864     } // else
       
  1865 
       
  1866     if (unsupported)
       
  1867         return fail(ctx, "invalid DCL register type for this shader model");
       
  1868 
       
  1869     if ((token & reserved_mask) != 0)
       
  1870         return fail(ctx, "reserved bits in DCL dword aren't zero");
       
  1871 
       
  1872     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1873 } // parse_args_DCL
       
  1874 
       
  1875 
       
  1876 static int parse_args_D(Context *ctx)
       
  1877 {
       
  1878     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
       
  1879     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1880 } // parse_args_D
       
  1881 
       
  1882 
       
  1883 static int parse_args_S(Context *ctx)
       
  1884 {
       
  1885     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
       
  1886     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1887 } // parse_args_S
       
  1888 
       
  1889 
       
  1890 static int parse_args_SS(Context *ctx)
       
  1891 {
       
  1892     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
       
  1893     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
       
  1894     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1895 } // parse_args_SS
       
  1896 
       
  1897 
       
  1898 static int parse_args_DS(Context *ctx)
       
  1899 {
       
  1900     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
       
  1901     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
       
  1902     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1903 } // parse_args_DS
       
  1904 
       
  1905 
       
  1906 static int parse_args_DSS(Context *ctx)
       
  1907 {
       
  1908     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
       
  1909     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
       
  1910     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
       
  1911     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1912 } // parse_args_DSS
       
  1913 
       
  1914 
       
  1915 static int parse_args_DSSS(Context *ctx)
       
  1916 {
       
  1917     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
       
  1918     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
       
  1919     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
       
  1920     if (parse_source_token(ctx, &ctx->source_args[2]) == FAIL) return FAIL;
       
  1921     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1922 } // parse_args_DSSS
       
  1923 
       
  1924 
       
  1925 static int parse_args_DSSSS(Context *ctx)
       
  1926 {
       
  1927     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
       
  1928     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
       
  1929     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
       
  1930     if (parse_source_token(ctx, &ctx->source_args[2]) == FAIL) return FAIL;
       
  1931     if (parse_source_token(ctx, &ctx->source_args[3]) == FAIL) return FAIL;
       
  1932     return ((ctx->failstr != NULL) ? FAIL : 0);
       
  1933 } // parse_args_DSSSS
       
  1934 
       
  1935 
       
  1936 // State machine functions...
       
  1937 
       
  1938 static int state_RESERVED(Context *ctx)
       
  1939 {
       
  1940     return fail(ctx, "Tried to use RESERVED opcode.");
       
  1941 } // state_RESERVED
       
  1942 
       
  1943 
       
  1944 // Lookup table for instruction opcodes...
       
  1945 
       
  1946 typedef struct
       
  1947 {
       
  1948     const char *opcode_string;
       
  1949     int arg_tokens;
       
  1950     args_function parse_args;
       
  1951     state_function state;
       
  1952     emit_function emitter[STATICARRAYLEN(profiles)];
       
  1953 } Instruction;
       
  1954 
       
  1955 // These have to be in the right order! This array is indexed by the value
       
  1956 //  of the instruction token.
       
  1957 static Instruction instructions[] =
       
  1958 {
       
  1959     // INSTRUCTION_STATE means this opcode has to update the state machine
       
  1960     //  (we're entering an ELSE block, etc). INSTRUCTION means there's no
       
  1961     //  state, just go straight to the emitters.
       
  1962     #define INSTRUCTION_STATE(op, args, argsseq) { \
       
  1963         #op, args, parse_args_##argsseq, state_##op, PROFILE_EMITTERS(op) \
       
  1964     }
       
  1965     #define INSTRUCTION(op, args, argsseq) { \
       
  1966         #op, args, parse_args_##argsseq, NULL, PROFILE_EMITTERS(op) \
       
  1967     }
       
  1968     INSTRUCTION(NOP, 0, NULL),
       
  1969     INSTRUCTION(MOV, 2, DS),
       
  1970     INSTRUCTION(ADD, 3, DSS),
       
  1971     INSTRUCTION(SUB, 3, DSS),
       
  1972     INSTRUCTION(MAD, 4, DSSS),
       
  1973     INSTRUCTION(MUL, 3, DSS),
       
  1974     INSTRUCTION(RCP, 2, DS),
       
  1975     INSTRUCTION(RSQ, 2, DS),
       
  1976     INSTRUCTION(DP3, 3, DSS),
       
  1977     INSTRUCTION(DP4, 3, DSS),
       
  1978     INSTRUCTION(MIN, 3, DSS),
       
  1979     INSTRUCTION(MAX, 3, DSS),
       
  1980     INSTRUCTION(SLT, 3, DSS),
       
  1981     INSTRUCTION(SGE, 3, DSS),
       
  1982     INSTRUCTION(EXP, 2, DS),
       
  1983     INSTRUCTION(LOG, 2, DS),
       
  1984     INSTRUCTION(LIT, 2, DS),
       
  1985     INSTRUCTION(DST, 3, DSS),
       
  1986     INSTRUCTION(LRP, 4, DSSS),
       
  1987     INSTRUCTION(FRC, 2, DS),
       
  1988     INSTRUCTION(M4X4, 3, DSS),
       
  1989     INSTRUCTION(M4X3, 3, DSS),
       
  1990     INSTRUCTION(M3X4, 3, DSS),
       
  1991     INSTRUCTION(M3X3, 3, DSS),
       
  1992     INSTRUCTION(M3X2, 3, DSS),
       
  1993     INSTRUCTION(CALL, 1, S),
       
  1994     INSTRUCTION(CALLNZ, 2, SS),
       
  1995     INSTRUCTION(LOOP, 2, SS),
       
  1996     INSTRUCTION(RET, 0, NULL),
       
  1997     INSTRUCTION(ENDLOOP, 0, NULL),
       
  1998     INSTRUCTION(LABEL, 1, S),
       
  1999     INSTRUCTION(DCL, 2, DCL),
       
  2000     INSTRUCTION(POW, 3, DSS),
       
  2001     INSTRUCTION(CRS, 3, DSS),
       
  2002     INSTRUCTION(SGN, 4, DSSS),
       
  2003     INSTRUCTION(ABS, 2, DS),
       
  2004     INSTRUCTION(NRM, 2, DS),
       
  2005     INSTRUCTION(SINCOS, 4, NULL),
       
  2006     INSTRUCTION(REP, 1, S),
       
  2007     INSTRUCTION(ENDREP, 0, NULL),
       
  2008     INSTRUCTION(IF, 1, S),
       
  2009     INSTRUCTION(IFC, 2, SS),
       
  2010     INSTRUCTION(ELSE, 0, NULL),
       
  2011     INSTRUCTION(ENDIF, 0, NULL),
       
  2012     INSTRUCTION(BREAK, 0, NULL),
       
  2013     INSTRUCTION(BREAKC, 2, SS),
       
  2014     INSTRUCTION(MOVA, 2, DS),
       
  2015     INSTRUCTION(DEFB, 2, DEFB),
       
  2016     INSTRUCTION(DEFI, 5, DEFI),
       
  2017     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2018     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2019     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2020     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2021     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2022     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2023     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2024     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2025     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2026     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2027     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2028     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2029     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2030     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2031     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2032     INSTRUCTION(TEXCOORD, -1, NULL),
       
  2033     INSTRUCTION(TEXKILL, 1, D),
       
  2034     INSTRUCTION(TEX, -1, NULL),
       
  2035     INSTRUCTION(TEXBEM, 2, DS),
       
  2036     INSTRUCTION(TEXBEML, 2, DS),
       
  2037     INSTRUCTION(TEXREG2AR, 2, DS),
       
  2038     INSTRUCTION(TEXREG2GB, 2, DS),
       
  2039     INSTRUCTION(TEXM3X2PAD, 2, DS),
       
  2040     INSTRUCTION(TEXM3X2TEX, 2, DS),
       
  2041     INSTRUCTION(TEXM3X3PAD, 2, DS),
       
  2042     INSTRUCTION(TEXM3X3TEX, 2, DS),
       
  2043     INSTRUCTION_STATE(RESERVED, 0, NULL),
       
  2044     INSTRUCTION(TEXM3X3SPEC, 3, DSS),
       
  2045     INSTRUCTION(TEXM3X3VSPEC, 2, DS),
       
  2046     INSTRUCTION(EXPP, 2, DS),
       
  2047     INSTRUCTION(LOGP, 2, DS),
       
  2048     INSTRUCTION(CND, 4, DSSS),
       
  2049     INSTRUCTION(DEF, 5, DEF),
       
  2050     INSTRUCTION(TEXREG2RGB, 2, DS),
       
  2051     INSTRUCTION(TEXDP3TEX, 2, DS),
       
  2052     INSTRUCTION(TEXM3X2DEPTH, 2, DS),
       
  2053     INSTRUCTION(TEXDP3, 2, DS),
       
  2054     INSTRUCTION(TEXM3X3, 2, DS),
       
  2055     INSTRUCTION(TEXDEPTH, 1, D),
       
  2056     INSTRUCTION(CMP, 4, DSSS),
       
  2057     INSTRUCTION(BEM, 3, DSS),
       
  2058     INSTRUCTION(DP2ADD, 4, DSSS),
       
  2059     INSTRUCTION(DSX, 2, DS),
       
  2060     INSTRUCTION(DSY, 2, DS),
       
  2061     INSTRUCTION(TEXLDD, 5, DSSSS),
       
  2062     INSTRUCTION(SETP, 3, DSS),
       
  2063     INSTRUCTION(TEXLDL, 3, DSS),
       
  2064     INSTRUCTION(BREAKP, 1, S),  // src
       
  2065     #undef INSTRUCTION
       
  2066     #undef INSTRUCTION_STATE
       
  2067 };
       
  2068 
       
  2069 
       
  2070 
       
  2071 // parse various token types...
       
  2072 
       
  2073 static int parse_instruction_token(Context *ctx)
       
  2074 {
       
  2075     const uint32 *start_tokens = ctx->tokens;
       
  2076     const uint32 start_tokencount = ctx->tokencount;
       
  2077     const uint32 token = SWAP32(*(ctx->tokens));
       
  2078     const uint32 opcode = (token & 0xFFFF);
       
  2079     const uint32 controls = ((token >> 16) & 0xFF);
       
  2080     const uint32 insttoks = ((token >> 24) & 0x0F);
       
  2081     const int coissue = (token & 0x40000000) ? 1 : 0;
       
  2082     const int predicated = (token & 0x10000000) ? 1 : 0;
       
  2083     const Instruction *instruction = &instructions[opcode];
       
  2084     const emit_function emitter = instruction->emitter[ctx->profileid];
       
  2085     int retval = FAIL;
       
  2086 
       
  2087     if ( opcode >= (sizeof (instructions) / sizeof (instructions[0])) )
       
  2088         return 0;  // not an instruction token, or just not handled here.
       
  2089 
       
  2090     if ((token & 0x80000000) != 0)
       
  2091         return fail(ctx, "instruction token high bit must be zero.");  // so says msdn.
       
  2092 
       
  2093     if (coissue)  // !!! FIXME: I'm not sure what this means, yet.
       
  2094         return fail(ctx, "coissue instructions unsupported");
       
  2095 
       
  2096     if (ctx->major_ver < 2)
       
  2097     {
       
  2098         if (insttoks != 0)  // this is a reserved field in shaders < 2.0 ...
       
  2099             return fail(ctx, "instruction token count must be zero");
       
  2100     } // if
       
  2101 
       
  2102     else if (instruction->arg_tokens >= 0)
       
  2103     {
       
  2104         if (instruction->arg_tokens != insttoks)
       
  2105         {
       
  2106             return failf(ctx, "unexpected tokens count (%u) for opcode '%s'.",
       
  2107                         (uint) insttoks, instruction->opcode_string);
       
  2108         } // if
       
  2109         else if (ctx->tokencount <= instruction->arg_tokens)
       
  2110         {
       
  2111             return failf(ctx,
       
  2112                         "need more tokens (need %u, got %u) for opcode '%s'.",
       
  2113                         (uint) instruction->arg_tokens, (uint) ctx->tokencount,
       
  2114                         instruction->opcode_string);
       
  2115         } // else if
       
  2116     } // else if
       
  2117 
       
  2118     ctx->instruction_count++;
       
  2119     ctx->instruction_controls = controls;
       
  2120 
       
  2121     // Update the context with instruction's arguments.
       
  2122     ctx->tokens++;
       
  2123     ctx->tokencount--;
       
  2124     if (instruction->parse_args(ctx) == FAIL)
       
  2125         return FAIL;
       
  2126 
       
  2127     // parse_args() moves these forward for convenience...reset them.
       
  2128     ctx->tokens = start_tokens;
       
  2129     ctx->tokencount = start_tokencount;
       
  2130 
       
  2131     if (instruction->state != NULL)  // update state machine
       
  2132         retval = instruction->state(ctx);
       
  2133     else
       
  2134     {
       
  2135         // !!! FIXME
       
  2136         //assert(instruction->arg_tokens >= 0);
       
  2137         //retval = instruction->arg_tokens + 1;
       
  2138         retval = insttoks + 1;
       
  2139     } // else
       
  2140 
       
  2141     if (retval != FAIL)  // only do this if there wasn't a previous fail.
       
  2142         emitter(ctx);  // call the profile's emitter.
       
  2143 
       
  2144     return retval;
       
  2145 } // parse_instruction_token
       
  2146 
       
  2147 
       
  2148 static int parse_version_token(Context *ctx)
       
  2149 {
       
  2150     if (ctx->tokencount == 0)
       
  2151         return fail(ctx, "Expected version token, got none at all.");
       
  2152 
       
  2153     const uint32 token = SWAP32(*(ctx->tokens));
       
  2154     const uint32 shadertype = ((token >> 16) & 0xFFFF);
       
  2155     const uint32 major = (uint32) ((token >> 8) & 0xFF);
       
  2156     const uint32 minor = (uint32) (token & 0xFF);
       
  2157 
       
  2158     // 0xFFFF == pixel shader, 0xFFFE == vertex shader
       
  2159     if (shadertype == 0xFFFF)
       
  2160         ctx->shader_type = SHADER_TYPE_PIXEL;
       
  2161     else if (shadertype == 0xFFFE)
       
  2162         ctx->shader_type = SHADER_TYPE_VERTEX;
       
  2163     else  // geometry shader? Bogus data?
       
  2164         return fail(ctx, "Unsupported shader type or not a shader at all");
       
  2165 
       
  2166     ctx->major_ver = major;
       
  2167     ctx->minor_ver = minor;
       
  2168 
       
  2169     if (!SHADER_VERSION_SUPPORTED(major, minor))
       
  2170     {
       
  2171         return failf(ctx, "Shader Model %u.%u is currently unsupported.",
       
  2172                      (uint) major, (uint) minor);
       
  2173     } // if
       
  2174 
       
  2175     ctx->profile->start_emitter(ctx);
       
  2176     return 1;  // ate one token.
       
  2177 } // parse_version_token
       
  2178 
       
  2179 
       
  2180 static int parse_comment_token(Context *ctx)
       
  2181 {
       
  2182     const uint32 token = SWAP32(*(ctx->tokens));
       
  2183     if ((token & 0xFFFF) != 0xFFFE)
       
  2184         return 0;  // not a comment token.
       
  2185     else if ((token & 0x80000000) != 0)
       
  2186         return fail(ctx, "comment token high bit must be zero.");  // so says msdn.
       
  2187     else
       
  2188     {
       
  2189         const uint32 commenttoks = ((token >> 16) & 0xFFFF);
       
  2190         const uint32 len = commenttoks * sizeof (uint32);
       
  2191         const int needmalloc = (len >= SCRATCH_BUFFER_SIZE);
       
  2192         char *str = ((needmalloc) ? (char *) ctx->malloc(len + 1) :
       
  2193                         get_scratch_buffer(ctx));
       
  2194         memcpy(str, (const char *) (ctx->tokens+1), len);
       
  2195         str[len] = '\0';
       
  2196         ctx->profile->comment_emitter(ctx, str);
       
  2197         if (needmalloc)
       
  2198             ctx->free(str);
       
  2199 
       
  2200         return commenttoks + 1;  // comment data plus the initial token.
       
  2201     } // else
       
  2202 
       
  2203     // shouldn't hit this.
       
  2204     return failf(ctx, "Logic error at %s:%d", __FILE__, __LINE__);
       
  2205 } // parse_comment_token
       
  2206 
       
  2207 
       
  2208 static int parse_end_token(Context *ctx)
       
  2209 {
       
  2210     if (SWAP32(*(ctx->tokens)) != 0x0000FFFF)   // end token always 0x0000FFFF.
       
  2211         return 0;  // not us, eat no tokens.
       
  2212 
       
  2213     if (ctx->tokencount != 1)  // we _must_ be last. If not: fail.
       
  2214         return fail(ctx, "end token before end of stream");
       
  2215 
       
  2216     ctx->profile->end_emitter(ctx);
       
  2217 
       
  2218     return END_OF_STREAM;
       
  2219 } // parse_end_token
       
  2220 
       
  2221 
       
  2222 static int parse_phase_token(Context *ctx)
       
  2223 {
       
  2224     if (SWAP32(*(ctx->tokens)) != 0x0000FFFD) // phase token always 0x0000FFFD.
       
  2225         return 0;  // not us, eat no tokens.
       
  2226     return fail(ctx, "not sure what this thing is yet.");
       
  2227 } // parse_phase_token
       
  2228 
       
  2229 
       
  2230 static int parse_token(Context *ctx)
       
  2231 {
       
  2232     int rc = 0;
       
  2233 
       
  2234     if (ctx->failstr != NULL)
       
  2235         return FAIL;  // just in case...catch previously unhandled fails here.
       
  2236 
       
  2237     if (ctx->tokencount == 0)
       
  2238         return fail(ctx, "unexpected end of shader.");
       
  2239 
       
  2240     if ((rc = parse_comment_token(ctx)) != 0)
       
  2241         return rc;
       
  2242 
       
  2243     if ((rc = parse_end_token(ctx)) != 0)
       
  2244         return rc;
       
  2245 
       
  2246     if ((rc = parse_phase_token(ctx)) != 0)
       
  2247         return rc;
       
  2248 
       
  2249     if ((rc = parse_instruction_token(ctx)) != 0)
       
  2250         return rc;
       
  2251 
       
  2252     return failf(ctx, "unknown token (%u)", (uint) *ctx->tokens);
       
  2253 } // parse_token
       
  2254 
       
  2255 
       
  2256 static void *internal_malloc(int bytes) { return malloc(bytes); }
       
  2257 static void internal_free(void *ptr) { free(ptr); }
       
  2258 
       
  2259 
       
  2260 static int find_profile_id(const char *profile)
       
  2261 {
       
  2262     int i;
       
  2263     for (i = 0; i < STATICARRAYLEN(profiles); i++)
       
  2264     {
       
  2265         const char *name = profiles[i].name;
       
  2266         if (strcmp(name, profile) == 0)
       
  2267             return i;
       
  2268     } // for
       
  2269     return -1;  // no match.
       
  2270 } // find_profile_id
       
  2271 
       
  2272 
       
  2273 static Context *build_context(const char *profile,
       
  2274                                        const unsigned char *tokenbuf,
       
  2275                                        const unsigned int bufsize,
       
  2276                                        MOJOSHADER_malloc m, MOJOSHADER_free f)
       
  2277 {
       
  2278     if (m == NULL) m = internal_malloc;
       
  2279     if (f == NULL) f = internal_free;
       
  2280 
       
  2281     Context *ctx = m(sizeof (Context));
       
  2282     if (ctx == NULL)
       
  2283         return NULL;
       
  2284 
       
  2285     memset(ctx, '\0', sizeof (Context));
       
  2286     ctx->malloc = m;
       
  2287     ctx->free = f;
       
  2288     ctx->tokens = (const uint32 *) tokenbuf;
       
  2289     ctx->tokencount = bufsize / sizeof (uint32);
       
  2290     ctx->endline = "\n";
       
  2291     ctx->endline_len = 1;  // !!! FIXME: do "\r\n" on Windows?
       
  2292     ctx->output.str = NULL;
       
  2293     ctx->output.next = NULL;
       
  2294     ctx->output_tail = &ctx->output;
       
  2295 
       
  2296     const int profileid = find_profile_id(profile);
       
  2297     ctx->profileid = profileid;
       
  2298     if (profileid >= 0)  // we'll fail later, but we still need the context!
       
  2299         ctx->profile = &profiles[profileid];
       
  2300 
       
  2301     return ctx;
       
  2302 } // build_context
       
  2303 
       
  2304 
       
  2305 static void destroy_context(Context *ctx)
       
  2306 {
       
  2307     OutputList *item = ctx->output.next;
       
  2308     while (item != NULL)
       
  2309     {
       
  2310         OutputList *next = item->next;
       
  2311         ctx->free(item->str);
       
  2312         ctx->free(item);
       
  2313         item = next;
       
  2314     } // for
       
  2315 
       
  2316     if (ctx->failstr != out_of_mem_string)
       
  2317         ctx->free((void *) ctx->failstr);
       
  2318     ctx->free(ctx);
       
  2319 } // destroy_context
       
  2320 
       
  2321 
       
  2322 static char *build_output(Context *ctx)
       
  2323 {
       
  2324     char *retval = (char *) ctx->malloc(ctx->output_len + 1);
       
  2325     if (retval == NULL)
       
  2326         out_of_memory(ctx);
       
  2327     else
       
  2328     {
       
  2329         const char *endline = ctx->endline;
       
  2330         const size_t endline_len = ctx->endline_len;
       
  2331         char *wptr = retval;
       
  2332         OutputList *item = ctx->output.next;
       
  2333         while (item != NULL)
       
  2334         {
       
  2335             const size_t len = strlen(item->str);
       
  2336             memcpy(wptr, item->str, len);
       
  2337             wptr += len;
       
  2338             memcpy(wptr, endline, endline_len);
       
  2339             wptr += endline_len;
       
  2340             item = item->next;
       
  2341         } // while
       
  2342         *wptr = '\0';
       
  2343     } // else
       
  2344 
       
  2345     return retval;
       
  2346 } // build_output
       
  2347 
       
  2348 
       
  2349 // API entry point...
       
  2350 
       
  2351 int MOJOSHADER_parse(const char *profile, const unsigned char *tokenbuf,
       
  2352                    const unsigned int bufsize, MOJOSHADER_malloc m,
       
  2353                    MOJOSHADER_free f)
       
  2354 {
       
  2355     int rc = FAIL;
       
  2356 
       
  2357     Context *ctx = build_context(profile, tokenbuf, bufsize, m, f);
       
  2358     if (ctx == NULL)
       
  2359         return 0;  // !!! FIXME: error string?
       
  2360 
       
  2361     if (ctx->profile == NULL)
       
  2362         failf(ctx, "Profile '%s' is unknown or unsupported", profile);
       
  2363 
       
  2364     if (ctx->failstr == NULL)  // only go on if there was no previous error...
       
  2365     {
       
  2366         // Version token always comes first.
       
  2367         rc = parse_version_token(ctx);
       
  2368 
       
  2369         // parse out the rest of the tokens after the version token...
       
  2370         while (rc > 0)
       
  2371         {
       
  2372             ctx->tokens += rc;
       
  2373             ctx->tokencount -= rc;
       
  2374             rc = parse_token(ctx);
       
  2375         } // while
       
  2376     } // if
       
  2377 
       
  2378 //    if (ctx->failstr == NULL)
       
  2379     {
       
  2380         char *str = build_output(ctx);
       
  2381         if (str != NULL)
       
  2382         {
       
  2383             printf("OUTPUT:\n%s\n", str);  // !!! FIXME: report to caller.
       
  2384             ctx->free(str);
       
  2385         } // if
       
  2386 
       
  2387         printf("INSTRUCTION COUNT: %u\n", (uint) ctx->instruction_count);
       
  2388     } // if
       
  2389 
       
  2390     if (ctx->failstr != NULL)
       
  2391         printf("FAIL: %s\n", ctx->failstr);
       
  2392 
       
  2393     destroy_context(ctx);
       
  2394 
       
  2395     return (rc == END_OF_STREAM);
       
  2396 } // MOJOSHADER_parse
       
  2397 
       
  2398 
       
  2399 int MOJOSHADER_version(void)
       
  2400 {
       
  2401     return MOJOSHADER_VERSION;
       
  2402 } // MOJOSHADER_version
       
  2403 
       
  2404 // end of mojoshader.c ...
       
  2405