wineps.drv: Slightly simplify a PPD parser code snippet.
[wine] / dlls / d3dcompiler_43 / bytecodewriter.c
1 /*
2  * Direct3D bytecode output functions
3  *
4  * Copyright 2008 Stefan Dösinger
5  * Copyright 2009 Matteo Bruni
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25 #include "wine/debug.h"
26
27 #include "d3d9types.h"
28 #include "d3dcompiler_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(bytecodewriter);
31
32 /****************************************************************
33  * General assembler shader construction helper routines follow *
34  ****************************************************************/
35 /* struct instruction *alloc_instr
36  *
37  * Allocates a new instruction structure with srcs registers
38  *
39  * Parameters:
40  *  srcs: Number of source registers to allocate
41  *
42  * Returns:
43  *  A pointer to the allocated instruction structure
44  *  NULL in case of an allocation failure
45  */
46 struct instruction *alloc_instr(unsigned int srcs) {
47     struct instruction *ret = d3dcompiler_alloc(sizeof(*ret));
48     if(!ret) {
49         ERR("Failed to allocate memory for an instruction structure\n");
50         return NULL;
51     }
52
53     if(srcs) {
54         ret->src = d3dcompiler_alloc(srcs * sizeof(*ret->src));
55         if(!ret->src) {
56             ERR("Failed to allocate memory for instruction registers\n");
57             d3dcompiler_free(ret);
58             return NULL;
59         }
60         ret->num_srcs = srcs;
61     }
62     return ret;
63 }
64
65 /* void add_instruction
66  *
67  * Adds a new instruction to the shader's instructions array and grows the instruction array
68  * if needed.
69  *
70  * The function does NOT copy the instruction structure. Make sure not to release the
71  * instruction or any of its substructures like registers.
72  *
73  * Parameters:
74  *  shader: Shader to add the instruction to
75  *  instr: Instruction to add to the shader
76  */
77 BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) {
78     struct instruction      **new_instructions;
79
80     if(!shader) return FALSE;
81
82     if(shader->instr_alloc_size == 0) {
83         shader->instr = d3dcompiler_alloc(sizeof(*shader->instr) * INSTRARRAY_INITIAL_SIZE);
84         if(!shader->instr) {
85             ERR("Failed to allocate the shader instruction array\n");
86             return FALSE;
87         }
88         shader->instr_alloc_size = INSTRARRAY_INITIAL_SIZE;
89     } else if(shader->instr_alloc_size == shader->num_instrs) {
90         new_instructions = d3dcompiler_realloc(shader->instr,
91                                        sizeof(*shader->instr) * (shader->instr_alloc_size) * 2);
92         if(!new_instructions) {
93             ERR("Failed to grow the shader instruction array\n");
94             return FALSE;
95         }
96         shader->instr = new_instructions;
97         shader->instr_alloc_size = shader->instr_alloc_size * 2;
98     } else if(shader->num_instrs > shader->instr_alloc_size) {
99         ERR("More instructions than allocated. This should not happen\n");
100         return FALSE;
101     }
102
103     shader->instr[shader->num_instrs] = instr;
104     shader->num_instrs++;
105     return TRUE;
106 }
107
108 BOOL add_constF(struct bwriter_shader *shader, DWORD reg, float x, float y, float z, float w) {
109     struct constant *newconst;
110
111     if(shader->num_cf) {
112         struct constant **newarray;
113         newarray = d3dcompiler_realloc(shader->constF,
114                                sizeof(*shader->constF) * (shader->num_cf + 1));
115         if(!newarray) {
116             ERR("Failed to grow the constants array\n");
117             return FALSE;
118         }
119         shader->constF = newarray;
120     } else {
121         shader->constF = d3dcompiler_alloc(sizeof(*shader->constF));
122         if(!shader->constF) {
123             ERR("Failed to allocate the constants array\n");
124             return FALSE;
125         }
126     }
127
128     newconst = d3dcompiler_alloc(sizeof(*newconst));
129     if(!newconst) {
130         ERR("Failed to allocate a new constant\n");
131         return FALSE;
132     }
133     newconst->regnum = reg;
134     newconst->value[0].f = x;
135     newconst->value[1].f = y;
136     newconst->value[2].f = z;
137     newconst->value[3].f = w;
138     shader->constF[shader->num_cf] = newconst;
139
140     shader->num_cf++;
141     return TRUE;
142 }
143
144 BOOL add_constI(struct bwriter_shader *shader, DWORD reg, INT x, INT y, INT z, INT w) {
145     struct constant *newconst;
146
147     if(shader->num_ci) {
148         struct constant **newarray;
149         newarray = d3dcompiler_realloc(shader->constI,
150                                sizeof(*shader->constI) * (shader->num_ci + 1));
151         if(!newarray) {
152             ERR("Failed to grow the constants array\n");
153             return FALSE;
154         }
155         shader->constI = newarray;
156     } else {
157         shader->constI = d3dcompiler_alloc(sizeof(*shader->constI));
158         if(!shader->constI) {
159             ERR("Failed to allocate the constants array\n");
160             return FALSE;
161         }
162     }
163
164     newconst = d3dcompiler_alloc(sizeof(*newconst));
165     if(!newconst) {
166         ERR("Failed to allocate a new constant\n");
167         return FALSE;
168     }
169     newconst->regnum = reg;
170     newconst->value[0].i = x;
171     newconst->value[1].i = y;
172     newconst->value[2].i = z;
173     newconst->value[3].i = w;
174     shader->constI[shader->num_ci] = newconst;
175
176     shader->num_ci++;
177     return TRUE;
178 }
179
180 BOOL add_constB(struct bwriter_shader *shader, DWORD reg, BOOL x) {
181     struct constant *newconst;
182
183     if(shader->num_cb) {
184         struct constant **newarray;
185         newarray = d3dcompiler_realloc(shader->constB,
186                                sizeof(*shader->constB) * (shader->num_cb + 1));
187         if(!newarray) {
188             ERR("Failed to grow the constants array\n");
189             return FALSE;
190         }
191         shader->constB = newarray;
192     } else {
193         shader->constB = d3dcompiler_alloc(sizeof(*shader->constB));
194         if(!shader->constB) {
195             ERR("Failed to allocate the constants array\n");
196             return FALSE;
197         }
198     }
199
200     newconst = d3dcompiler_alloc(sizeof(*newconst));
201     if(!newconst) {
202         ERR("Failed to allocate a new constant\n");
203         return FALSE;
204     }
205     newconst->regnum = reg;
206     newconst->value[0].b = x;
207     shader->constB[shader->num_cb] = newconst;
208
209     shader->num_cb++;
210     return TRUE;
211 }
212
213 BOOL record_declaration(struct bwriter_shader *shader, DWORD usage,
214                         DWORD usage_idx, DWORD mod, BOOL output,
215                         DWORD regnum, DWORD writemask, BOOL builtin) {
216     unsigned int *num;
217     struct declaration **decl;
218     unsigned int i;
219
220     if(!shader) return FALSE;
221
222     if(output) {
223         num = &shader->num_outputs;
224         decl = &shader->outputs;
225     } else {
226         num = &shader->num_inputs;
227         decl = &shader->inputs;
228     }
229
230     if(*num == 0) {
231         *decl = d3dcompiler_alloc(sizeof(**decl));
232         if(!*decl) {
233             ERR("Error allocating declarations array\n");
234             return FALSE;
235         }
236     } else {
237         struct declaration *newdecl;
238         for(i = 0; i < *num; i++) {
239             if((*decl)[i].regnum == regnum && ((*decl)[i].writemask & writemask)) {
240                 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
241                       regnum, (*decl)[i].writemask & writemask);
242             }
243         }
244
245         newdecl = d3dcompiler_realloc(*decl,
246                               sizeof(**decl) * ((*num) + 1));
247         if(!newdecl) {
248             ERR("Error reallocating declarations array\n");
249             return FALSE;
250         }
251         *decl = newdecl;
252     }
253     (*decl)[*num].usage = usage;
254     (*decl)[*num].usage_idx = usage_idx;
255     (*decl)[*num].regnum = regnum;
256     (*decl)[*num].mod = mod;
257     (*decl)[*num].writemask = writemask;
258     (*decl)[*num].builtin = builtin;
259     (*num)++;
260
261     return TRUE;
262 }
263
264 BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD mod, DWORD regnum) {
265     unsigned int i;
266
267     if(!shader) return FALSE;
268
269     if(shader->num_samplers == 0) {
270         shader->samplers = d3dcompiler_alloc(sizeof(*shader->samplers));
271         if(!shader->samplers) {
272             ERR("Error allocating samplers array\n");
273             return FALSE;
274         }
275     } else {
276         struct samplerdecl *newarray;
277
278         for(i = 0; i < shader->num_samplers; i++) {
279             if(shader->samplers[i].regnum == regnum) {
280                 WARN("Sampler %u already declared\n", regnum);
281                 /* This is not an error as far as the assembler is concerned.
282                  * Direct3D might refuse to load the compiled shader though
283                  */
284             }
285         }
286
287         newarray = d3dcompiler_realloc(shader->samplers,
288                                sizeof(*shader->samplers) * (shader->num_samplers + 1));
289         if(!newarray) {
290             ERR("Error reallocating samplers array\n");
291             return FALSE;
292         }
293         shader->samplers = newarray;
294     }
295
296     shader->samplers[shader->num_samplers].type = samptype;
297     shader->samplers[shader->num_samplers].mod = mod;
298     shader->samplers[shader->num_samplers].regnum = regnum;
299     shader->num_samplers++;
300     return TRUE;
301 }
302
303
304 /* shader bytecode buffer manipulation functions.
305  * allocate_buffer creates a new buffer structure, put_dword adds a new
306  * DWORD to the buffer. In the rare case of a memory allocation failure
307  * when trying to grow the buffer a flag is set in the buffer to mark it
308  * invalid. This avoids return value checking and passing in many places
309  */
310 static struct bytecode_buffer *allocate_buffer(void) {
311     struct bytecode_buffer *ret;
312
313     ret = d3dcompiler_alloc(sizeof(*ret));
314     if(!ret) return NULL;
315
316     ret->alloc_size = BYTECODEBUFFER_INITIAL_SIZE;
317     ret->data = d3dcompiler_alloc(sizeof(DWORD) * ret->alloc_size);
318     if(!ret->data) {
319         d3dcompiler_free(ret);
320         return NULL;
321     }
322     ret->state = S_OK;
323     return ret;
324 }
325
326 static void put_dword(struct bytecode_buffer *buffer, DWORD value) {
327     if(FAILED(buffer->state)) return;
328
329     if(buffer->alloc_size == buffer->size) {
330         DWORD *newarray;
331         buffer->alloc_size *= 2;
332         newarray = d3dcompiler_realloc(buffer->data,
333                                sizeof(DWORD) * buffer->alloc_size);
334         if(!newarray) {
335             ERR("Failed to grow the buffer data memory\n");
336             buffer->state = E_OUTOFMEMORY;
337             return;
338         }
339         buffer->data = newarray;
340     }
341     buffer->data[buffer->size++] = value;
342 }
343
344 /* bwriter -> d3d9 conversion functions. */
345 static DWORD d3d9_swizzle(DWORD bwriter_swizzle)
346 {
347     /* Currently a NOP, but this allows changing the internal definitions
348      * without side effects. */
349     DWORD ret = 0;
350
351     if ((bwriter_swizzle & BWRITERVS_X_X) == BWRITERVS_X_X) ret |= D3DVS_X_X;
352     if ((bwriter_swizzle & BWRITERVS_X_Y) == BWRITERVS_X_Y) ret |= D3DVS_X_Y;
353     if ((bwriter_swizzle & BWRITERVS_X_Z) == BWRITERVS_X_Z) ret |= D3DVS_X_Z;
354     if ((bwriter_swizzle & BWRITERVS_X_W) == BWRITERVS_X_W) ret |= D3DVS_X_W;
355
356     if ((bwriter_swizzle & BWRITERVS_Y_X) == BWRITERVS_Y_X) ret |= D3DVS_Y_X;
357     if ((bwriter_swizzle & BWRITERVS_Y_Y) == BWRITERVS_Y_Y) ret |= D3DVS_Y_Y;
358     if ((bwriter_swizzle & BWRITERVS_Y_Z) == BWRITERVS_Y_Z) ret |= D3DVS_Y_Z;
359     if ((bwriter_swizzle & BWRITERVS_Y_W) == BWRITERVS_Y_W) ret |= D3DVS_Y_W;
360
361     if ((bwriter_swizzle & BWRITERVS_Z_X) == BWRITERVS_Z_X) ret |= D3DVS_Z_X;
362     if ((bwriter_swizzle & BWRITERVS_Z_Y) == BWRITERVS_Z_Y) ret |= D3DVS_Z_Y;
363     if ((bwriter_swizzle & BWRITERVS_Z_Z) == BWRITERVS_Z_Z) ret |= D3DVS_Z_Z;
364     if ((bwriter_swizzle & BWRITERVS_Z_W) == BWRITERVS_Z_W) ret |= D3DVS_Z_W;
365
366     if ((bwriter_swizzle & BWRITERVS_W_X) == BWRITERVS_W_X) ret |= D3DVS_W_X;
367     if ((bwriter_swizzle & BWRITERVS_W_Y) == BWRITERVS_W_Y) ret |= D3DVS_W_Y;
368     if ((bwriter_swizzle & BWRITERVS_W_Z) == BWRITERVS_W_Z) ret |= D3DVS_W_Z;
369     if ((bwriter_swizzle & BWRITERVS_W_W) == BWRITERVS_W_W) ret |= D3DVS_W_W;
370
371     return ret;
372 }
373
374 static DWORD d3d9_writemask(DWORD bwriter_writemask)
375 {
376     DWORD ret = 0;
377
378     if (bwriter_writemask & BWRITERSP_WRITEMASK_0) ret |= D3DSP_WRITEMASK_0;
379     if (bwriter_writemask & BWRITERSP_WRITEMASK_1) ret |= D3DSP_WRITEMASK_1;
380     if (bwriter_writemask & BWRITERSP_WRITEMASK_2) ret |= D3DSP_WRITEMASK_2;
381     if (bwriter_writemask & BWRITERSP_WRITEMASK_3) ret |= D3DSP_WRITEMASK_3;
382
383     return ret;
384 }
385
386 static DWORD d3d9_srcmod(DWORD bwriter_srcmod)
387 {
388     switch (bwriter_srcmod)
389     {
390         case BWRITERSPSM_NONE:       return D3DSPSM_NONE;
391         case BWRITERSPSM_NEG:        return D3DSPSM_NEG;
392         case BWRITERSPSM_BIAS:       return D3DSPSM_BIAS;
393         case BWRITERSPSM_BIASNEG:    return D3DSPSM_BIASNEG;
394         case BWRITERSPSM_SIGN:       return D3DSPSM_SIGN;
395         case BWRITERSPSM_SIGNNEG:    return D3DSPSM_SIGNNEG;
396         case BWRITERSPSM_COMP:       return D3DSPSM_COMP;
397         case BWRITERSPSM_X2:         return D3DSPSM_X2;
398         case BWRITERSPSM_X2NEG:      return D3DSPSM_X2NEG;
399         case BWRITERSPSM_DZ:         return D3DSPSM_DZ;
400         case BWRITERSPSM_DW:         return D3DSPSM_DW;
401         case BWRITERSPSM_ABS:        return D3DSPSM_ABS;
402         case BWRITERSPSM_ABSNEG:     return D3DSPSM_ABSNEG;
403         case BWRITERSPSM_NOT:        return D3DSPSM_NOT;
404         default:
405             FIXME("Unhandled BWRITERSPSM token %#x.\n", bwriter_srcmod);
406             return 0;
407     }
408 }
409
410 static DWORD d3d9_dstmod(DWORD bwriter_mod)
411 {
412     DWORD ret = 0;
413
414     if (bwriter_mod & BWRITERSPDM_SATURATE)         ret |= D3DSPDM_SATURATE;
415     if (bwriter_mod & BWRITERSPDM_PARTIALPRECISION) ret |= D3DSPDM_PARTIALPRECISION;
416     if (bwriter_mod & BWRITERSPDM_MSAMPCENTROID)    ret |= D3DSPDM_MSAMPCENTROID;
417
418     return ret;
419 }
420
421 static DWORD d3d9_comparetype(DWORD asmshader_comparetype)
422 {
423     switch (asmshader_comparetype)
424     {
425         case BWRITER_COMPARISON_GT:     return D3DSPC_GT;
426         case BWRITER_COMPARISON_EQ:     return D3DSPC_EQ;
427         case BWRITER_COMPARISON_GE:     return D3DSPC_GE;
428         case BWRITER_COMPARISON_LT:     return D3DSPC_LT;
429         case BWRITER_COMPARISON_NE:     return D3DSPC_NE;
430         case BWRITER_COMPARISON_LE:     return D3DSPC_LE;
431         default:
432             FIXME("Unexpected BWRITER_COMPARISON type %#x.\n", asmshader_comparetype);
433             return 0;
434     }
435 }
436
437 static DWORD d3d9_sampler(DWORD bwriter_sampler)
438 {
439     if (bwriter_sampler == BWRITERSTT_UNKNOWN)  return D3DSTT_UNKNOWN;
440     if (bwriter_sampler == BWRITERSTT_1D)       return D3DSTT_1D;
441     if (bwriter_sampler == BWRITERSTT_2D)       return D3DSTT_2D;
442     if (bwriter_sampler == BWRITERSTT_CUBE)     return D3DSTT_CUBE;
443     if (bwriter_sampler == BWRITERSTT_VOLUME)   return D3DSTT_VOLUME;
444     FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %#x.\n", bwriter_sampler);
445
446     return 0;
447 }
448
449 static DWORD d3d9_register(DWORD bwriter_register)
450 {
451     if (bwriter_register == BWRITERSPR_TEMP)        return D3DSPR_TEMP;
452     if (bwriter_register == BWRITERSPR_INPUT)       return D3DSPR_INPUT;
453     if (bwriter_register == BWRITERSPR_CONST)       return D3DSPR_CONST;
454     if (bwriter_register == BWRITERSPR_ADDR)        return D3DSPR_ADDR;
455     if (bwriter_register == BWRITERSPR_TEXTURE)     return D3DSPR_TEXTURE;
456     if (bwriter_register == BWRITERSPR_RASTOUT)     return D3DSPR_RASTOUT;
457     if (bwriter_register == BWRITERSPR_ATTROUT)     return D3DSPR_ATTROUT;
458     if (bwriter_register == BWRITERSPR_TEXCRDOUT)   return D3DSPR_TEXCRDOUT;
459     if (bwriter_register == BWRITERSPR_OUTPUT)      return D3DSPR_OUTPUT;
460     if (bwriter_register == BWRITERSPR_CONSTINT)    return D3DSPR_CONSTINT;
461     if (bwriter_register == BWRITERSPR_COLOROUT)    return D3DSPR_COLOROUT;
462     if (bwriter_register == BWRITERSPR_DEPTHOUT)    return D3DSPR_DEPTHOUT;
463     if (bwriter_register == BWRITERSPR_SAMPLER)     return D3DSPR_SAMPLER;
464     if (bwriter_register == BWRITERSPR_CONSTBOOL)   return D3DSPR_CONSTBOOL;
465     if (bwriter_register == BWRITERSPR_LOOP)        return D3DSPR_LOOP;
466     if (bwriter_register == BWRITERSPR_MISCTYPE)    return D3DSPR_MISCTYPE;
467     if (bwriter_register == BWRITERSPR_LABEL)       return D3DSPR_LABEL;
468     if (bwriter_register == BWRITERSPR_PREDICATE)   return D3DSPR_PREDICATE;
469
470     FIXME("Unexpected BWRITERSPR %#x.\n", bwriter_register);
471     return ~0U;
472 }
473
474 static DWORD d3d9_opcode(DWORD bwriter_opcode)
475 {
476     switch (bwriter_opcode)
477     {
478         case BWRITERSIO_NOP:         return D3DSIO_NOP;
479         case BWRITERSIO_MOV:         return D3DSIO_MOV;
480         case BWRITERSIO_ADD:         return D3DSIO_ADD;
481         case BWRITERSIO_SUB:         return D3DSIO_SUB;
482         case BWRITERSIO_MAD:         return D3DSIO_MAD;
483         case BWRITERSIO_MUL:         return D3DSIO_MUL;
484         case BWRITERSIO_RCP:         return D3DSIO_RCP;
485         case BWRITERSIO_RSQ:         return D3DSIO_RSQ;
486         case BWRITERSIO_DP3:         return D3DSIO_DP3;
487         case BWRITERSIO_DP4:         return D3DSIO_DP4;
488         case BWRITERSIO_MIN:         return D3DSIO_MIN;
489         case BWRITERSIO_MAX:         return D3DSIO_MAX;
490         case BWRITERSIO_SLT:         return D3DSIO_SLT;
491         case BWRITERSIO_SGE:         return D3DSIO_SGE;
492         case BWRITERSIO_EXP:         return D3DSIO_EXP;
493         case BWRITERSIO_LOG:         return D3DSIO_LOG;
494         case BWRITERSIO_LIT:         return D3DSIO_LIT;
495         case BWRITERSIO_DST:         return D3DSIO_DST;
496         case BWRITERSIO_LRP:         return D3DSIO_LRP;
497         case BWRITERSIO_FRC:         return D3DSIO_FRC;
498         case BWRITERSIO_M4x4:        return D3DSIO_M4x4;
499         case BWRITERSIO_M4x3:        return D3DSIO_M4x3;
500         case BWRITERSIO_M3x4:        return D3DSIO_M3x4;
501         case BWRITERSIO_M3x3:        return D3DSIO_M3x3;
502         case BWRITERSIO_M3x2:        return D3DSIO_M3x2;
503         case BWRITERSIO_CALL:        return D3DSIO_CALL;
504         case BWRITERSIO_CALLNZ:      return D3DSIO_CALLNZ;
505         case BWRITERSIO_LOOP:        return D3DSIO_LOOP;
506         case BWRITERSIO_RET:         return D3DSIO_RET;
507         case BWRITERSIO_ENDLOOP:     return D3DSIO_ENDLOOP;
508         case BWRITERSIO_LABEL:       return D3DSIO_LABEL;
509         case BWRITERSIO_DCL:         return D3DSIO_DCL;
510         case BWRITERSIO_POW:         return D3DSIO_POW;
511         case BWRITERSIO_CRS:         return D3DSIO_CRS;
512         case BWRITERSIO_SGN:         return D3DSIO_SGN;
513         case BWRITERSIO_ABS:         return D3DSIO_ABS;
514         case BWRITERSIO_NRM:         return D3DSIO_NRM;
515         case BWRITERSIO_SINCOS:      return D3DSIO_SINCOS;
516         case BWRITERSIO_REP:         return D3DSIO_REP;
517         case BWRITERSIO_ENDREP:      return D3DSIO_ENDREP;
518         case BWRITERSIO_IF:          return D3DSIO_IF;
519         case BWRITERSIO_IFC:         return D3DSIO_IFC;
520         case BWRITERSIO_ELSE:        return D3DSIO_ELSE;
521         case BWRITERSIO_ENDIF:       return D3DSIO_ENDIF;
522         case BWRITERSIO_BREAK:       return D3DSIO_BREAK;
523         case BWRITERSIO_BREAKC:      return D3DSIO_BREAKC;
524         case BWRITERSIO_MOVA:        return D3DSIO_MOVA;
525         case BWRITERSIO_DEFB:        return D3DSIO_DEFB;
526         case BWRITERSIO_DEFI:        return D3DSIO_DEFI;
527
528         case BWRITERSIO_TEXCOORD:    return D3DSIO_TEXCOORD;
529         case BWRITERSIO_TEXKILL:     return D3DSIO_TEXKILL;
530         case BWRITERSIO_TEX:         return D3DSIO_TEX;
531         case BWRITERSIO_TEXBEM:      return D3DSIO_TEXBEM;
532         case BWRITERSIO_TEXBEML:     return D3DSIO_TEXBEML;
533         case BWRITERSIO_TEXREG2AR:   return D3DSIO_TEXREG2AR;
534         case BWRITERSIO_TEXREG2GB:   return D3DSIO_TEXREG2GB;
535         case BWRITERSIO_TEXM3x2PAD:  return D3DSIO_TEXM3x2PAD;
536         case BWRITERSIO_TEXM3x2TEX:  return D3DSIO_TEXM3x2TEX;
537         case BWRITERSIO_TEXM3x3PAD:  return D3DSIO_TEXM3x3PAD;
538         case BWRITERSIO_TEXM3x3TEX:  return D3DSIO_TEXM3x3TEX;
539         case BWRITERSIO_TEXM3x3SPEC: return D3DSIO_TEXM3x3SPEC;
540         case BWRITERSIO_TEXM3x3VSPEC:return D3DSIO_TEXM3x3VSPEC;
541         case BWRITERSIO_EXPP:        return D3DSIO_EXPP;
542         case BWRITERSIO_LOGP:        return D3DSIO_LOGP;
543         case BWRITERSIO_CND:         return D3DSIO_CND;
544         case BWRITERSIO_DEF:         return D3DSIO_DEF;
545         case BWRITERSIO_TEXREG2RGB:  return D3DSIO_TEXREG2RGB;
546         case BWRITERSIO_TEXDP3TEX:   return D3DSIO_TEXDP3TEX;
547         case BWRITERSIO_TEXM3x2DEPTH:return D3DSIO_TEXM3x2DEPTH;
548         case BWRITERSIO_TEXDP3:      return D3DSIO_TEXDP3;
549         case BWRITERSIO_TEXM3x3:     return D3DSIO_TEXM3x3;
550         case BWRITERSIO_TEXDEPTH:    return D3DSIO_TEXDEPTH;
551         case BWRITERSIO_CMP:         return D3DSIO_CMP;
552         case BWRITERSIO_BEM:         return D3DSIO_BEM;
553         case BWRITERSIO_DP2ADD:      return D3DSIO_DP2ADD;
554         case BWRITERSIO_DSX:         return D3DSIO_DSX;
555         case BWRITERSIO_DSY:         return D3DSIO_DSY;
556         case BWRITERSIO_TEXLDD:      return D3DSIO_TEXLDD;
557         case BWRITERSIO_SETP:        return D3DSIO_SETP;
558         case BWRITERSIO_TEXLDL:      return D3DSIO_TEXLDL;
559         case BWRITERSIO_BREAKP:      return D3DSIO_BREAKP;
560
561         case BWRITERSIO_PHASE:       return D3DSIO_PHASE;
562         case BWRITERSIO_COMMENT:     return D3DSIO_COMMENT;
563         case BWRITERSIO_END:         return D3DSIO_END;
564
565         case BWRITERSIO_TEXLDP:      return D3DSIO_TEX | D3DSI_TEXLD_PROJECT;
566         case BWRITERSIO_TEXLDB:      return D3DSIO_TEX | D3DSI_TEXLD_BIAS;
567
568         default:
569             FIXME("Unhandled BWRITERSIO token %#x.\n", bwriter_opcode);
570             return ~0U;
571     }
572 }
573
574 /******************************************************
575  * Implementation of the writer functions starts here *
576  ******************************************************/
577 static void write_declarations(struct bc_writer *This,
578                                struct bytecode_buffer *buffer, BOOL len,
579                                const struct declaration *decls, unsigned int num, DWORD type) {
580     DWORD i;
581     DWORD instr_dcl = D3DSIO_DCL;
582     DWORD token;
583     struct shader_reg reg;
584
585     ZeroMemory(&reg, sizeof(reg));
586
587     if(len) {
588         instr_dcl |= 2 << D3DSI_INSTLENGTH_SHIFT;
589     }
590
591     for(i = 0; i < num; i++) {
592         if(decls[i].builtin) continue;
593
594         /* Write the DCL instruction */
595         put_dword(buffer, instr_dcl);
596
597         /* Write the usage and index */
598         token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
599         token |= (decls[i].usage << D3DSP_DCL_USAGE_SHIFT) & D3DSP_DCL_USAGE_MASK;
600         token |= (decls[i].usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT) & D3DSP_DCL_USAGEINDEX_MASK;
601         put_dword(buffer, token);
602
603         /* Write the dest register */
604         reg.type = type;
605         reg.regnum = decls[i].regnum;
606         reg.u.writemask = decls[i].writemask;
607         This->funcs->dstreg(This, &reg, buffer, 0, decls[i].mod);
608     }
609 }
610
611 static void write_const(struct constant **consts, int num, DWORD opcode, DWORD reg_type, struct bytecode_buffer *buffer, BOOL len) {
612     DWORD i;
613     DWORD instr_def = opcode;
614     const DWORD reg = (1<<31) |
615                       ((reg_type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
616                       ((reg_type << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
617                       D3DSP_WRITEMASK_ALL;
618
619     if(len) {
620         if(opcode == D3DSIO_DEFB)
621             instr_def |= 2 << D3DSI_INSTLENGTH_SHIFT;
622         else
623             instr_def |= 5 << D3DSI_INSTLENGTH_SHIFT;
624     }
625
626     for(i = 0; i < num; i++) {
627         /* Write the DEF instruction */
628         put_dword(buffer, instr_def);
629
630         put_dword(buffer, reg | (consts[i]->regnum & D3DSP_REGNUM_MASK));
631         put_dword(buffer, consts[i]->value[0].d);
632         if(opcode != D3DSIO_DEFB) {
633             put_dword(buffer, consts[i]->value[1].d);
634             put_dword(buffer, consts[i]->value[2].d);
635             put_dword(buffer, consts[i]->value[3].d);
636         }
637     }
638 }
639
640 static void write_constF(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
641     write_const(shader->constF, shader->num_cf, D3DSIO_DEF, D3DSPR_CONST, buffer, len);
642 }
643
644 /* This function looks for VS 1/2 registers mapping to VS 3 output registers */
645 static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwriter_shader *shader) {
646     DWORD i;
647     DWORD usage, usage_idx, writemask, regnum;
648
649     for(i = 0; i < shader->num_outputs; i++) {
650         if(!shader->outputs[i].builtin) continue;
651
652         usage = shader->outputs[i].usage;
653         usage_idx = shader->outputs[i].usage_idx;
654         writemask = shader->outputs[i].writemask;
655         regnum = shader->outputs[i].regnum;
656
657         switch(usage) {
658             case BWRITERDECLUSAGE_POSITION:
659             case BWRITERDECLUSAGE_POSITIONT:
660                 if(usage_idx > 0) {
661                     WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx);
662                     return E_INVALIDARG;
663                 }
664                 TRACE("o%u is oPos\n", regnum);
665                 This->oPos_regnum = regnum;
666                 break;
667
668             case BWRITERDECLUSAGE_COLOR:
669                 if(usage_idx > 1) {
670                     WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
671                     return E_INVALIDARG;
672                 }
673                 if(writemask != BWRITERSP_WRITEMASK_ALL) {
674                     WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
675                     return E_INVALIDARG;
676                 }
677                 TRACE("o%u is oD%u\n", regnum, usage_idx);
678                 This->oD_regnum[usage_idx] = regnum;
679                 break;
680
681             case BWRITERDECLUSAGE_TEXCOORD:
682                 if(usage_idx >= 8) {
683                     WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
684                     return E_INVALIDARG;
685                 }
686                 if(writemask != (BWRITERSP_WRITEMASK_0) &&
687                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
688                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
689                    writemask != (BWRITERSP_WRITEMASK_ALL)) {
690                     WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
691                     return E_INVALIDARG;
692                 }
693                 TRACE("o%u is oT%u\n", regnum, usage_idx);
694                 This->oT_regnum[usage_idx] = regnum;
695                 break;
696
697             case BWRITERDECLUSAGE_PSIZE:
698                 if(usage_idx > 0) {
699                     WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx);
700                     return E_INVALIDARG;
701                 }
702                 TRACE("o%u writemask 0x%08x is oPts\n", regnum, writemask);
703                 This->oPts_regnum = regnum;
704                 This->oPts_mask = writemask;
705                 break;
706
707             case BWRITERDECLUSAGE_FOG:
708                 if(usage_idx > 0) {
709                     WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx);
710                     return E_INVALIDARG;
711                 }
712                 if(writemask != BWRITERSP_WRITEMASK_0 && writemask != BWRITERSP_WRITEMASK_1 &&
713                    writemask != BWRITERSP_WRITEMASK_2 && writemask != BWRITERSP_WRITEMASK_3) {
714                     WARN("Unsupported fog writemask\n");
715                     return E_INVALIDARG;
716                 }
717                 TRACE("o%u writemask 0x%08x is oFog\n", regnum, writemask);
718                 This->oFog_regnum = regnum;
719                 This->oFog_mask = writemask;
720                 break;
721
722             default:
723                 WARN("Varying type %u is not supported in shader model 1.x\n", usage);
724                 return E_INVALIDARG;
725         }
726     }
727
728     return S_OK;
729 }
730
731 static void vs_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
732     HRESULT hr;
733
734     if(shader->num_ci || shader->num_cb) {
735         WARN("Int and bool constants are not supported in shader model 1 shaders\n");
736         WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
737         This->state = E_INVALIDARG;
738         return;
739     }
740
741     hr = vs_find_builtin_varyings(This, shader);
742     if(FAILED(hr)) {
743         This->state = hr;
744         return;
745     }
746
747     write_declarations(This, buffer, FALSE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
748     write_constF(shader, buffer, FALSE);
749 }
750
751 static HRESULT find_ps_builtin_semantics(struct bc_writer *This,
752                                          const struct bwriter_shader *shader,
753                                          DWORD texcoords) {
754     DWORD i;
755     DWORD usage, usage_idx, writemask, regnum;
756
757     This->v_regnum[0] = -1; This->v_regnum[1] = -1;
758     for(i = 0; i < 8; i++) This->t_regnum[i] = -1;
759
760     for(i = 0; i < shader->num_inputs; i++) {
761         if(!shader->inputs[i].builtin) continue;
762
763         usage = shader->inputs[i].usage;
764         usage_idx = shader->inputs[i].usage_idx;
765         writemask = shader->inputs[i].writemask;
766         regnum = shader->inputs[i].regnum;
767
768         switch(usage) {
769             case BWRITERDECLUSAGE_COLOR:
770                 if(usage_idx > 1) {
771                     WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx);
772                     return E_INVALIDARG;
773                 }
774                 if(writemask != BWRITERSP_WRITEMASK_ALL) {
775                     WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
776                     return E_INVALIDARG;
777                 }
778                 TRACE("v%u is v%u\n", regnum, usage_idx);
779                 This->v_regnum[usage_idx] = regnum;
780                 break;
781
782             case BWRITERDECLUSAGE_TEXCOORD:
783                 if(usage_idx > texcoords) {
784                     WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx);
785                     return E_INVALIDARG;
786                 }
787                 if(writemask != (BWRITERSP_WRITEMASK_0) &&
788                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
789                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
790                    writemask != (BWRITERSP_WRITEMASK_ALL)) {
791                     WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
792                 } else {
793                     writemask = BWRITERSP_WRITEMASK_ALL;
794                 }
795                 TRACE("v%u is t%u\n", regnum, usage_idx);
796                 This->t_regnum[usage_idx] = regnum;
797                 break;
798
799             default:
800                 WARN("Varying type %u is not supported in shader model 1.x\n", usage);
801                 return E_INVALIDARG;
802         }
803     }
804
805     return S_OK;
806 }
807
808 static void ps_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
809     HRESULT hr;
810
811     /* First check the constants and varyings, and complain if unsupported things are used */
812     if(shader->num_ci || shader->num_cb) {
813         WARN("Int and bool constants are not supported in shader model 1 shaders\n");
814         WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
815         This->state = E_INVALIDARG;
816         return;
817     }
818
819     hr = find_ps_builtin_semantics(This, shader, 4);
820     if(FAILED(hr)) {
821         This->state = hr;
822         return;
823     }
824
825     write_constF(shader, buffer, FALSE);
826 }
827
828 static void ps_1_4_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
829     HRESULT hr;
830
831     /* First check the constants and varyings, and complain if unsupported things are used */
832     if(shader->num_ci || shader->num_cb) {
833         WARN("Int and bool constants are not supported in shader model 1 shaders\n");
834         WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
835         This->state = E_INVALIDARG;
836         return;
837     }
838     hr = find_ps_builtin_semantics(This, shader, 6);
839     if(FAILED(hr)) {
840         This->state = hr;
841         return;
842     }
843
844     write_constF(shader, buffer, FALSE);
845 }
846
847 static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
848     put_dword(buffer, D3DSIO_END);
849 }
850
851 static DWORD map_vs_output(struct bc_writer *This, DWORD regnum, DWORD mask, DWORD *has_components) {
852     DWORD token = 0;
853     DWORD i;
854
855     *has_components = TRUE;
856     if(regnum == This->oPos_regnum) {
857         token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
858         token |= D3DSRO_POSITION & D3DSP_REGNUM_MASK; /* No shift */
859         return token;
860     }
861     if(regnum == This->oFog_regnum && mask == This->oFog_mask) {
862         token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
863         token |= D3DSRO_FOG & D3DSP_REGNUM_MASK; /* No shift */
864         token |= D3DSP_WRITEMASK_ALL;
865         *has_components = FALSE;
866         return token;
867     }
868     if(regnum == This->oPts_regnum && mask == This->oPts_mask) {
869         token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
870         token |= D3DSRO_POINT_SIZE & D3DSP_REGNUM_MASK; /* No shift */
871         token |= D3DSP_WRITEMASK_ALL;
872         *has_components = FALSE;
873         return token;
874     }
875     for(i = 0; i < 2; i++) {
876         if(regnum == This->oD_regnum[i]) {
877             token |= (D3DSPR_ATTROUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
878             token |= i & D3DSP_REGNUM_MASK; /* No shift */
879             return token;
880         }
881     }
882     for(i = 0; i < 8; i++) {
883         if(regnum == This->oT_regnum[i]) {
884             token |= (D3DSPR_TEXCRDOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
885             token |= i & D3DSP_REGNUM_MASK; /* No shift */
886             return token;
887         }
888     }
889
890     /* The varying must be undeclared - if an unsupported varying was declared,
891      * the vs_find_builtin_varyings function would have caught it and this code
892      * would not run */
893     WARN("Undeclared varying %u\n", regnum);
894     This->state = E_INVALIDARG;
895     return -1;
896 }
897
898 static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg,
899                          struct bytecode_buffer *buffer,
900                          DWORD shift, DWORD mod) {
901     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
902     DWORD has_wmask;
903
904     if(reg->rel_reg) {
905         WARN("Relative addressing not supported for destination registers\n");
906         This->state = E_INVALIDARG;
907         return;
908     }
909
910     switch(reg->type) {
911         case BWRITERSPR_OUTPUT:
912             token |= map_vs_output(This, reg->regnum, reg->u.writemask, &has_wmask);
913             break;
914
915         case BWRITERSPR_RASTOUT:
916         case BWRITERSPR_ATTROUT:
917             /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
918             * but are unexpected. If we hit this path it might be due to an error.
919             */
920             FIXME("Unexpected register type %u\n", reg->type);
921             /* drop through */
922         case BWRITERSPR_INPUT:
923         case BWRITERSPR_TEMP:
924         case BWRITERSPR_CONST:
925             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
926             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
927             has_wmask = TRUE;
928             break;
929
930         case BWRITERSPR_ADDR:
931             if(reg->regnum != 0) {
932                 WARN("Only a0 exists\n");
933                 This->state = E_INVALIDARG;
934                 return;
935             }
936             token |= (D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
937             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
938             has_wmask = TRUE;
939             break;
940
941         case BWRITERSPR_PREDICATE:
942             if(This->version != BWRITERVS_VERSION(2, 1)){
943                 WARN("Predicate register is allowed only in vs_2_x\n");
944                 This->state = E_INVALIDARG;
945                 return;
946             }
947             if(reg->regnum != 0) {
948                 WARN("Only predicate register p0 exists\n");
949                 This->state = E_INVALIDARG;
950                 return;
951             }
952             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
953             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
954             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
955             has_wmask = TRUE;
956             break;
957
958         default:
959             WARN("Invalid register type for 1.x-2.x vertex shader\n");
960             This->state = E_INVALIDARG;
961             return;
962     }
963
964     /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
965      * into the bytecode and since the compiler doesn't do such checks write them
966      * (the checks are done by the undocumented shader validator)
967      */
968     token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
969     token |= d3d9_dstmod(mod);
970
971     if(has_wmask) {
972         token |= d3d9_writemask(reg->u.writemask);
973     }
974     put_dword(buffer, token);
975 }
976
977 static void vs_1_x_srcreg(struct bc_writer *This, const struct shader_reg *reg,
978                           struct bytecode_buffer *buffer) {
979     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
980     DWORD has_swizzle;
981     DWORD component;
982
983     switch(reg->type) {
984         case BWRITERSPR_OUTPUT:
985             /* Map the swizzle to a writemask, the format expected
986                by map_vs_output
987              */
988             switch(reg->u.swizzle) {
989                 case BWRITERVS_SWIZZLE_X:
990                     component = BWRITERSP_WRITEMASK_0;
991                     break;
992                 case BWRITERVS_SWIZZLE_Y:
993                     component = BWRITERSP_WRITEMASK_1;
994                     break;
995                 case BWRITERVS_SWIZZLE_Z:
996                     component = BWRITERSP_WRITEMASK_2;
997                     break;
998                 case BWRITERVS_SWIZZLE_W:
999                     component = BWRITERSP_WRITEMASK_3;
1000                     break;
1001                 default:
1002                     component = 0;
1003             }
1004             token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
1005             break;
1006
1007         case BWRITERSPR_RASTOUT:
1008         case BWRITERSPR_ATTROUT:
1009             /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1010              * but are unexpected. If we hit this path it might be due to an error.
1011              */
1012             FIXME("Unexpected register type %u\n", reg->type);
1013             /* drop through */
1014         case BWRITERSPR_INPUT:
1015         case BWRITERSPR_TEMP:
1016         case BWRITERSPR_CONST:
1017         case BWRITERSPR_ADDR:
1018             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1019             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1020             if(reg->rel_reg) {
1021                 if(reg->rel_reg->type != BWRITERSPR_ADDR ||
1022                    reg->rel_reg->regnum != 0 ||
1023                    reg->rel_reg->u.swizzle != BWRITERVS_SWIZZLE_X) {
1024                     WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
1025                     This->state = E_INVALIDARG;
1026                     return;
1027                 }
1028                 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1029             }
1030             break;
1031
1032         default:
1033             WARN("Invalid register type for 1.x vshader\n");
1034             This->state = E_INVALIDARG;
1035             return;
1036     }
1037
1038     token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1039
1040     token |= d3d9_srcmod(reg->srcmod);
1041     put_dword(buffer, token);
1042 }
1043
1044 static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
1045                           struct bytecode_buffer *buffer){
1046     unsigned int i;
1047     if(instr->has_predicate){
1048         This->funcs->srcreg(This, &instr->predicate, buffer);
1049     }
1050     for(i = 0; i < instr->num_srcs; i++){
1051         This->funcs->srcreg(This, &instr->src[i], buffer);
1052     }
1053 }
1054
1055 static DWORD map_ps13_temp(struct bc_writer *This, const struct shader_reg *reg) {
1056     DWORD token = 0;
1057     if(reg->regnum == T0_REG) {
1058         token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1059         token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1060     } else if(reg->regnum == T1_REG) {
1061         token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1062         token |= 1 & D3DSP_REGNUM_MASK; /* No shift */
1063     } else if(reg->regnum == T2_REG) {
1064         token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1065         token |= 2 & D3DSP_REGNUM_MASK; /* No shift */
1066     } else if(reg->regnum == T3_REG) {
1067         token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1068         token |= 3 & D3DSP_REGNUM_MASK; /* No shift */
1069     } else {
1070         token |= (D3DSPR_TEMP << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1071         token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1072     }
1073     return token;
1074 }
1075
1076 static DWORD map_ps_input(struct bc_writer *This,
1077                           const struct shader_reg *reg) {
1078     DWORD i, token = 0;
1079     /* Map color interpolators */
1080     for(i = 0; i < 2; i++) {
1081         if(reg->regnum == This->v_regnum[i]) {
1082             token |= (D3DSPR_INPUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1083             token |= i & D3DSP_REGNUM_MASK; /* No shift */
1084             return token;
1085         }
1086     }
1087     for(i = 0; i < 8; i++) {
1088         if(reg->regnum == This->t_regnum[i]) {
1089             token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1090             token |= i & D3DSP_REGNUM_MASK; /* No shift */
1091             return token;
1092         }
1093     }
1094
1095     WARN("Invalid ps 1/2 varying\n");
1096     This->state = E_INVALIDARG;
1097     return token;
1098 }
1099
1100 static void ps_1_0123_srcreg(struct bc_writer *This, const struct shader_reg *reg,
1101                              struct bytecode_buffer *buffer) {
1102     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1103     if(reg->rel_reg) {
1104         WARN("Relative addressing not supported in <= ps_3_0\n");
1105         This->state = E_INVALIDARG;
1106         return;
1107     }
1108
1109     switch(reg->type) {
1110         case BWRITERSPR_INPUT:
1111             token |= map_ps_input(This, reg);
1112             break;
1113
1114             /* Take care about the texture temporaries. There's a problem: They aren't
1115              * declared anywhere, so we can only hardcode the values that are used
1116              * to map ps_1_3 shaders to the common shader structure
1117              */
1118         case BWRITERSPR_TEMP:
1119             token |= map_ps13_temp(This, reg);
1120             break;
1121
1122         case BWRITERSPR_CONST: /* Can be mapped 1:1 */
1123             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1124             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1125             break;
1126
1127         default:
1128             WARN("Invalid register type for <= ps_1_3 shader\n");
1129             This->state = E_INVALIDARG;
1130             return;
1131     }
1132
1133     token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1134
1135     if(reg->srcmod == BWRITERSPSM_DZ || reg->srcmod == BWRITERSPSM_DW ||
1136        reg->srcmod == BWRITERSPSM_ABS || reg->srcmod == BWRITERSPSM_ABSNEG ||
1137        reg->srcmod == BWRITERSPSM_NOT) {
1138         WARN("Invalid source modifier %u for <= ps_1_3\n", reg->srcmod);
1139         This->state = E_INVALIDARG;
1140         return;
1141     }
1142     token |= d3d9_srcmod(reg->srcmod);
1143     put_dword(buffer, token);
1144 }
1145
1146 static void ps_1_0123_dstreg(struct bc_writer *This, const struct shader_reg *reg,
1147                              struct bytecode_buffer *buffer,
1148                              DWORD shift, DWORD mod) {
1149     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1150
1151     if(reg->rel_reg) {
1152         WARN("Relative addressing not supported for destination registers\n");
1153         This->state = E_INVALIDARG;
1154         return;
1155     }
1156
1157     switch(reg->type) {
1158         case BWRITERSPR_TEMP:
1159             token |= map_ps13_temp(This, reg);
1160             break;
1161
1162         /* texkill uses the input register as a destination parameter */
1163         case BWRITERSPR_INPUT:
1164             token |= map_ps_input(This, reg);
1165             break;
1166
1167         default:
1168             WARN("Invalid dest register type for 1.x pshader\n");
1169             This->state = E_INVALIDARG;
1170             return;
1171     }
1172
1173     token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1174     token |= d3d9_dstmod(mod);
1175
1176     token |= d3d9_writemask(reg->u.writemask);
1177     put_dword(buffer, token);
1178 }
1179
1180 /* The length of an instruction consists of the destination register (if any),
1181  * the number of source registers, the number of address registers used for
1182  * indirect addressing, and optionally the predicate register
1183  */
1184 static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsigned int dsts) {
1185     unsigned int i;
1186     DWORD ret = srcs + dsts + (instr->has_predicate ? 1 : 0);
1187
1188     if(dsts){
1189         if(instr->dst.rel_reg) ret++;
1190     }
1191     for(i = 0; i < srcs; i++) {
1192         if(instr->src[i].rel_reg) ret++;
1193     }
1194     return ret;
1195 }
1196
1197 static void sm_1_x_opcode(struct bc_writer *This,
1198                           const struct instruction *instr,
1199                           DWORD token, struct bytecode_buffer *buffer) {
1200     /* In sm_1_x instruction length isn't encoded */
1201     if(instr->coissue){
1202         token |= D3DSI_COISSUE;
1203     }
1204     put_dword(buffer, token);
1205 }
1206
1207 static void instr_handler(struct bc_writer *This,
1208                           const struct instruction *instr,
1209                           struct bytecode_buffer *buffer) {
1210     DWORD token = d3d9_opcode(instr->opcode);
1211
1212     This->funcs->opcode(This, instr, token, buffer);
1213     if(instr->has_dst) This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1214     write_srcregs(This, instr, buffer);
1215 }
1216
1217 static const struct instr_handler_table vs_1_x_handlers[] = {
1218     {BWRITERSIO_ADD,            instr_handler},
1219     {BWRITERSIO_NOP,            instr_handler},
1220     {BWRITERSIO_MOV,            instr_handler},
1221     {BWRITERSIO_SUB,            instr_handler},
1222     {BWRITERSIO_MAD,            instr_handler},
1223     {BWRITERSIO_MUL,            instr_handler},
1224     {BWRITERSIO_RCP,            instr_handler},
1225     {BWRITERSIO_RSQ,            instr_handler},
1226     {BWRITERSIO_DP3,            instr_handler},
1227     {BWRITERSIO_DP4,            instr_handler},
1228     {BWRITERSIO_MIN,            instr_handler},
1229     {BWRITERSIO_MAX,            instr_handler},
1230     {BWRITERSIO_SLT,            instr_handler},
1231     {BWRITERSIO_SGE,            instr_handler},
1232     {BWRITERSIO_EXP,            instr_handler},
1233     {BWRITERSIO_LOG,            instr_handler},
1234     {BWRITERSIO_EXPP,           instr_handler},
1235     {BWRITERSIO_LOGP,           instr_handler},
1236     {BWRITERSIO_DST,            instr_handler},
1237     {BWRITERSIO_FRC,            instr_handler},
1238     {BWRITERSIO_M4x4,           instr_handler},
1239     {BWRITERSIO_M4x3,           instr_handler},
1240     {BWRITERSIO_M3x4,           instr_handler},
1241     {BWRITERSIO_M3x3,           instr_handler},
1242     {BWRITERSIO_M3x2,           instr_handler},
1243     {BWRITERSIO_LIT,            instr_handler},
1244
1245     {BWRITERSIO_END,            NULL}, /* Sentinel value, it signals
1246                                           the end of the list */
1247 };
1248
1249 static const struct bytecode_backend vs_1_x_backend = {
1250     vs_1_x_header,
1251     end,
1252     vs_1_x_srcreg,
1253     vs_12_dstreg,
1254     sm_1_x_opcode,
1255     vs_1_x_handlers
1256 };
1257
1258 static void instr_ps_1_0123_texld(struct bc_writer *This,
1259                                   const struct instruction *instr,
1260                                   struct bytecode_buffer *buffer) {
1261     DWORD idx;
1262     struct shader_reg reg;
1263     DWORD swizzlemask;
1264
1265     if(instr->src[1].type != BWRITERSPR_SAMPLER ||
1266        instr->src[1].regnum > 3) {
1267         WARN("Unsupported sampler type %u regnum %u\n",
1268              instr->src[1].type, instr->src[1].regnum);
1269         This->state = E_INVALIDARG;
1270         return;
1271     } else if(instr->dst.type != BWRITERSPR_TEMP) {
1272         WARN("Can only sample into a temp register\n");
1273         This->state = E_INVALIDARG;
1274         return;
1275     }
1276
1277     idx = instr->src[1].regnum;
1278     if((idx == 0 && instr->dst.regnum != T0_REG) ||
1279        (idx == 1 && instr->dst.regnum != T1_REG) ||
1280        (idx == 2 && instr->dst.regnum != T2_REG) ||
1281        (idx == 3 && instr->dst.regnum != T3_REG)) {
1282         WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n",
1283              idx, instr->dst.regnum);
1284         This->state = E_INVALIDARG;
1285         return;
1286     }
1287     if(instr->src[0].type == BWRITERSPR_INPUT) {
1288         /* A simple non-dependent read tex instruction */
1289         if(instr->src[0].regnum != This->t_regnum[idx]) {
1290             WARN("Cannot sample from s%u with texture address data from interpolator %u\n",
1291                  idx, instr->src[0].regnum);
1292             This->state = E_INVALIDARG;
1293             return;
1294         }
1295         This->funcs->opcode(This, instr, D3DSIO_TEX & D3DSI_OPCODE_MASK, buffer);
1296
1297         /* map the temp dstreg to the ps_1_3 texture temporary register */
1298         This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1299     } else if(instr->src[0].type == BWRITERSPR_TEMP) {
1300
1301         swizzlemask = (3 << BWRITERVS_SWIZZLE_SHIFT) |
1302             (3 << (BWRITERVS_SWIZZLE_SHIFT + 2)) |
1303             (3 << (BWRITERVS_SWIZZLE_SHIFT + 4));
1304         if((instr->src[0].u.swizzle & swizzlemask) == (BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z)) {
1305             TRACE("writing texreg2rgb\n");
1306             This->funcs->opcode(This, instr, D3DSIO_TEXREG2RGB & D3DSI_OPCODE_MASK, buffer);
1307         } else if(instr->src[0].u.swizzle == (BWRITERVS_X_W | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X)) {
1308             TRACE("writing texreg2ar\n");
1309             This->funcs->opcode(This, instr, D3DSIO_TEXREG2AR & D3DSI_OPCODE_MASK, buffer);
1310         } else if(instr->src[0].u.swizzle == (BWRITERVS_X_Y | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z)) {
1311             TRACE("writing texreg2gb\n");
1312             This->funcs->opcode(This, instr, D3DSIO_TEXREG2GB & D3DSI_OPCODE_MASK, buffer);
1313         } else {
1314             WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr->src[0].u.swizzle);
1315             This->state = E_INVALIDARG;
1316             return;
1317         }
1318
1319         /* Dst and src reg can be mapped normally. Both registers are temporary registers in the
1320          * source shader and have to be mapped to the temporary form of the texture registers. However,
1321          * the src reg doesn't have a swizzle
1322          */
1323         This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1324         reg = instr->src[0];
1325         reg.u.swizzle = BWRITERVS_NOSWIZZLE;
1326         This->funcs->srcreg(This, &reg, buffer);
1327     } else {
1328         WARN("Invalid address data source register\n");
1329         This->state = E_INVALIDARG;
1330         return;
1331     }
1332 }
1333
1334 static void instr_ps_1_0123_mov(struct bc_writer *This,
1335                                 const struct instruction *instr,
1336                                 struct bytecode_buffer *buffer) {
1337     DWORD token = D3DSIO_MOV & D3DSI_OPCODE_MASK;
1338
1339     if(instr->dst.type == BWRITERSPR_TEMP && instr->src[0].type == BWRITERSPR_INPUT) {
1340         if((instr->dst.regnum == T0_REG && instr->src[0].regnum == This->t_regnum[0]) ||
1341            (instr->dst.regnum == T1_REG && instr->src[0].regnum == This->t_regnum[1]) ||
1342            (instr->dst.regnum == T2_REG && instr->src[0].regnum == This->t_regnum[2]) ||
1343            (instr->dst.regnum == T3_REG && instr->src[0].regnum == This->t_regnum[3])) {
1344             if(instr->dstmod & BWRITERSPDM_SATURATE) {
1345                 This->funcs->opcode(This, instr, D3DSIO_TEXCOORD & D3DSI_OPCODE_MASK, buffer);
1346                 /* Remove the SATURATE flag, it's implicit to the instruction */
1347                 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod & (~BWRITERSPDM_SATURATE));
1348                 return;
1349             } else {
1350                 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1351                 This->state = E_INVALIDARG;
1352                 return;
1353             }
1354         } else if(instr->src[0].regnum == This->v_regnum[0] ||
1355                   instr->src[0].regnum == This->v_regnum[1]) {
1356             /* Handled by the normal mov below. Just drop out of the if condition */
1357         } else {
1358             WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1359             This->state = E_INVALIDARG;
1360             return;
1361         }
1362     }
1363
1364     This->funcs->opcode(This, instr, token, buffer);
1365     This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1366     This->funcs->srcreg(This, &instr->src[0], buffer);
1367 }
1368
1369 static const struct instr_handler_table ps_1_0123_handlers[] = {
1370     {BWRITERSIO_ADD,            instr_handler},
1371     {BWRITERSIO_NOP,            instr_handler},
1372     {BWRITERSIO_MOV,            instr_ps_1_0123_mov},
1373     {BWRITERSIO_SUB,            instr_handler},
1374     {BWRITERSIO_MAD,            instr_handler},
1375     {BWRITERSIO_MUL,            instr_handler},
1376     {BWRITERSIO_DP3,            instr_handler},
1377     {BWRITERSIO_DP4,            instr_handler},
1378     {BWRITERSIO_LRP,            instr_handler},
1379
1380     /* pshader instructions */
1381     {BWRITERSIO_CND,            instr_handler},
1382     {BWRITERSIO_CMP,            instr_handler},
1383     {BWRITERSIO_TEXKILL,        instr_handler},
1384     {BWRITERSIO_TEX,            instr_ps_1_0123_texld},
1385     {BWRITERSIO_TEXBEM,         instr_handler},
1386     {BWRITERSIO_TEXBEML,        instr_handler},
1387     {BWRITERSIO_TEXM3x2PAD,     instr_handler},
1388     {BWRITERSIO_TEXM3x3PAD,     instr_handler},
1389     {BWRITERSIO_TEXM3x3SPEC,    instr_handler},
1390     {BWRITERSIO_TEXM3x3VSPEC,   instr_handler},
1391     {BWRITERSIO_TEXM3x3TEX,     instr_handler},
1392     {BWRITERSIO_TEXM3x3,        instr_handler},
1393     {BWRITERSIO_TEXM3x2DEPTH,   instr_handler},
1394     {BWRITERSIO_TEXM3x2TEX,     instr_handler},
1395     {BWRITERSIO_TEXDP3,         instr_handler},
1396     {BWRITERSIO_TEXDP3TEX,      instr_handler},
1397     {BWRITERSIO_END,            NULL},
1398 };
1399
1400 static const struct bytecode_backend ps_1_0123_backend = {
1401     ps_1_x_header,
1402     end,
1403     ps_1_0123_srcreg,
1404     ps_1_0123_dstreg,
1405     sm_1_x_opcode,
1406     ps_1_0123_handlers
1407 };
1408
1409 static void ps_1_4_srcreg(struct bc_writer *This, const struct shader_reg *reg,
1410                           struct bytecode_buffer *buffer) {
1411     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1412     if(reg->rel_reg) {
1413         WARN("Relative addressing not supported in <= ps_3_0\n");
1414         This->state = E_INVALIDARG;
1415         return;
1416     }
1417
1418     switch(reg->type) {
1419         case BWRITERSPR_INPUT:
1420             token |= map_ps_input(This, reg);
1421             break;
1422
1423         /* Can be mapped 1:1 */
1424         case BWRITERSPR_TEMP:
1425         case BWRITERSPR_CONST:
1426             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1427             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1428             break;
1429
1430         default:
1431             WARN("Invalid register type for ps_1_4 shader\n");
1432             This->state = E_INVALIDARG;
1433             return;
1434     }
1435
1436     token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1437
1438     if(reg->srcmod == BWRITERSPSM_ABS || reg->srcmod == BWRITERSPSM_ABSNEG ||
1439        reg->srcmod == BWRITERSPSM_NOT) {
1440         WARN("Invalid source modifier %u for ps_1_4\n", reg->srcmod);
1441         This->state = E_INVALIDARG;
1442         return;
1443     }
1444     token |= d3d9_srcmod(reg->srcmod);
1445     put_dword(buffer, token);
1446 }
1447
1448 static void ps_1_4_dstreg(struct bc_writer *This, const struct shader_reg *reg,
1449                           struct bytecode_buffer *buffer,
1450                           DWORD shift, DWORD mod) {
1451     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1452
1453     if(reg->rel_reg) {
1454         WARN("Relative addressing not supported for destination registers\n");
1455         This->state = E_INVALIDARG;
1456         return;
1457     }
1458
1459     switch(reg->type) {
1460         case BWRITERSPR_TEMP: /* 1:1 mapping */
1461             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1462             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1463             break;
1464
1465         /* For texkill */
1466         case BWRITERSPR_INPUT:
1467             token |= map_ps_input(This, reg);
1468             break;
1469
1470         default:
1471             WARN("Invalid dest register type for 1.x pshader\n");
1472             This->state = E_INVALIDARG;
1473             return;
1474     }
1475
1476     token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1477     token |= d3d9_dstmod(mod);
1478
1479     token |= d3d9_writemask(reg->u.writemask);
1480     put_dword(buffer, token);
1481 }
1482
1483 static void instr_ps_1_4_mov(struct bc_writer *This,
1484                              const struct instruction *instr,
1485                              struct bytecode_buffer *buffer) {
1486     DWORD token = D3DSIO_MOV & D3DSI_OPCODE_MASK;
1487
1488     if(instr->dst.type == BWRITERSPR_TEMP && instr->src[0].type == BWRITERSPR_INPUT) {
1489         if(instr->src[0].regnum == This->t_regnum[0] ||
1490            instr->src[0].regnum == This->t_regnum[1] ||
1491            instr->src[0].regnum == This->t_regnum[2] ||
1492            instr->src[0].regnum == This->t_regnum[3] ||
1493            instr->src[0].regnum == This->t_regnum[4] ||
1494            instr->src[0].regnum == This->t_regnum[5]) {
1495             /* Similar to a regular mov, but a different opcode */
1496             token = D3DSIO_TEXCOORD & D3DSI_OPCODE_MASK;
1497         } else if(instr->src[0].regnum == This->v_regnum[0] ||
1498                   instr->src[0].regnum == This->v_regnum[1]) {
1499             /* Handled by the normal mov below. Just drop out of the if condition */
1500         } else {
1501             WARN("Unsupported varying -> temp mov in ps_1_4\n");
1502             This->state = E_INVALIDARG;
1503             return;
1504         }
1505     }
1506
1507     This->funcs->opcode(This, instr, token, buffer);
1508     This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1509     This->funcs->srcreg(This, &instr->src[0], buffer);
1510 }
1511
1512 static void instr_ps_1_4_texld(struct bc_writer *This,
1513                                const struct instruction *instr,
1514                                struct bytecode_buffer *buffer) {
1515     if(instr->src[1].type != BWRITERSPR_SAMPLER ||
1516        instr->src[1].regnum > 5) {
1517         WARN("Unsupported sampler type %u regnum %u\n",
1518              instr->src[1].type, instr->src[1].regnum);
1519         This->state = E_INVALIDARG;
1520         return;
1521     } else if(instr->dst.type != BWRITERSPR_TEMP) {
1522         WARN("Can only sample into a temp register\n");
1523         This->state = E_INVALIDARG;
1524         return;
1525     }
1526
1527     if(instr->src[1].regnum != instr->dst.regnum) {
1528         WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4\n",
1529              instr->src[1].regnum, instr->dst.regnum);
1530         This->state = E_INVALIDARG;
1531         return;
1532     }
1533
1534     This->funcs->opcode(This, instr, D3DSIO_TEX & D3DSI_OPCODE_MASK, buffer);
1535     This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1536     This->funcs->srcreg(This, &instr->src[0], buffer);
1537 }
1538
1539 static const struct instr_handler_table ps_1_4_handlers[] = {
1540     {BWRITERSIO_ADD,            instr_handler},
1541     {BWRITERSIO_NOP,            instr_handler},
1542     {BWRITERSIO_MOV,            instr_ps_1_4_mov},
1543     {BWRITERSIO_SUB,            instr_handler},
1544     {BWRITERSIO_MAD,            instr_handler},
1545     {BWRITERSIO_MUL,            instr_handler},
1546     {BWRITERSIO_DP3,            instr_handler},
1547     {BWRITERSIO_DP4,            instr_handler},
1548     {BWRITERSIO_LRP,            instr_handler},
1549
1550     /* pshader instructions */
1551     {BWRITERSIO_CND,            instr_handler},
1552     {BWRITERSIO_CMP,            instr_handler},
1553     {BWRITERSIO_TEXKILL,        instr_handler},
1554     {BWRITERSIO_TEX,            instr_ps_1_4_texld},
1555     {BWRITERSIO_TEXDEPTH,       instr_handler},
1556     {BWRITERSIO_BEM,            instr_handler},
1557
1558     {BWRITERSIO_PHASE,          instr_handler},
1559     {BWRITERSIO_END,            NULL},
1560 };
1561
1562 static const struct bytecode_backend ps_1_4_backend = {
1563     ps_1_4_header,
1564     end,
1565     ps_1_4_srcreg,
1566     ps_1_4_dstreg,
1567     sm_1_x_opcode,
1568     ps_1_4_handlers
1569 };
1570
1571 static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
1572     write_const(shader->constB, shader->num_cb, D3DSIO_DEFB, D3DSPR_CONSTBOOL, buffer, len);
1573 }
1574
1575 static void write_constI(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
1576     write_const(shader->constI, shader->num_ci, D3DSIO_DEFI, D3DSPR_CONSTINT, buffer, len);
1577 }
1578
1579 static void vs_2_header(struct bc_writer *This,
1580                         const struct bwriter_shader *shader,
1581                         struct bytecode_buffer *buffer) {
1582     HRESULT hr;
1583
1584     hr = vs_find_builtin_varyings(This, shader);
1585     if(FAILED(hr)) {
1586         This->state = hr;
1587         return;
1588     }
1589
1590     write_declarations(This, buffer, TRUE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
1591     write_constF(shader, buffer, TRUE);
1592     write_constB(shader, buffer, TRUE);
1593     write_constI(shader, buffer, TRUE);
1594 }
1595
1596 static void vs_2_srcreg(struct bc_writer *This,
1597                         const struct shader_reg *reg,
1598                         struct bytecode_buffer *buffer) {
1599     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1600     DWORD has_swizzle;
1601     DWORD component;
1602     DWORD d3d9reg;
1603
1604     switch(reg->type) {
1605         case BWRITERSPR_OUTPUT:
1606             /* Map the swizzle to a writemask, the format expected
1607                by map_vs_output
1608              */
1609             switch(reg->u.swizzle) {
1610                 case BWRITERVS_SWIZZLE_X:
1611                     component = BWRITERSP_WRITEMASK_0;
1612                     break;
1613                 case BWRITERVS_SWIZZLE_Y:
1614                     component = BWRITERSP_WRITEMASK_1;
1615                     break;
1616                 case BWRITERVS_SWIZZLE_Z:
1617                     component = BWRITERSP_WRITEMASK_2;
1618                     break;
1619                 case BWRITERVS_SWIZZLE_W:
1620                     component = BWRITERSP_WRITEMASK_3;
1621                     break;
1622                 default:
1623                     component = 0;
1624             }
1625             token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
1626             break;
1627
1628         case BWRITERSPR_RASTOUT:
1629         case BWRITERSPR_ATTROUT:
1630             /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1631              * but are unexpected. If we hit this path it might be due to an error.
1632              */
1633             FIXME("Unexpected register type %u\n", reg->type);
1634             /* drop through */
1635         case BWRITERSPR_INPUT:
1636         case BWRITERSPR_TEMP:
1637         case BWRITERSPR_CONST:
1638         case BWRITERSPR_ADDR:
1639         case BWRITERSPR_CONSTINT:
1640         case BWRITERSPR_CONSTBOOL:
1641         case BWRITERSPR_LABEL:
1642             d3d9reg = d3d9_register(reg->type);
1643             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1644             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1645             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1646             break;
1647
1648         case BWRITERSPR_LOOP:
1649             if(reg->regnum != 0) {
1650                 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1651                 This->state = E_INVALIDARG;
1652                 return;
1653             }
1654             token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1655             token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1656             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1657             break;
1658
1659         case BWRITERSPR_PREDICATE:
1660             if(This->version != BWRITERVS_VERSION(2, 1)){
1661                 WARN("Predicate register is allowed only in vs_2_x\n");
1662                 This->state = E_INVALIDARG;
1663                 return;
1664             }
1665             if(reg->regnum > 0) {
1666                 WARN("Only predicate register 0 is supported\n");
1667                 This->state = E_INVALIDARG;
1668                 return;
1669             }
1670             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1671             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1672             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1673
1674             break;
1675
1676         default:
1677             WARN("Invalid register type for 2.0 vshader\n");
1678             This->state = E_INVALIDARG;
1679             return;
1680     }
1681
1682     token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1683
1684     token |= d3d9_srcmod(reg->srcmod);
1685
1686     if(reg->rel_reg)
1687         token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1688
1689     put_dword(buffer, token);
1690
1691     /* vs_2_0 and newer write the register containing the index explicitly in the
1692      * binary code
1693      */
1694     if(token & D3DVS_ADDRMODE_RELATIVE)
1695         vs_2_srcreg(This, reg->rel_reg, buffer);
1696 }
1697
1698 static void sm_2_opcode(struct bc_writer *This,
1699                         const struct instruction *instr,
1700                         DWORD token, struct bytecode_buffer *buffer) {
1701     /* From sm 2 onwards instruction length is encoded in the opcode field */
1702     int dsts = instr->has_dst ? 1 : 0;
1703     token |= instrlen(instr, instr->num_srcs, dsts) << D3DSI_INSTLENGTH_SHIFT;
1704     if(instr->comptype)
1705         token |= (d3d9_comparetype(instr->comptype) << 16) & (0xf << 16);
1706     if(instr->has_predicate)
1707         token |= D3DSHADER_INSTRUCTION_PREDICATED;
1708     put_dword(buffer,token);
1709 }
1710
1711 static const struct instr_handler_table vs_2_0_handlers[] = {
1712     {BWRITERSIO_ADD,            instr_handler},
1713     {BWRITERSIO_NOP,            instr_handler},
1714     {BWRITERSIO_MOV,            instr_handler},
1715     {BWRITERSIO_SUB,            instr_handler},
1716     {BWRITERSIO_MAD,            instr_handler},
1717     {BWRITERSIO_MUL,            instr_handler},
1718     {BWRITERSIO_RCP,            instr_handler},
1719     {BWRITERSIO_RSQ,            instr_handler},
1720     {BWRITERSIO_DP3,            instr_handler},
1721     {BWRITERSIO_DP4,            instr_handler},
1722     {BWRITERSIO_MIN,            instr_handler},
1723     {BWRITERSIO_MAX,            instr_handler},
1724     {BWRITERSIO_SLT,            instr_handler},
1725     {BWRITERSIO_SGE,            instr_handler},
1726     {BWRITERSIO_ABS,            instr_handler},
1727     {BWRITERSIO_EXP,            instr_handler},
1728     {BWRITERSIO_LOG,            instr_handler},
1729     {BWRITERSIO_EXPP,           instr_handler},
1730     {BWRITERSIO_LOGP,           instr_handler},
1731     {BWRITERSIO_DST,            instr_handler},
1732     {BWRITERSIO_LRP,            instr_handler},
1733     {BWRITERSIO_FRC,            instr_handler},
1734     {BWRITERSIO_CRS,            instr_handler},
1735     {BWRITERSIO_SGN,            instr_handler},
1736     {BWRITERSIO_NRM,            instr_handler},
1737     {BWRITERSIO_SINCOS,         instr_handler},
1738     {BWRITERSIO_M4x4,           instr_handler},
1739     {BWRITERSIO_M4x3,           instr_handler},
1740     {BWRITERSIO_M3x4,           instr_handler},
1741     {BWRITERSIO_M3x3,           instr_handler},
1742     {BWRITERSIO_M3x2,           instr_handler},
1743     {BWRITERSIO_LIT,            instr_handler},
1744     {BWRITERSIO_POW,            instr_handler},
1745     {BWRITERSIO_MOVA,           instr_handler},
1746
1747     {BWRITERSIO_CALL,           instr_handler},
1748     {BWRITERSIO_CALLNZ,         instr_handler},
1749     {BWRITERSIO_REP,            instr_handler},
1750     {BWRITERSIO_ENDREP,         instr_handler},
1751     {BWRITERSIO_IF,             instr_handler},
1752     {BWRITERSIO_LABEL,          instr_handler},
1753     {BWRITERSIO_ELSE,           instr_handler},
1754     {BWRITERSIO_ENDIF,          instr_handler},
1755     {BWRITERSIO_LOOP,           instr_handler},
1756     {BWRITERSIO_RET,            instr_handler},
1757     {BWRITERSIO_ENDLOOP,        instr_handler},
1758
1759     {BWRITERSIO_END,            NULL},
1760 };
1761
1762 static const struct bytecode_backend vs_2_0_backend = {
1763     vs_2_header,
1764     end,
1765     vs_2_srcreg,
1766     vs_12_dstreg,
1767     sm_2_opcode,
1768     vs_2_0_handlers
1769 };
1770
1771 static const struct instr_handler_table vs_2_x_handlers[] = {
1772     {BWRITERSIO_ADD,            instr_handler},
1773     {BWRITERSIO_NOP,            instr_handler},
1774     {BWRITERSIO_MOV,            instr_handler},
1775     {BWRITERSIO_SUB,            instr_handler},
1776     {BWRITERSIO_MAD,            instr_handler},
1777     {BWRITERSIO_MUL,            instr_handler},
1778     {BWRITERSIO_RCP,            instr_handler},
1779     {BWRITERSIO_RSQ,            instr_handler},
1780     {BWRITERSIO_DP3,            instr_handler},
1781     {BWRITERSIO_DP4,            instr_handler},
1782     {BWRITERSIO_MIN,            instr_handler},
1783     {BWRITERSIO_MAX,            instr_handler},
1784     {BWRITERSIO_SLT,            instr_handler},
1785     {BWRITERSIO_SGE,            instr_handler},
1786     {BWRITERSIO_ABS,            instr_handler},
1787     {BWRITERSIO_EXP,            instr_handler},
1788     {BWRITERSIO_LOG,            instr_handler},
1789     {BWRITERSIO_EXPP,           instr_handler},
1790     {BWRITERSIO_LOGP,           instr_handler},
1791     {BWRITERSIO_DST,            instr_handler},
1792     {BWRITERSIO_LRP,            instr_handler},
1793     {BWRITERSIO_FRC,            instr_handler},
1794     {BWRITERSIO_CRS,            instr_handler},
1795     {BWRITERSIO_SGN,            instr_handler},
1796     {BWRITERSIO_NRM,            instr_handler},
1797     {BWRITERSIO_SINCOS,         instr_handler},
1798     {BWRITERSIO_M4x4,           instr_handler},
1799     {BWRITERSIO_M4x3,           instr_handler},
1800     {BWRITERSIO_M3x4,           instr_handler},
1801     {BWRITERSIO_M3x3,           instr_handler},
1802     {BWRITERSIO_M3x2,           instr_handler},
1803     {BWRITERSIO_LIT,            instr_handler},
1804     {BWRITERSIO_POW,            instr_handler},
1805     {BWRITERSIO_MOVA,           instr_handler},
1806
1807     {BWRITERSIO_CALL,           instr_handler},
1808     {BWRITERSIO_CALLNZ,         instr_handler},
1809     {BWRITERSIO_REP,            instr_handler},
1810     {BWRITERSIO_ENDREP,         instr_handler},
1811     {BWRITERSIO_IF,             instr_handler},
1812     {BWRITERSIO_LABEL,          instr_handler},
1813     {BWRITERSIO_IFC,            instr_handler},
1814     {BWRITERSIO_ELSE,           instr_handler},
1815     {BWRITERSIO_ENDIF,          instr_handler},
1816     {BWRITERSIO_BREAK,          instr_handler},
1817     {BWRITERSIO_BREAKC,         instr_handler},
1818     {BWRITERSIO_LOOP,           instr_handler},
1819     {BWRITERSIO_RET,            instr_handler},
1820     {BWRITERSIO_ENDLOOP,        instr_handler},
1821
1822     {BWRITERSIO_SETP,           instr_handler},
1823     {BWRITERSIO_BREAKP,         instr_handler},
1824
1825     {BWRITERSIO_END,            NULL},
1826 };
1827
1828 static const struct bytecode_backend vs_2_x_backend = {
1829     vs_2_header,
1830     end,
1831     vs_2_srcreg,
1832     vs_12_dstreg,
1833     sm_2_opcode,
1834     vs_2_x_handlers
1835 };
1836
1837 static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1838     DWORD i;
1839     DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT);
1840     DWORD token;
1841     const DWORD reg = (1<<31) |
1842         ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
1843         ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
1844         D3DSP_WRITEMASK_ALL;
1845
1846     for(i = 0; i < shader->num_samplers; i++) {
1847         /* Write the DCL instruction */
1848         put_dword(buffer, instr_dcl);
1849         token = (1<<31);
1850         /* Already shifted */
1851         token |= (d3d9_sampler(shader->samplers[i].type)) & D3DSP_TEXTURETYPE_MASK;
1852         put_dword(buffer, token);
1853         token = reg | (shader->samplers[i].regnum & D3DSP_REGNUM_MASK);
1854         token |= d3d9_dstmod(shader->samplers[i].mod);
1855         put_dword(buffer, token);
1856     }
1857 }
1858
1859 static void ps_2_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1860     HRESULT hr = find_ps_builtin_semantics(This, shader, 8);
1861     if(FAILED(hr)) {
1862         This->state = hr;
1863         return;
1864     }
1865
1866     write_declarations(This, buffer, TRUE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
1867     write_samplers(shader, buffer);
1868     write_constF(shader, buffer, TRUE);
1869     write_constB(shader, buffer, TRUE);
1870     write_constI(shader, buffer, TRUE);
1871 }
1872
1873 static void ps_2_srcreg(struct bc_writer *This,
1874                         const struct shader_reg *reg,
1875                         struct bytecode_buffer *buffer) {
1876     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1877     DWORD d3d9reg;
1878     if(reg->rel_reg) {
1879         WARN("Relative addressing not supported in <= ps_3_0\n");
1880         This->state = E_INVALIDARG;
1881         return;
1882     }
1883
1884     switch(reg->type) {
1885         case BWRITERSPR_INPUT:
1886             token |= map_ps_input(This, reg);
1887             break;
1888
1889             /* Can be mapped 1:1 */
1890         case BWRITERSPR_TEMP:
1891         case BWRITERSPR_CONST:
1892         case BWRITERSPR_COLOROUT:
1893         case BWRITERSPR_CONSTBOOL:
1894         case BWRITERSPR_CONSTINT:
1895         case BWRITERSPR_SAMPLER:
1896         case BWRITERSPR_LABEL:
1897         case BWRITERSPR_DEPTHOUT:
1898             d3d9reg = d3d9_register(reg->type);
1899             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1900             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1901             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1902             break;
1903
1904         case BWRITERSPR_PREDICATE:
1905             if(This->version != BWRITERPS_VERSION(2, 1)){
1906                 WARN("Predicate register not supported in ps_2_0\n");
1907                 This->state = E_INVALIDARG;
1908             }
1909             if(reg->regnum) {
1910                 WARN("Predicate register with regnum %u not supported\n",
1911                      reg->regnum);
1912                 This->state = E_INVALIDARG;
1913             }
1914             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1915             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1916             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1917             break;
1918
1919         default:
1920             WARN("Invalid register type for ps_2_0 shader\n");
1921             This->state = E_INVALIDARG;
1922             return;
1923     }
1924
1925     token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1926
1927     token |= d3d9_srcmod(reg->srcmod);
1928     put_dword(buffer, token);
1929 }
1930
1931 static void ps_2_0_dstreg(struct bc_writer *This,
1932                           const struct shader_reg *reg,
1933                           struct bytecode_buffer *buffer,
1934                           DWORD shift, DWORD mod) {
1935     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1936     DWORD d3d9reg;
1937
1938     if(reg->rel_reg) {
1939         WARN("Relative addressing not supported for destination registers\n");
1940         This->state = E_INVALIDARG;
1941         return;
1942     }
1943
1944     switch(reg->type) {
1945         case BWRITERSPR_TEMP: /* 1:1 mapping */
1946         case BWRITERSPR_COLOROUT:
1947         case BWRITERSPR_DEPTHOUT:
1948             d3d9reg = d3d9_register(reg->type);
1949             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1950             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1951             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1952             break;
1953
1954         case BWRITERSPR_PREDICATE:
1955             if(This->version != BWRITERPS_VERSION(2, 1)){
1956                 WARN("Predicate register not supported in ps_2_0\n");
1957                 This->state = E_INVALIDARG;
1958             }
1959             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1960             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1961             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1962             break;
1963
1964         /* texkill uses the input register as a destination parameter */
1965         case BWRITERSPR_INPUT:
1966             token |= map_ps_input(This, reg);
1967             break;
1968
1969         default:
1970             WARN("Invalid dest register type for 2.x pshader\n");
1971             This->state = E_INVALIDARG;
1972             return;
1973     }
1974
1975     token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1976     token |= d3d9_dstmod(mod);
1977
1978     token |= d3d9_writemask(reg->u.writemask);
1979     put_dword(buffer, token);
1980 }
1981
1982 static const struct instr_handler_table ps_2_0_handlers[] = {
1983     {BWRITERSIO_ADD,            instr_handler},
1984     {BWRITERSIO_NOP,            instr_handler},
1985     {BWRITERSIO_MOV,            instr_handler},
1986     {BWRITERSIO_SUB,            instr_handler},
1987     {BWRITERSIO_MAD,            instr_handler},
1988     {BWRITERSIO_MUL,            instr_handler},
1989     {BWRITERSIO_RCP,            instr_handler},
1990     {BWRITERSIO_RSQ,            instr_handler},
1991     {BWRITERSIO_DP3,            instr_handler},
1992     {BWRITERSIO_DP4,            instr_handler},
1993     {BWRITERSIO_MIN,            instr_handler},
1994     {BWRITERSIO_MAX,            instr_handler},
1995     {BWRITERSIO_ABS,            instr_handler},
1996     {BWRITERSIO_EXP,            instr_handler},
1997     {BWRITERSIO_LOG,            instr_handler},
1998     {BWRITERSIO_EXPP,           instr_handler},
1999     {BWRITERSIO_LOGP,           instr_handler},
2000     {BWRITERSIO_LRP,            instr_handler},
2001     {BWRITERSIO_FRC,            instr_handler},
2002     {BWRITERSIO_CRS,            instr_handler},
2003     {BWRITERSIO_NRM,            instr_handler},
2004     {BWRITERSIO_SINCOS,         instr_handler},
2005     {BWRITERSIO_M4x4,           instr_handler},
2006     {BWRITERSIO_M4x3,           instr_handler},
2007     {BWRITERSIO_M3x4,           instr_handler},
2008     {BWRITERSIO_M3x3,           instr_handler},
2009     {BWRITERSIO_M3x2,           instr_handler},
2010     {BWRITERSIO_POW,            instr_handler},
2011     {BWRITERSIO_DP2ADD,         instr_handler},
2012     {BWRITERSIO_CMP,            instr_handler},
2013
2014     {BWRITERSIO_TEX,            instr_handler},
2015     {BWRITERSIO_TEXLDP,         instr_handler},
2016     {BWRITERSIO_TEXLDB,         instr_handler},
2017     {BWRITERSIO_TEXKILL,        instr_handler},
2018
2019     {BWRITERSIO_END,            NULL},
2020 };
2021
2022 static const struct bytecode_backend ps_2_0_backend = {
2023     ps_2_header,
2024     end,
2025     ps_2_srcreg,
2026     ps_2_0_dstreg,
2027     sm_2_opcode,
2028     ps_2_0_handlers
2029 };
2030
2031 static const struct instr_handler_table ps_2_x_handlers[] = {
2032     {BWRITERSIO_ADD,            instr_handler},
2033     {BWRITERSIO_NOP,            instr_handler},
2034     {BWRITERSIO_MOV,            instr_handler},
2035     {BWRITERSIO_SUB,            instr_handler},
2036     {BWRITERSIO_MAD,            instr_handler},
2037     {BWRITERSIO_MUL,            instr_handler},
2038     {BWRITERSIO_RCP,            instr_handler},
2039     {BWRITERSIO_RSQ,            instr_handler},
2040     {BWRITERSIO_DP3,            instr_handler},
2041     {BWRITERSIO_DP4,            instr_handler},
2042     {BWRITERSIO_MIN,            instr_handler},
2043     {BWRITERSIO_MAX,            instr_handler},
2044     {BWRITERSIO_ABS,            instr_handler},
2045     {BWRITERSIO_EXP,            instr_handler},
2046     {BWRITERSIO_LOG,            instr_handler},
2047     {BWRITERSIO_EXPP,           instr_handler},
2048     {BWRITERSIO_LOGP,           instr_handler},
2049     {BWRITERSIO_LRP,            instr_handler},
2050     {BWRITERSIO_FRC,            instr_handler},
2051     {BWRITERSIO_CRS,            instr_handler},
2052     {BWRITERSIO_NRM,            instr_handler},
2053     {BWRITERSIO_SINCOS,         instr_handler},
2054     {BWRITERSIO_M4x4,           instr_handler},
2055     {BWRITERSIO_M4x3,           instr_handler},
2056     {BWRITERSIO_M3x4,           instr_handler},
2057     {BWRITERSIO_M3x3,           instr_handler},
2058     {BWRITERSIO_M3x2,           instr_handler},
2059     {BWRITERSIO_POW,            instr_handler},
2060     {BWRITERSIO_DP2ADD,         instr_handler},
2061     {BWRITERSIO_CMP,            instr_handler},
2062
2063     {BWRITERSIO_CALL,           instr_handler},
2064     {BWRITERSIO_CALLNZ,         instr_handler},
2065     {BWRITERSIO_REP,            instr_handler},
2066     {BWRITERSIO_ENDREP,         instr_handler},
2067     {BWRITERSIO_IF,             instr_handler},
2068     {BWRITERSIO_LABEL,          instr_handler},
2069     {BWRITERSIO_IFC,            instr_handler},
2070     {BWRITERSIO_ELSE,           instr_handler},
2071     {BWRITERSIO_ENDIF,          instr_handler},
2072     {BWRITERSIO_BREAK,          instr_handler},
2073     {BWRITERSIO_BREAKC,         instr_handler},
2074     {BWRITERSIO_RET,            instr_handler},
2075
2076     {BWRITERSIO_TEX,            instr_handler},
2077     {BWRITERSIO_TEXLDP,         instr_handler},
2078     {BWRITERSIO_TEXLDB,         instr_handler},
2079     {BWRITERSIO_TEXKILL,        instr_handler},
2080     {BWRITERSIO_DSX,            instr_handler},
2081     {BWRITERSIO_DSY,            instr_handler},
2082
2083     {BWRITERSIO_SETP,           instr_handler},
2084     {BWRITERSIO_BREAKP,         instr_handler},
2085
2086     {BWRITERSIO_TEXLDD,         instr_handler},
2087
2088     {BWRITERSIO_END,            NULL},
2089 };
2090
2091 static const struct bytecode_backend ps_2_x_backend = {
2092     ps_2_header,
2093     end,
2094     ps_2_srcreg,
2095     ps_2_0_dstreg,
2096     sm_2_opcode,
2097     ps_2_x_handlers
2098 };
2099
2100 static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
2101     write_declarations(This, buffer, TRUE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
2102     write_declarations(This, buffer, TRUE, shader->outputs, shader->num_outputs, BWRITERSPR_OUTPUT);
2103     write_constF(shader, buffer, TRUE);
2104     write_constB(shader, buffer, TRUE);
2105     write_constI(shader, buffer, TRUE);
2106     write_samplers(shader, buffer);
2107 }
2108
2109 static void sm_3_srcreg(struct bc_writer *This,
2110                         const struct shader_reg *reg,
2111                         struct bytecode_buffer *buffer) {
2112     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
2113     DWORD d3d9reg;
2114
2115     d3d9reg = d3d9_register(reg->type);
2116     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
2117     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
2118     token |= reg->regnum & D3DSP_REGNUM_MASK;
2119
2120     token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK;
2121     token |= d3d9_srcmod(reg->srcmod);
2122
2123     if(reg->rel_reg) {
2124         if(reg->type == BWRITERSPR_CONST && This->version == BWRITERPS_VERSION(3, 0)) {
2125             WARN("c%u[...] is unsupported in ps_3_0\n", reg->regnum);
2126             This->state = E_INVALIDARG;
2127             return;
2128         }
2129         if(((reg->rel_reg->type == BWRITERSPR_ADDR && This->version == BWRITERVS_VERSION(3, 0)) ||
2130            reg->rel_reg->type == BWRITERSPR_LOOP) &&
2131            reg->rel_reg->regnum == 0) {
2132             token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
2133         } else {
2134             WARN("Unsupported relative addressing register\n");
2135             This->state = E_INVALIDARG;
2136             return;
2137         }
2138     }
2139
2140     put_dword(buffer, token);
2141
2142     /* vs_2_0 and newer write the register containing the index explicitly in the
2143      * binary code
2144      */
2145     if(token & D3DVS_ADDRMODE_RELATIVE) {
2146         sm_3_srcreg(This, reg->rel_reg, buffer);
2147     }
2148 }
2149
2150 static void sm_3_dstreg(struct bc_writer *This,
2151                         const struct shader_reg *reg,
2152                         struct bytecode_buffer *buffer,
2153                         DWORD shift, DWORD mod) {
2154     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
2155     DWORD d3d9reg;
2156
2157     if(reg->rel_reg) {
2158         if(This->version == BWRITERVS_VERSION(3, 0) &&
2159            reg->type == BWRITERSPR_OUTPUT) {
2160             token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
2161         } else {
2162             WARN("Relative addressing not supported for this shader type or register type\n");
2163             This->state = E_INVALIDARG;
2164             return;
2165         }
2166     }
2167
2168     d3d9reg = d3d9_register(reg->type);
2169     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
2170     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
2171     token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
2172
2173     token |= d3d9_dstmod(mod);
2174
2175     token |= d3d9_writemask(reg->u.writemask);
2176     put_dword(buffer, token);
2177
2178     /* vs_2_0 and newer write the register containing the index explicitly in the
2179      * binary code
2180      */
2181     if(token & D3DVS_ADDRMODE_RELATIVE) {
2182         sm_3_srcreg(This, reg->rel_reg, buffer);
2183     }
2184 }
2185
2186 static const struct instr_handler_table vs_3_handlers[] = {
2187     {BWRITERSIO_ADD,            instr_handler},
2188     {BWRITERSIO_NOP,            instr_handler},
2189     {BWRITERSIO_MOV,            instr_handler},
2190     {BWRITERSIO_SUB,            instr_handler},
2191     {BWRITERSIO_MAD,            instr_handler},
2192     {BWRITERSIO_MUL,            instr_handler},
2193     {BWRITERSIO_RCP,            instr_handler},
2194     {BWRITERSIO_RSQ,            instr_handler},
2195     {BWRITERSIO_DP3,            instr_handler},
2196     {BWRITERSIO_DP4,            instr_handler},
2197     {BWRITERSIO_MIN,            instr_handler},
2198     {BWRITERSIO_MAX,            instr_handler},
2199     {BWRITERSIO_SLT,            instr_handler},
2200     {BWRITERSIO_SGE,            instr_handler},
2201     {BWRITERSIO_ABS,            instr_handler},
2202     {BWRITERSIO_EXP,            instr_handler},
2203     {BWRITERSIO_LOG,            instr_handler},
2204     {BWRITERSIO_EXPP,           instr_handler},
2205     {BWRITERSIO_LOGP,           instr_handler},
2206     {BWRITERSIO_DST,            instr_handler},
2207     {BWRITERSIO_LRP,            instr_handler},
2208     {BWRITERSIO_FRC,            instr_handler},
2209     {BWRITERSIO_CRS,            instr_handler},
2210     {BWRITERSIO_SGN,            instr_handler},
2211     {BWRITERSIO_NRM,            instr_handler},
2212     {BWRITERSIO_SINCOS,         instr_handler},
2213     {BWRITERSIO_M4x4,           instr_handler},
2214     {BWRITERSIO_M4x3,           instr_handler},
2215     {BWRITERSIO_M3x4,           instr_handler},
2216     {BWRITERSIO_M3x3,           instr_handler},
2217     {BWRITERSIO_M3x2,           instr_handler},
2218     {BWRITERSIO_LIT,            instr_handler},
2219     {BWRITERSIO_POW,            instr_handler},
2220     {BWRITERSIO_MOVA,           instr_handler},
2221
2222     {BWRITERSIO_CALL,           instr_handler},
2223     {BWRITERSIO_CALLNZ,         instr_handler},
2224     {BWRITERSIO_REP,            instr_handler},
2225     {BWRITERSIO_ENDREP,         instr_handler},
2226     {BWRITERSIO_IF,             instr_handler},
2227     {BWRITERSIO_LABEL,          instr_handler},
2228     {BWRITERSIO_IFC,            instr_handler},
2229     {BWRITERSIO_ELSE,           instr_handler},
2230     {BWRITERSIO_ENDIF,          instr_handler},
2231     {BWRITERSIO_BREAK,          instr_handler},
2232     {BWRITERSIO_BREAKC,         instr_handler},
2233     {BWRITERSIO_LOOP,           instr_handler},
2234     {BWRITERSIO_RET,            instr_handler},
2235     {BWRITERSIO_ENDLOOP,        instr_handler},
2236
2237     {BWRITERSIO_SETP,           instr_handler},
2238     {BWRITERSIO_BREAKP,         instr_handler},
2239     {BWRITERSIO_TEXLDL,         instr_handler},
2240
2241     {BWRITERSIO_END,            NULL},
2242 };
2243
2244 static const struct bytecode_backend vs_3_backend = {
2245     sm_3_header,
2246     end,
2247     sm_3_srcreg,
2248     sm_3_dstreg,
2249     sm_2_opcode,
2250     vs_3_handlers
2251 };
2252
2253 static const struct instr_handler_table ps_3_handlers[] = {
2254     {BWRITERSIO_ADD,            instr_handler},
2255     {BWRITERSIO_NOP,            instr_handler},
2256     {BWRITERSIO_MOV,            instr_handler},
2257     {BWRITERSIO_SUB,            instr_handler},
2258     {BWRITERSIO_MAD,            instr_handler},
2259     {BWRITERSIO_MUL,            instr_handler},
2260     {BWRITERSIO_RCP,            instr_handler},
2261     {BWRITERSIO_RSQ,            instr_handler},
2262     {BWRITERSIO_DP3,            instr_handler},
2263     {BWRITERSIO_DP4,            instr_handler},
2264     {BWRITERSIO_MIN,            instr_handler},
2265     {BWRITERSIO_MAX,            instr_handler},
2266     {BWRITERSIO_ABS,            instr_handler},
2267     {BWRITERSIO_EXP,            instr_handler},
2268     {BWRITERSIO_LOG,            instr_handler},
2269     {BWRITERSIO_EXPP,           instr_handler},
2270     {BWRITERSIO_LOGP,           instr_handler},
2271     {BWRITERSIO_LRP,            instr_handler},
2272     {BWRITERSIO_FRC,            instr_handler},
2273     {BWRITERSIO_CRS,            instr_handler},
2274     {BWRITERSIO_NRM,            instr_handler},
2275     {BWRITERSIO_SINCOS,         instr_handler},
2276     {BWRITERSIO_M4x4,           instr_handler},
2277     {BWRITERSIO_M4x3,           instr_handler},
2278     {BWRITERSIO_M3x4,           instr_handler},
2279     {BWRITERSIO_M3x3,           instr_handler},
2280     {BWRITERSIO_M3x2,           instr_handler},
2281     {BWRITERSIO_POW,            instr_handler},
2282     {BWRITERSIO_DP2ADD,         instr_handler},
2283     {BWRITERSIO_CMP,            instr_handler},
2284
2285     {BWRITERSIO_CALL,           instr_handler},
2286     {BWRITERSIO_CALLNZ,         instr_handler},
2287     {BWRITERSIO_REP,            instr_handler},
2288     {BWRITERSIO_ENDREP,         instr_handler},
2289     {BWRITERSIO_IF,             instr_handler},
2290     {BWRITERSIO_LABEL,          instr_handler},
2291     {BWRITERSIO_IFC,            instr_handler},
2292     {BWRITERSIO_ELSE,           instr_handler},
2293     {BWRITERSIO_ENDIF,          instr_handler},
2294     {BWRITERSIO_BREAK,          instr_handler},
2295     {BWRITERSIO_BREAKC,         instr_handler},
2296     {BWRITERSIO_LOOP,           instr_handler},
2297     {BWRITERSIO_RET,            instr_handler},
2298     {BWRITERSIO_ENDLOOP,        instr_handler},
2299
2300     {BWRITERSIO_SETP,           instr_handler},
2301     {BWRITERSIO_BREAKP,         instr_handler},
2302     {BWRITERSIO_TEXLDL,         instr_handler},
2303
2304     {BWRITERSIO_TEX,            instr_handler},
2305     {BWRITERSIO_TEXLDP,         instr_handler},
2306     {BWRITERSIO_TEXLDB,         instr_handler},
2307     {BWRITERSIO_TEXKILL,        instr_handler},
2308     {BWRITERSIO_DSX,            instr_handler},
2309     {BWRITERSIO_DSY,            instr_handler},
2310     {BWRITERSIO_TEXLDD,         instr_handler},
2311
2312     {BWRITERSIO_END,            NULL},
2313 };
2314
2315 static const struct bytecode_backend ps_3_backend = {
2316     sm_3_header,
2317     end,
2318     sm_3_srcreg,
2319     sm_3_dstreg,
2320     sm_2_opcode,
2321     ps_3_handlers
2322 };
2323
2324 static void init_vs10_dx9_writer(struct bc_writer *writer) {
2325     TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
2326     writer->funcs = &vs_1_x_backend;
2327 }
2328
2329 static void init_vs11_dx9_writer(struct bc_writer *writer) {
2330     TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
2331     writer->funcs = &vs_1_x_backend;
2332 }
2333
2334 static void init_vs20_dx9_writer(struct bc_writer *writer) {
2335     TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
2336     writer->funcs = &vs_2_0_backend;
2337 }
2338
2339 static void init_vs2x_dx9_writer(struct bc_writer *writer) {
2340     TRACE("Creating DirectX9 vertex shader 2.x writer\n");
2341     writer->funcs = &vs_2_x_backend;
2342 }
2343
2344 static void init_vs30_dx9_writer(struct bc_writer *writer) {
2345     TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
2346     writer->funcs = &vs_3_backend;
2347 }
2348
2349 static void init_ps10_dx9_writer(struct bc_writer *writer) {
2350     TRACE("Creating DirectX9 pixel shader 1.0 writer\n");
2351     writer->funcs = &ps_1_0123_backend;
2352 }
2353
2354 static void init_ps11_dx9_writer(struct bc_writer *writer) {
2355     TRACE("Creating DirectX9 pixel shader 1.1 writer\n");
2356     writer->funcs = &ps_1_0123_backend;
2357 }
2358
2359 static void init_ps12_dx9_writer(struct bc_writer *writer) {
2360     TRACE("Creating DirectX9 pixel shader 1.2 writer\n");
2361     writer->funcs = &ps_1_0123_backend;
2362 }
2363
2364 static void init_ps13_dx9_writer(struct bc_writer *writer) {
2365     TRACE("Creating DirectX9 pixel shader 1.3 writer\n");
2366     writer->funcs = &ps_1_0123_backend;
2367 }
2368
2369 static void init_ps14_dx9_writer(struct bc_writer *writer) {
2370     TRACE("Creating DirectX9 pixel shader 1.4 writer\n");
2371     writer->funcs = &ps_1_4_backend;
2372 }
2373
2374 static void init_ps20_dx9_writer(struct bc_writer *writer) {
2375     TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
2376     writer->funcs = &ps_2_0_backend;
2377 }
2378
2379 static void init_ps2x_dx9_writer(struct bc_writer *writer) {
2380     TRACE("Creating DirectX9 pixel shader 2.x writer\n");
2381     writer->funcs = &ps_2_x_backend;
2382 }
2383
2384 static void init_ps30_dx9_writer(struct bc_writer *writer) {
2385     TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
2386     writer->funcs = &ps_3_backend;
2387 }
2388
2389 static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
2390     struct bc_writer *ret = d3dcompiler_alloc(sizeof(*ret));
2391
2392     if(!ret) {
2393         WARN("Failed to allocate a bytecode writer instance\n");
2394         return NULL;
2395     }
2396
2397     switch(version) {
2398         case BWRITERVS_VERSION(1, 0):
2399             if(dxversion != 9) {
2400                 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
2401                 goto fail;
2402             }
2403             init_vs10_dx9_writer(ret);
2404             break;
2405         case BWRITERVS_VERSION(1, 1):
2406             if(dxversion != 9) {
2407                 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
2408                 goto fail;
2409             }
2410             init_vs11_dx9_writer(ret);
2411             break;
2412         case BWRITERVS_VERSION(2, 0):
2413             if(dxversion != 9) {
2414                 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion);
2415                 goto fail;
2416             }
2417             init_vs20_dx9_writer(ret);
2418             break;
2419         case BWRITERVS_VERSION(2, 1):
2420             if(dxversion != 9) {
2421                 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion);
2422                 goto fail;
2423             }
2424             init_vs2x_dx9_writer(ret);
2425             break;
2426         case BWRITERVS_VERSION(3, 0):
2427             if(dxversion != 9) {
2428                 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion);
2429                 goto fail;
2430             }
2431             init_vs30_dx9_writer(ret);
2432             break;
2433
2434         case BWRITERPS_VERSION(1, 0):
2435             if(dxversion != 9) {
2436                 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion);
2437                 goto fail;
2438             }
2439             init_ps10_dx9_writer(ret);
2440             break;
2441         case BWRITERPS_VERSION(1, 1):
2442             if(dxversion != 9) {
2443                 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion);
2444                 goto fail;
2445             }
2446             init_ps11_dx9_writer(ret);
2447             break;
2448         case BWRITERPS_VERSION(1, 2):
2449             if(dxversion != 9) {
2450                 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion);
2451                 goto fail;
2452             }
2453             init_ps12_dx9_writer(ret);
2454             break;
2455         case BWRITERPS_VERSION(1, 3):
2456             if(dxversion != 9) {
2457                 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion);
2458                 goto fail;
2459             }
2460             init_ps13_dx9_writer(ret);
2461             break;
2462         case BWRITERPS_VERSION(1, 4):
2463             if(dxversion != 9) {
2464                 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion);
2465                 goto fail;
2466             }
2467             init_ps14_dx9_writer(ret);
2468             break;
2469
2470         case BWRITERPS_VERSION(2, 0):
2471             if(dxversion != 9) {
2472                 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion);
2473                 goto fail;
2474             }
2475             init_ps20_dx9_writer(ret);
2476             break;
2477
2478         case BWRITERPS_VERSION(2, 1):
2479             if(dxversion != 9) {
2480                 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion);
2481                 goto fail;
2482             }
2483             init_ps2x_dx9_writer(ret);
2484             break;
2485
2486         case BWRITERPS_VERSION(3, 0):
2487             if(dxversion != 9) {
2488                 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion);
2489                 goto fail;
2490             }
2491             init_ps30_dx9_writer(ret);
2492             break;
2493
2494         default:
2495             WARN("Unexpected shader version requested: %08x\n", version);
2496             goto fail;
2497     }
2498     ret->version = version;
2499     return ret;
2500
2501 fail:
2502     d3dcompiler_free(ret);
2503     return NULL;
2504 }
2505
2506 static HRESULT call_instr_handler(struct bc_writer *writer,
2507                                   const struct instruction *instr,
2508                                   struct bytecode_buffer *buffer) {
2509     DWORD i=0;
2510
2511     while(writer->funcs->instructions[i].opcode != BWRITERSIO_END) {
2512         if(instr->opcode == writer->funcs->instructions[i].opcode) {
2513             if(!writer->funcs->instructions[i].func) {
2514                 WARN("Opcode %u not supported by this profile\n", instr->opcode);
2515                 return E_INVALIDARG;
2516             }
2517             writer->funcs->instructions[i].func(writer, instr, buffer);
2518             return S_OK;
2519         }
2520         i++;
2521     }
2522
2523     FIXME("Unhandled instruction %u - %s\n", instr->opcode,
2524           debug_print_opcode(instr->opcode));
2525     return E_INVALIDARG;
2526 }
2527
2528 HRESULT SlWriteBytecode(const struct bwriter_shader *shader, int dxversion, DWORD **result, DWORD *size)
2529 {
2530     struct bc_writer *writer;
2531     struct bytecode_buffer *buffer = NULL;
2532     HRESULT hr;
2533     unsigned int i;
2534
2535     if(!shader){
2536         ERR("NULL shader structure, aborting\n");
2537         return E_FAIL;
2538     }
2539     writer = create_writer(shader->version, dxversion);
2540     *result = NULL;
2541
2542     if(!writer) {
2543         WARN("Could not create a bytecode writer instance. Either unsupported version\n");
2544         WARN("or out of memory\n");
2545         hr = E_FAIL;
2546         goto error;
2547     }
2548
2549     buffer = allocate_buffer();
2550     if(!buffer) {
2551         WARN("Failed to allocate a buffer for the shader bytecode\n");
2552         hr = E_FAIL;
2553         goto error;
2554     }
2555
2556     /* Write shader type and version */
2557     put_dword(buffer, shader->version);
2558
2559     writer->funcs->header(writer, shader, buffer);
2560     if(FAILED(writer->state)) {
2561         hr = writer->state;
2562         goto error;
2563     }
2564
2565     for(i = 0; i < shader->num_instrs; i++) {
2566         hr = call_instr_handler(writer, shader->instr[i], buffer);
2567         if(FAILED(hr)) {
2568             goto error;
2569         }
2570     }
2571
2572     if(FAILED(writer->state)) {
2573         hr = writer->state;
2574         goto error;
2575     }
2576
2577     writer->funcs->end(writer, shader, buffer);
2578
2579     if(FAILED(buffer->state)) {
2580         hr = buffer->state;
2581         goto error;
2582     }
2583
2584     *size = buffer->size * sizeof(DWORD);
2585     *result = buffer->data;
2586     buffer->data = NULL;
2587     hr = S_OK;
2588
2589 error:
2590     if(buffer) {
2591         d3dcompiler_free(buffer->data);
2592         d3dcompiler_free(buffer);
2593     }
2594     d3dcompiler_free(writer);
2595     return hr;
2596 }
2597
2598 void SlDeleteShader(struct bwriter_shader *shader) {
2599     unsigned int i, j;
2600
2601     TRACE("Deleting shader %p\n", shader);
2602
2603     for(i = 0; i < shader->num_cf; i++) {
2604         d3dcompiler_free(shader->constF[i]);
2605     }
2606     d3dcompiler_free(shader->constF);
2607     for(i = 0; i < shader->num_ci; i++) {
2608         d3dcompiler_free(shader->constI[i]);
2609     }
2610     d3dcompiler_free(shader->constI);
2611     for(i = 0; i < shader->num_cb; i++) {
2612         d3dcompiler_free(shader->constB[i]);
2613     }
2614     d3dcompiler_free(shader->constB);
2615
2616     d3dcompiler_free(shader->inputs);
2617     d3dcompiler_free(shader->outputs);
2618     d3dcompiler_free(shader->samplers);
2619
2620     for(i = 0; i < shader->num_instrs; i++) {
2621         for(j = 0; j < shader->instr[i]->num_srcs; j++) {
2622             d3dcompiler_free(shader->instr[i]->src[j].rel_reg);
2623         }
2624         d3dcompiler_free(shader->instr[i]->src);
2625         d3dcompiler_free(shader->instr[i]);
2626     }
2627     d3dcompiler_free(shader->instr);
2628
2629     d3dcompiler_free(shader);
2630 }