1/**************************************************************************
2 *
3 * Copyright 2012-2021 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28/*
29 * ShaderParse.c --
30 *    Functions for parsing shader tokens.
31 */
32
33#include "Debug.h"
34#include "ShaderParse.h"
35
36#include "util/u_memory.h"
37
38
39void
40Shader_parse_init(struct Shader_parser *parser,
41                       const unsigned *code)
42{
43   parser->curr = parser->code = code;
44
45   parser->header.type = DECODE_D3D10_SB_TOKENIZED_PROGRAM_TYPE(*parser->curr);
46   parser->header.major_version = DECODE_D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION(*parser->curr);
47   parser->header.minor_version = DECODE_D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION(*parser->curr);
48   parser->curr++;
49
50   parser->header.size = DECODE_D3D10_SB_TOKENIZED_PROGRAM_LENGTH(*parser->curr);
51   parser->curr++;
52}
53
54#define OP_NOT_DONE (1 << 0) /* not implemented yet */
55#define OP_SATURATE (1 << 1) /* saturate in opcode specific control */
56#define OP_TEST_BOOLEAN (1 << 2) /* test boolean in opcode specific control */
57#define OP_DCL (1 << 3) /* custom opcode specific control */
58#define OP_RESINFO_RET_TYPE (1 << 4) /* return type for resinfo */
59
60struct dx10_opcode_info {
61   D3D10_SB_OPCODE_TYPE type;
62   const char *name;
63   unsigned num_dst;
64   unsigned num_src;
65   unsigned flags;
66};
67
68#define _(_opcode) _opcode, #_opcode
69
70static const struct dx10_opcode_info
71opcode_info[D3D10_SB_NUM_OPCODES] = {
72   {_(D3D10_SB_OPCODE_ADD),                              1, 2, OP_SATURATE},
73   {_(D3D10_SB_OPCODE_AND),                              1, 2, 0},
74   {_(D3D10_SB_OPCODE_BREAK),                            0, 0, 0},
75   {_(D3D10_SB_OPCODE_BREAKC),                           0, 1, OP_TEST_BOOLEAN},
76   {_(D3D10_SB_OPCODE_CALL),                             0, 1, 0},
77   {_(D3D10_SB_OPCODE_CALLC),                            0, 2, OP_TEST_BOOLEAN},
78   {_(D3D10_SB_OPCODE_CASE),                             0, 1, 0},
79   {_(D3D10_SB_OPCODE_CONTINUE),                         0, 0, 0},
80   {_(D3D10_SB_OPCODE_CONTINUEC),                        0, 1, OP_TEST_BOOLEAN},
81   {_(D3D10_SB_OPCODE_CUT),                              0, 0, 0},
82   {_(D3D10_SB_OPCODE_DEFAULT),                          0, 0, 0},
83   {_(D3D10_SB_OPCODE_DERIV_RTX),                        1, 1, OP_SATURATE},
84   {_(D3D10_SB_OPCODE_DERIV_RTY),                        1, 1, OP_SATURATE},
85   {_(D3D10_SB_OPCODE_DISCARD),                          0, 1, OP_TEST_BOOLEAN},
86   {_(D3D10_SB_OPCODE_DIV),                              1, 2, OP_SATURATE},
87   {_(D3D10_SB_OPCODE_DP2),                              1, 2, OP_SATURATE},
88   {_(D3D10_SB_OPCODE_DP3),                              1, 2, OP_SATURATE},
89   {_(D3D10_SB_OPCODE_DP4),                              1, 2, OP_SATURATE},
90   {_(D3D10_SB_OPCODE_ELSE),                             0, 0, 0},
91   {_(D3D10_SB_OPCODE_EMIT),                             0, 0, 0},
92   {_(D3D10_SB_OPCODE_EMITTHENCUT),                      0, 0, 0},
93   {_(D3D10_SB_OPCODE_ENDIF),                            0, 0, 0},
94   {_(D3D10_SB_OPCODE_ENDLOOP),                          0, 0, 0},
95   {_(D3D10_SB_OPCODE_ENDSWITCH),                        0, 0, 0},
96   {_(D3D10_SB_OPCODE_EQ),                               1, 2, 0},
97   {_(D3D10_SB_OPCODE_EXP),                              1, 1, OP_SATURATE},
98   {_(D3D10_SB_OPCODE_FRC),                              1, 1, OP_SATURATE},
99   {_(D3D10_SB_OPCODE_FTOI),                             1, 1, 0},
100   {_(D3D10_SB_OPCODE_FTOU),                             1, 1, 0},
101   {_(D3D10_SB_OPCODE_GE),                               1, 2, 0},
102   {_(D3D10_SB_OPCODE_IADD),                             1, 2, 0},
103   {_(D3D10_SB_OPCODE_IF),                               0, 1, OP_TEST_BOOLEAN},
104   {_(D3D10_SB_OPCODE_IEQ),                              1, 2, 0},
105   {_(D3D10_SB_OPCODE_IGE),                              1, 2, 0},
106   {_(D3D10_SB_OPCODE_ILT),                              1, 2, 0},
107   {_(D3D10_SB_OPCODE_IMAD),                             1, 3, 0},
108   {_(D3D10_SB_OPCODE_IMAX),                             1, 2, 0},
109   {_(D3D10_SB_OPCODE_IMIN),                             1, 2, 0},
110   {_(D3D10_SB_OPCODE_IMUL),                             2, 2, 0},
111   {_(D3D10_SB_OPCODE_INE),                              1, 2, 0},
112   {_(D3D10_SB_OPCODE_INEG),                             1, 1, 0},
113   {_(D3D10_SB_OPCODE_ISHL),                             1, 2, 0},
114   {_(D3D10_SB_OPCODE_ISHR),                             1, 2, 0},
115   {_(D3D10_SB_OPCODE_ITOF),                             1, 1, 0},
116   {_(D3D10_SB_OPCODE_LABEL),                            0, 1, 0},
117   {_(D3D10_SB_OPCODE_LD),                               1, 2, 0},
118   {_(D3D10_SB_OPCODE_LD_MS),                            1, 3, 0},
119   {_(D3D10_SB_OPCODE_LOG),                              1, 1, OP_SATURATE},
120   {_(D3D10_SB_OPCODE_LOOP),                             0, 0, 0},
121   {_(D3D10_SB_OPCODE_LT),                               1, 2, 0},
122   {_(D3D10_SB_OPCODE_MAD),                              1, 3, OP_SATURATE},
123   {_(D3D10_SB_OPCODE_MIN),                              1, 2, OP_SATURATE},
124   {_(D3D10_SB_OPCODE_MAX),                              1, 2, OP_SATURATE},
125   {_(D3D10_SB_OPCODE_CUSTOMDATA),                       0, 0, 0},
126   {_(D3D10_SB_OPCODE_MOV),                              1, 1, OP_SATURATE},
127   {_(D3D10_SB_OPCODE_MOVC),                             1, 3, OP_SATURATE},
128   {_(D3D10_SB_OPCODE_MUL),                              1, 2, OP_SATURATE},
129   {_(D3D10_SB_OPCODE_NE),                               1, 2, 0},
130   {_(D3D10_SB_OPCODE_NOP),                              0, 0, 0},
131   {_(D3D10_SB_OPCODE_NOT),                              1, 1, 0},
132   {_(D3D10_SB_OPCODE_OR),                               1, 2, 0},
133   {_(D3D10_SB_OPCODE_RESINFO),                          1, 2, OP_RESINFO_RET_TYPE},
134   {_(D3D10_SB_OPCODE_RET),                              0, 0, 0},
135   {_(D3D10_SB_OPCODE_RETC),                             0, 1, OP_TEST_BOOLEAN},
136   {_(D3D10_SB_OPCODE_ROUND_NE),                         1, 1, OP_SATURATE},
137   {_(D3D10_SB_OPCODE_ROUND_NI),                         1, 1, OP_SATURATE},
138   {_(D3D10_SB_OPCODE_ROUND_PI),                         1, 1, OP_SATURATE},
139   {_(D3D10_SB_OPCODE_ROUND_Z),                          1, 1, OP_SATURATE},
140   {_(D3D10_SB_OPCODE_RSQ),                              1, 1, OP_SATURATE},
141   {_(D3D10_SB_OPCODE_SAMPLE),                           1, 3, 0},
142   {_(D3D10_SB_OPCODE_SAMPLE_C),                         1, 4, 0},
143   {_(D3D10_SB_OPCODE_SAMPLE_C_LZ),                      1, 4, 0},
144   {_(D3D10_SB_OPCODE_SAMPLE_L),                         1, 4, 0},
145   {_(D3D10_SB_OPCODE_SAMPLE_D),                         1, 5, 0},
146   {_(D3D10_SB_OPCODE_SAMPLE_B),                         1, 4, 0},
147   {_(D3D10_SB_OPCODE_SQRT),                             1, 1, OP_SATURATE},
148   {_(D3D10_SB_OPCODE_SWITCH),                           0, 1, 0},
149   {_(D3D10_SB_OPCODE_SINCOS),                           2, 1, OP_SATURATE},
150   {_(D3D10_SB_OPCODE_UDIV),                             2, 2, 0},
151   {_(D3D10_SB_OPCODE_ULT),                              1, 2, 0},
152   {_(D3D10_SB_OPCODE_UGE),                              1, 2, 0},
153   {_(D3D10_SB_OPCODE_UMUL),                             2, 2, 0},
154   {_(D3D10_SB_OPCODE_UMAD),                             1, 3, 0},
155   {_(D3D10_SB_OPCODE_UMAX),                             1, 2, 0},
156   {_(D3D10_SB_OPCODE_UMIN),                             1, 2, 0},
157   {_(D3D10_SB_OPCODE_USHR),                             1, 2, 0},
158   {_(D3D10_SB_OPCODE_UTOF),                             1, 1, 0},
159   {_(D3D10_SB_OPCODE_XOR),                              1, 2, 0},
160   {_(D3D10_SB_OPCODE_DCL_RESOURCE),                     1, 0, OP_DCL},
161   {_(D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER),              0, 1, OP_DCL},
162   {_(D3D10_SB_OPCODE_DCL_SAMPLER),                      1, 0, OP_DCL},
163   {_(D3D10_SB_OPCODE_DCL_INDEX_RANGE),                  1, 0, OP_DCL},
164   {_(D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY), 0, 0, OP_DCL},
165   {_(D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE),           0, 0, OP_DCL},
166   {_(D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT),      0, 0, OP_DCL},
167   {_(D3D10_SB_OPCODE_DCL_INPUT),                        1, 0, OP_DCL},
168   {_(D3D10_SB_OPCODE_DCL_INPUT_SGV),                    1, 0, OP_DCL},
169   {_(D3D10_SB_OPCODE_DCL_INPUT_SIV),                    1, 0, OP_DCL},
170   {_(D3D10_SB_OPCODE_DCL_INPUT_PS),                     1, 0, OP_DCL},
171   {_(D3D10_SB_OPCODE_DCL_INPUT_PS_SGV),                 1, 0, OP_DCL},
172   {_(D3D10_SB_OPCODE_DCL_INPUT_PS_SIV),                 1, 0, OP_DCL},
173   {_(D3D10_SB_OPCODE_DCL_OUTPUT),                       1, 0, OP_DCL},
174   {_(D3D10_SB_OPCODE_DCL_OUTPUT_SGV),                   1, 0, OP_DCL},
175   {_(D3D10_SB_OPCODE_DCL_OUTPUT_SIV),                   1, 0, OP_DCL},
176   {_(D3D10_SB_OPCODE_DCL_TEMPS),                        0, 0, OP_DCL},
177   {_(D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP),               0, 0, OP_DCL},
178   {_(D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS),                 0, 0, OP_DCL},
179   {_(D3D10_SB_OPCODE_RESERVED0),                        0, 0, OP_NOT_DONE},
180   {_(D3D10_1_SB_OPCODE_LOD),                            0, 0, OP_NOT_DONE},
181   {_(D3D10_1_SB_OPCODE_GATHER4),                        0, 0, OP_NOT_DONE},
182   {_(D3D10_1_SB_OPCODE_SAMPLE_POS),                     0, 0, OP_NOT_DONE},
183   {_(D3D10_1_SB_OPCODE_SAMPLE_INFO),                    0, 0, OP_NOT_DONE}
184};
185
186#undef _
187
188static void
189parse_operand(const unsigned **curr,
190              struct Shader_operand *operand)
191{
192   operand->type = DECODE_D3D10_SB_OPERAND_TYPE(**curr);
193
194   /* Index dimension. */
195   switch (DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr)) {
196   case D3D10_SB_OPERAND_INDEX_0D:
197      operand->index_dim = 0;
198      break;
199   case D3D10_SB_OPERAND_INDEX_1D:
200      operand->index_dim = 1;
201      break;
202   case D3D10_SB_OPERAND_INDEX_2D:
203      operand->index_dim = 2;
204      break;
205   default:
206      assert(0);
207   }
208
209   if (operand->index_dim >= 1) {
210      operand->index[0].index_rep = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(0, **curr);
211      if (operand->index_dim >= 2) {
212         operand->index[1].index_rep = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(1, **curr);
213      }
214   }
215
216   (*curr)++;
217}
218
219static void
220parse_relative_operand(const unsigned **curr,
221                       struct Shader_relative_operand *operand)
222{
223   assert(!DECODE_IS_D3D10_SB_OPERAND_EXTENDED(**curr));
224   assert(DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(**curr) == D3D10_SB_OPERAND_4_COMPONENT);
225   assert(DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(**curr) == D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE);
226
227   operand->comp = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(**curr);
228
229   operand->type = DECODE_D3D10_SB_OPERAND_TYPE(**curr);
230   assert(operand->type != D3D10_SB_OPERAND_TYPE_IMMEDIATE32);
231
232   /* Index dimension. */
233   assert(DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(0, **curr) == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
234
235   if (DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr) == D3D10_SB_OPERAND_INDEX_1D) {
236      (*curr)++;
237      operand->index[0].imm = **curr;
238   } else {
239      assert(DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr) == D3D10_SB_OPERAND_INDEX_2D);
240      (*curr)++;
241      operand->index[0].imm = **curr;
242      (*curr)++;
243      operand->index[1].imm = **curr;
244
245   }
246   (*curr)++;
247}
248
249static void
250parse_index(const unsigned **curr,
251            struct Shader_index *index)
252{
253   switch (index->index_rep) {
254   case D3D10_SB_OPERAND_INDEX_IMMEDIATE32:
255      index->imm = *(*curr)++;
256      break;
257   case D3D10_SB_OPERAND_INDEX_RELATIVE:
258      index->imm = 0;
259      parse_relative_operand(curr, &index->rel);
260      break;
261   case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE:
262      index->imm = *(*curr)++;
263      parse_relative_operand(curr, &index->rel);
264      break;
265   default:
266      /* XXX: Support other index representations.
267       */
268      assert(0);
269   }
270}
271
272static void
273parse_operand_index(const unsigned **curr,
274                    struct Shader_operand *operand)
275{
276   if (operand->index_dim >= 1) {
277      parse_index(curr, &operand->index[0]);
278      if (operand->index_dim >= 2) {
279         parse_index(curr, &operand->index[1]);
280      }
281   }
282}
283
284boolean
285Shader_parse_opcode(struct Shader_parser *parser,
286                         struct Shader_opcode *opcode)
287{
288   const unsigned *curr = parser->curr;
289   const struct dx10_opcode_info *info;
290   unsigned length;
291   boolean opcode_is_extended;
292   unsigned i;
293
294   if (curr >= parser->code + parser->header.size) {
295      return FALSE;
296   }
297
298   memset(opcode, 0, sizeof *opcode);
299
300   /* Opcode type. */
301   opcode->type = DECODE_D3D10_SB_OPCODE_TYPE(*curr);
302
303   if (opcode->type == D3D10_SB_OPCODE_CUSTOMDATA) {
304      opcode->customdata._class = DECODE_D3D10_SB_CUSTOMDATA_CLASS(*curr);
305      curr++;
306
307      assert(opcode->customdata._class == D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER);
308
309      opcode->customdata.u.constbuf.count = *curr - 2;
310      curr++;
311
312      opcode->customdata.u.constbuf.data = MALLOC(opcode->customdata.u.constbuf.count * sizeof(unsigned));
313      assert(opcode->customdata.u.constbuf.data);
314
315      memcpy(opcode->customdata.u.constbuf.data,
316             curr,
317             opcode->customdata.u.constbuf.count * sizeof(unsigned));
318      curr += opcode->customdata.u.constbuf.count;
319
320      parser->curr = curr;
321      return TRUE;
322   }
323
324   opcode->dcl_siv_name = D3D10_SB_NAME_UNDEFINED;
325
326   /* Lookup extra information based on opcode type. */
327   assert(opcode->type < D3D10_SB_NUM_OPCODES);
328   info = &opcode_info[opcode->type];
329
330   /* Opcode specific. */
331   switch (opcode->type) {
332   case D3D10_SB_OPCODE_DCL_RESOURCE:
333      opcode->specific.dcl_resource_dimension = DECODE_D3D10_SB_RESOURCE_DIMENSION(*curr);
334      break;
335   case D3D10_SB_OPCODE_DCL_SAMPLER:
336      opcode->specific.dcl_sampler_mode = DECODE_D3D10_SB_SAMPLER_MODE(*curr);
337      break;
338   case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:
339      opcode->specific.dcl_gs_output_primitive_topology = DECODE_D3D10_SB_GS_OUTPUT_PRIMITIVE_TOPOLOGY(*curr);
340      break;
341   case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE:
342      opcode->specific.dcl_gs_input_primitive = DECODE_D3D10_SB_GS_INPUT_PRIMITIVE(*curr);
343      break;
344   case D3D10_SB_OPCODE_DCL_INPUT_PS:
345   case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV:
346      opcode->specific.dcl_in_ps_interp = DECODE_D3D10_SB_INPUT_INTERPOLATION_MODE(*curr);
347      break;
348   case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS:
349      opcode->specific.global_flags.refactoring_allowed = DECODE_D3D10_SB_GLOBAL_FLAGS(*curr) ? 1 : 0;
350      break;
351   default:
352      /* Parse opcode-specific control bits */
353      if (info->flags & OP_DCL) {
354         /* no-op */
355      } else if (info->flags & OP_SATURATE) {
356         opcode->saturate =
357            !!DECODE_IS_D3D10_SB_INSTRUCTION_SATURATE_ENABLED(*curr);
358      } else if (info->flags & OP_TEST_BOOLEAN) {
359         opcode->specific.test_boolean =
360            DECODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(*curr);
361      } else if (info->flags & OP_RESINFO_RET_TYPE) {
362         opcode->specific.resinfo_ret_type =
363            DECODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(*curr);
364      } else {
365         /* Warn if there are bits set in the opcode-specific controls (bits 23:11 inclusive)*/
366         if (*curr & ((1 << 24) - (1 << 11))) {
367            debug_printf("warning: unexpected opcode-specific control in opcode %s\n",
368                         info->name);
369         }
370      }
371      break;
372   }
373
374   /* Opcode length in DWORDs. */
375   length = DECODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(*curr);
376   assert(curr + length <= parser->code + parser->header.size);
377
378   /* Opcode specific fields in token0. */
379   switch (opcode->type) {
380   case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER:
381      opcode->specific.dcl_cb_access_pattern =
382         DECODE_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(*curr);
383      break;
384   default:
385      break;
386   }
387
388   opcode_is_extended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(*curr);
389
390   curr++;
391
392   if (opcode_is_extended) {
393      /* NOTE: DECODE_IS_D3D10_SB_OPCODE_DOUBLE_EXTENDED is broken.
394       */
395      assert(!((*curr & D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK) >> D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT));
396
397      switch (DECODE_D3D10_SB_EXTENDED_OPCODE_TYPE(*curr)) {
398      case D3D10_SB_EXTENDED_OPCODE_EMPTY:
399         break;
400      case D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS:
401         opcode->imm_texel_offset.u = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U, *curr);
402         opcode->imm_texel_offset.v = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V, *curr);
403         opcode->imm_texel_offset.w = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W, *curr);
404         break;
405      default:
406         assert(0);
407      }
408
409      curr++;
410   }
411
412   if (info->flags & OP_NOT_DONE) {
413      /* XXX: Need to figure out the number of operands for this opcode.
414       *      Should be okay to continue execution -- we have enough info
415       *      to skip to the next instruction.
416       */
417      LOG_UNSUPPORTED(TRUE);
418      opcode->num_dst = 0;
419      opcode->num_src = 0;
420      goto skip;
421   }
422
423   opcode->num_dst = info->num_dst;
424   opcode->num_src = info->num_src;
425
426   /* Destination operands. */
427   for (i = 0; i < info->num_dst; i++) {
428      D3D10_SB_OPERAND_NUM_COMPONENTS num_components;
429
430      assert(!DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*curr));
431
432      num_components = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(*curr);
433      if (num_components == D3D10_SB_OPERAND_4_COMPONENT) {
434         D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE selection_mode;
435
436         selection_mode = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(*curr);
437         assert(selection_mode == D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE);
438
439         opcode->dst[i].mask = DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(*curr);
440      } else {
441         assert(num_components == D3D10_SB_OPERAND_0_COMPONENT ||
442                num_components == D3D10_SB_OPERAND_1_COMPONENT);
443
444         opcode->dst[i].mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_X;
445      }
446
447      parse_operand(&curr, &opcode->dst[i].base);
448      parse_operand_index(&curr, &opcode->dst[i].base);
449   }
450
451   /* Source operands. */
452   for (i = 0; i < info->num_src; i++) {
453      boolean extended;
454      D3D10_SB_OPERAND_NUM_COMPONENTS num_components;
455
456      extended = DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*curr);
457
458      num_components = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(*curr);
459      if (num_components == D3D10_SB_OPERAND_4_COMPONENT) {
460         D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE selection_mode;
461
462         selection_mode = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(*curr);
463
464         if (selection_mode == D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE) {
465            opcode->src[i].swizzle[0] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 0);
466            opcode->src[i].swizzle[1] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 1);
467            opcode->src[i].swizzle[2] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 2);
468            opcode->src[i].swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 3);
469         } else if (selection_mode == D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE) {
470            opcode->src[i].swizzle[0] =
471               opcode->src[i].swizzle[1] =
472               opcode->src[i].swizzle[2] =
473               opcode->src[i].swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(*curr);
474         } else {
475            /* This case apparently happens only for 4-component 32-bit
476             * immediate operands.
477             */
478            assert(selection_mode == D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE);
479            assert(DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(*curr) == 0);
480            assert(DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_IMMEDIATE32);
481
482
483            opcode->src[i].swizzle[0] = D3D10_SB_4_COMPONENT_X;
484            opcode->src[i].swizzle[1] = D3D10_SB_4_COMPONENT_Y;
485            opcode->src[i].swizzle[2] = D3D10_SB_4_COMPONENT_Z;
486            opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_W;
487         }
488      } else if (num_components == D3D10_SB_OPERAND_1_COMPONENT) {
489         opcode->src[i].swizzle[0] =
490            opcode->src[i].swizzle[1] =
491            opcode->src[i].swizzle[2] =
492            opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_X;
493      } else {
494         /* Samplers only?
495          */
496         assert(num_components == D3D10_SB_OPERAND_0_COMPONENT);
497         assert(DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_SAMPLER ||
498                DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_LABEL);
499
500         opcode->src[i].swizzle[0] = D3D10_SB_4_COMPONENT_X;
501         opcode->src[i].swizzle[1] = D3D10_SB_4_COMPONENT_Y;
502         opcode->src[i].swizzle[2] = D3D10_SB_4_COMPONENT_Z;
503         opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_W;
504      }
505
506      parse_operand(&curr, &opcode->src[i].base);
507
508      opcode->src[i].modifier = D3D10_SB_OPERAND_MODIFIER_NONE;
509      if (extended) {
510         /* NOTE: DECODE_IS_D3D10_SB_OPERAND_DOUBLE_EXTENDED is broken.
511          */
512         assert(!((*curr & D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK) >> D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT));
513
514         switch (DECODE_D3D10_SB_EXTENDED_OPERAND_TYPE(*curr)) {
515         case D3D10_SB_EXTENDED_OPERAND_EMPTY:
516            break;
517
518         case D3D10_SB_EXTENDED_OPERAND_MODIFIER:
519            opcode->src[i].modifier = DECODE_D3D10_SB_OPERAND_MODIFIER(*curr);
520            break;
521
522         default:
523            assert(0);
524         }
525
526         curr++;
527      }
528
529      parse_operand_index(&curr, &opcode->src[i].base);
530
531      if (opcode->src[i].base.type == D3D10_SB_OPERAND_TYPE_IMMEDIATE32) {
532         switch (num_components) {
533         case D3D10_SB_OPERAND_1_COMPONENT:
534            opcode->src[i].imm[0].u32 =
535               opcode->src[i].imm[1].u32 =
536               opcode->src[i].imm[2].u32 =
537               opcode->src[i].imm[3].u32 = *curr++;
538            break;
539
540         case D3D10_SB_OPERAND_4_COMPONENT:
541            opcode->src[i].imm[0].u32 = *curr++;
542            opcode->src[i].imm[1].u32 = *curr++;
543            opcode->src[i].imm[2].u32 = *curr++;
544            opcode->src[i].imm[3].u32 = *curr++;
545            break;
546
547         default:
548            /* XXX: Support other component sizes.
549             */
550            assert(0);
551         }
552      }
553   }
554
555   /* Opcode specific trailing operands. */
556   switch (opcode->type) {
557   case D3D10_SB_OPCODE_DCL_RESOURCE:
558      opcode->dcl_resource_ret_type[0] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 0);
559      opcode->dcl_resource_ret_type[1] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 1);
560      opcode->dcl_resource_ret_type[2] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 2);
561      opcode->dcl_resource_ret_type[3] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 3);
562      curr++;
563      break;
564   case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT:
565      opcode->specific.dcl_max_output_vertex_count = *curr;
566      curr++;
567      break;
568   case D3D10_SB_OPCODE_DCL_INPUT_SGV:
569   case D3D10_SB_OPCODE_DCL_INPUT_SIV:
570   case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV:
571   case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV:
572   case D3D10_SB_OPCODE_DCL_OUTPUT_SIV:
573   case D3D10_SB_OPCODE_DCL_OUTPUT_SGV:
574      opcode->dcl_siv_name = DECODE_D3D10_SB_NAME(*curr);
575      curr++;
576      break;
577   case D3D10_SB_OPCODE_DCL_TEMPS:
578      opcode->specific.dcl_num_temps = *curr;
579      curr++;
580      break;
581   case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP:
582      opcode->specific.dcl_indexable_temp.index = *curr++;
583      opcode->specific.dcl_indexable_temp.count = *curr++;
584      opcode->specific.dcl_indexable_temp.components = *curr++;
585      break;
586   case D3D10_SB_OPCODE_DCL_INDEX_RANGE:
587      opcode->specific.index_range_count = *curr++;
588      break;
589   default:
590      break;
591   }
592
593   assert(curr == parser->curr + length);
594
595skip:
596   /* Advance to the next opcode. */
597   parser->curr += length;
598
599   return TRUE;
600}
601
602void
603Shader_opcode_free(struct Shader_opcode *opcode)
604{
605   if (opcode->type == D3D10_SB_OPCODE_CUSTOMDATA) {
606      if (opcode->customdata._class == D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER) {
607         FREE(opcode->customdata.u.constbuf.data);
608      }
609   }
610}
611