xref: /reactos/dll/directx/wine/wined3d/shader_sm1.c (revision da5f10af)
1 /*
2  * Copyright 2002-2003 Jason Edmeades
3  * Copyright 2002-2003 Raphael Junqueira
4  * Copyright 2004 Christian Costa
5  * Copyright 2005 Oliver Stieber
6  * Copyright 2006 Ivan Gyurdiev
7  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
8  * Copyright 2009 Henri Verbeet for CodeWeavers
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include "config.h"
26 #include "wine/port.h"
27 
28 #include "wined3d_private.h"
29 
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
31 
32 /* DCL usage masks */
33 #define WINED3D_SM1_DCL_USAGE_SHIFT             0
34 #define WINED3D_SM1_DCL_USAGE_MASK              (0xfu << WINED3D_SM1_DCL_USAGE_SHIFT)
35 #define WINED3D_SM1_DCL_USAGE_INDEX_SHIFT       16
36 #define WINED3D_SM1_DCL_USAGE_INDEX_MASK        (0xfu << WINED3D_SM1_DCL_USAGE_INDEX_SHIFT)
37 
38 /* DCL sampler type */
39 #define WINED3D_SM1_RESOURCE_TYPE_SHIFT         27
40 #define WINED3D_SM1_RESOURCE_TYPE_MASK          (0xfu << WINED3D_SM1_RESOURCE_TYPE_SHIFT)
41 
42 /* Opcode-related masks */
43 #define WINED3D_SM1_OPCODE_MASK                 0x0000ffff
44 
45 #define WINED3D_SM1_INSTRUCTION_FLAGS_SHIFT     16
46 #define WINED3D_SM1_INSTRUCTION_FLAGS_MASK      (0xffu << WINED3D_SM1_INSTRUCTION_FLAGS_SHIFT)
47 
48 #define WINED3D_SM1_INSTRUCTION_LENGTH_SHIFT    24
49 #define WINED3D_SM1_INSTRUCTION_LENGTH_MASK     (0xfu << WINED3D_SM1_INSTRUCTION_LENGTH_SHIFT)
50 
51 #define WINED3D_SM1_COISSUE                     (0x1u << 30)
52 
53 #define WINED3D_SM1_COMMENT_SIZE_SHIFT          16
54 #define WINED3D_SM1_COMMENT_SIZE_MASK           (0x7fffu << WINED3D_SM1_COMMENT_SIZE_SHIFT)
55 
56 #define WINED3D_SM1_INSTRUCTION_PREDICATED      (0x1u << 28)
57 
58 /* Register number mask */
59 #define WINED3D_SM1_REGISTER_NUMBER_MASK        0x000007ff
60 
61 /* Register type masks  */
62 #define WINED3D_SM1_REGISTER_TYPE_SHIFT         28
63 #define WINED3D_SM1_REGISTER_TYPE_MASK          (0x7u << WINED3D_SM1_REGISTER_TYPE_SHIFT)
64 #define WINED3D_SM1_REGISTER_TYPE_SHIFT2        8
65 #define WINED3D_SM1_REGISTER_TYPE_MASK2         (0x18u << WINED3D_SM1_REGISTER_TYPE_SHIFT2)
66 
67 /* Relative addressing mask */
68 #define WINED3D_SM1_ADDRESS_MODE_SHIFT          13
69 #define WINED3D_SM1_ADDRESS_MODE_MASK           (0x1u << WINED3D_SM1_ADDRESS_MODE_SHIFT)
70 
71 /* Destination modifier mask */
72 #define WINED3D_SM1_DST_MODIFIER_SHIFT          20
73 #define WINED3D_SM1_DST_MODIFIER_MASK           (0xfu << WINED3D_SM1_DST_MODIFIER_SHIFT)
74 
75 /* Destination shift mask */
76 #define WINED3D_SM1_DSTSHIFT_SHIFT              24
77 #define WINED3D_SM1_DSTSHIFT_MASK               (0xfu << WINED3D_SM1_DSTSHIFT_SHIFT)
78 
79 /* Write mask */
80 #define WINED3D_SM1_WRITEMASK_SHIFT             16
81 #define WINED3D_SM1_WRITEMASK_MASK              (0xfu << WINED3D_SM1_WRITEMASK_SHIFT)
82 
83 /* Swizzle mask */
84 #define WINED3D_SM1_SWIZZLE_SHIFT               16
85 #define WINED3D_SM1_SWIZZLE_MASK                (0xffu << WINED3D_SM1_SWIZZLE_SHIFT)
86 
87 /* Source modifier mask */
88 #define WINED3D_SM1_SRC_MODIFIER_SHIFT          24
89 #define WINED3D_SM1_SRC_MODIFIER_MASK           (0xfu << WINED3D_SM1_SRC_MODIFIER_SHIFT)
90 
91 #define WINED3D_SM1_END                         0x0000ffff
92 
93 #define WINED3D_SM1_VERSION_MAJOR(version)      (((version) >> 8) & 0xff)
94 #define WINED3D_SM1_VERSION_MINOR(version)      (((version) >> 0) & 0xff)
95 
96 enum wined3d_sm1_address_mode_type
97 {
98     WINED3D_SM1_ADDRESS_MODE_ABSOLUTE = 0u << WINED3D_SM1_ADDRESS_MODE_SHIFT,
99     WINED3D_SM1_ADDRESS_MODE_RELATIVE = 1u << WINED3D_SM1_ADDRESS_MODE_SHIFT,
100 };
101 
102 enum wined3d_sm1_resource_type
103 {
104     WINED3D_SM1_RESOURCE_UNKNOWN        = 0x0,
105     WINED3D_SM1_RESOURCE_TEXTURE_1D     = 0x1,
106     WINED3D_SM1_RESOURCE_TEXTURE_2D     = 0x2,
107     WINED3D_SM1_RESOURCE_TEXTURE_CUBE   = 0x3,
108     WINED3D_SM1_RESOURCE_TEXTURE_3D     = 0x4,
109 };
110 
111 enum wined3d_sm1_opcode
112 {
113     WINED3D_SM1_OP_NOP          = 0x00,
114     WINED3D_SM1_OP_MOV          = 0x01,
115     WINED3D_SM1_OP_ADD          = 0x02,
116     WINED3D_SM1_OP_SUB          = 0x03,
117     WINED3D_SM1_OP_MAD          = 0x04,
118     WINED3D_SM1_OP_MUL          = 0x05,
119     WINED3D_SM1_OP_RCP          = 0x06,
120     WINED3D_SM1_OP_RSQ          = 0x07,
121     WINED3D_SM1_OP_DP3          = 0x08,
122     WINED3D_SM1_OP_DP4          = 0x09,
123     WINED3D_SM1_OP_MIN          = 0x0a,
124     WINED3D_SM1_OP_MAX          = 0x0b,
125     WINED3D_SM1_OP_SLT          = 0x0c,
126     WINED3D_SM1_OP_SGE          = 0x0d,
127     WINED3D_SM1_OP_EXP          = 0x0e,
128     WINED3D_SM1_OP_LOG          = 0x0f,
129     WINED3D_SM1_OP_LIT          = 0x10,
130     WINED3D_SM1_OP_DST          = 0x11,
131     WINED3D_SM1_OP_LRP          = 0x12,
132     WINED3D_SM1_OP_FRC          = 0x13,
133     WINED3D_SM1_OP_M4x4         = 0x14,
134     WINED3D_SM1_OP_M4x3         = 0x15,
135     WINED3D_SM1_OP_M3x4         = 0x16,
136     WINED3D_SM1_OP_M3x3         = 0x17,
137     WINED3D_SM1_OP_M3x2         = 0x18,
138     WINED3D_SM1_OP_CALL         = 0x19,
139     WINED3D_SM1_OP_CALLNZ       = 0x1a,
140     WINED3D_SM1_OP_LOOP         = 0x1b,
141     WINED3D_SM1_OP_RET          = 0x1c,
142     WINED3D_SM1_OP_ENDLOOP      = 0x1d,
143     WINED3D_SM1_OP_LABEL        = 0x1e,
144     WINED3D_SM1_OP_DCL          = 0x1f,
145     WINED3D_SM1_OP_POW          = 0x20,
146     WINED3D_SM1_OP_CRS          = 0x21,
147     WINED3D_SM1_OP_SGN          = 0x22,
148     WINED3D_SM1_OP_ABS          = 0x23,
149     WINED3D_SM1_OP_NRM          = 0x24,
150     WINED3D_SM1_OP_SINCOS       = 0x25,
151     WINED3D_SM1_OP_REP          = 0x26,
152     WINED3D_SM1_OP_ENDREP       = 0x27,
153     WINED3D_SM1_OP_IF           = 0x28,
154     WINED3D_SM1_OP_IFC          = 0x29,
155     WINED3D_SM1_OP_ELSE         = 0x2a,
156     WINED3D_SM1_OP_ENDIF        = 0x2b,
157     WINED3D_SM1_OP_BREAK        = 0x2c,
158     WINED3D_SM1_OP_BREAKC       = 0x2d,
159     WINED3D_SM1_OP_MOVA         = 0x2e,
160     WINED3D_SM1_OP_DEFB         = 0x2f,
161     WINED3D_SM1_OP_DEFI         = 0x30,
162 
163     WINED3D_SM1_OP_TEXCOORD     = 0x40,
164     WINED3D_SM1_OP_TEXKILL      = 0x41,
165     WINED3D_SM1_OP_TEX          = 0x42,
166     WINED3D_SM1_OP_TEXBEM       = 0x43,
167     WINED3D_SM1_OP_TEXBEML      = 0x44,
168     WINED3D_SM1_OP_TEXREG2AR    = 0x45,
169     WINED3D_SM1_OP_TEXREG2GB    = 0x46,
170     WINED3D_SM1_OP_TEXM3x2PAD   = 0x47,
171     WINED3D_SM1_OP_TEXM3x2TEX   = 0x48,
172     WINED3D_SM1_OP_TEXM3x3PAD   = 0x49,
173     WINED3D_SM1_OP_TEXM3x3TEX   = 0x4a,
174     WINED3D_SM1_OP_TEXM3x3DIFF  = 0x4b,
175     WINED3D_SM1_OP_TEXM3x3SPEC  = 0x4c,
176     WINED3D_SM1_OP_TEXM3x3VSPEC = 0x4d,
177     WINED3D_SM1_OP_EXPP         = 0x4e,
178     WINED3D_SM1_OP_LOGP         = 0x4f,
179     WINED3D_SM1_OP_CND          = 0x50,
180     WINED3D_SM1_OP_DEF          = 0x51,
181     WINED3D_SM1_OP_TEXREG2RGB   = 0x52,
182     WINED3D_SM1_OP_TEXDP3TEX    = 0x53,
183     WINED3D_SM1_OP_TEXM3x2DEPTH = 0x54,
184     WINED3D_SM1_OP_TEXDP3       = 0x55,
185     WINED3D_SM1_OP_TEXM3x3      = 0x56,
186     WINED3D_SM1_OP_TEXDEPTH     = 0x57,
187     WINED3D_SM1_OP_CMP          = 0x58,
188     WINED3D_SM1_OP_BEM          = 0x59,
189     WINED3D_SM1_OP_DP2ADD       = 0x5a,
190     WINED3D_SM1_OP_DSX          = 0x5b,
191     WINED3D_SM1_OP_DSY          = 0x5c,
192     WINED3D_SM1_OP_TEXLDD       = 0x5d,
193     WINED3D_SM1_OP_SETP         = 0x5e,
194     WINED3D_SM1_OP_TEXLDL       = 0x5f,
195     WINED3D_SM1_OP_BREAKP       = 0x60,
196 
197     WINED3D_SM1_OP_PHASE        = 0xfffd,
198     WINED3D_SM1_OP_COMMENT      = 0xfffe,
199     WINED3D_SM1_OP_END          = 0Xffff,
200 };
201 
202 struct wined3d_sm1_opcode_info
203 {
204     enum wined3d_sm1_opcode opcode;
205     unsigned int dst_count;
206     unsigned int param_count;
207     enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
208     DWORD min_version;
209     DWORD max_version;
210 };
211 
212 struct wined3d_sm1_data
213 {
214     struct wined3d_shader_version shader_version;
215     const struct wined3d_sm1_opcode_info *opcode_table;
216     const DWORD *start;
217 
218     struct wined3d_shader_src_param src_rel_addr[4];
219     struct wined3d_shader_src_param pred_rel_addr;
220     struct wined3d_shader_src_param dst_rel_addr;
221     struct wined3d_shader_src_param src_param[4];
222     struct wined3d_shader_src_param pred_param;
223     struct wined3d_shader_dst_param dst_param;
224 };
225 
226 /* This table is not order or position dependent. */
227 static const struct wined3d_sm1_opcode_info vs_opcode_table[] =
228 {
229     /* Arithmetic */
230     {WINED3D_SM1_OP_NOP,      0, 0, WINED3DSIH_NOP,          0,                           0                          },
231     {WINED3D_SM1_OP_MOV,      1, 2, WINED3DSIH_MOV,          0,                           0                          },
232     {WINED3D_SM1_OP_MOVA,     1, 2, WINED3DSIH_MOVA,         WINED3D_SHADER_VERSION(2,0), -1                         },
233     {WINED3D_SM1_OP_ADD,      1, 3, WINED3DSIH_ADD,          0,                           0                          },
234     {WINED3D_SM1_OP_SUB,      1, 3, WINED3DSIH_SUB,          0,                           0                          },
235     {WINED3D_SM1_OP_MAD,      1, 4, WINED3DSIH_MAD,          0,                           0                          },
236     {WINED3D_SM1_OP_MUL,      1, 3, WINED3DSIH_MUL,          0,                           0                          },
237     {WINED3D_SM1_OP_RCP,      1, 2, WINED3DSIH_RCP,          0,                           0                          },
238     {WINED3D_SM1_OP_RSQ,      1, 2, WINED3DSIH_RSQ,          0,                           0                          },
239     {WINED3D_SM1_OP_DP3,      1, 3, WINED3DSIH_DP3,          0,                           0                          },
240     {WINED3D_SM1_OP_DP4,      1, 3, WINED3DSIH_DP4,          0,                           0                          },
241     {WINED3D_SM1_OP_MIN,      1, 3, WINED3DSIH_MIN,          0,                           0                          },
242     {WINED3D_SM1_OP_MAX,      1, 3, WINED3DSIH_MAX,          0,                           0                          },
243     {WINED3D_SM1_OP_SLT,      1, 3, WINED3DSIH_SLT,          0,                           0                          },
244     {WINED3D_SM1_OP_SGE,      1, 3, WINED3DSIH_SGE,          0,                           0                          },
245     {WINED3D_SM1_OP_ABS,      1, 2, WINED3DSIH_ABS,          0,                           0                          },
246     {WINED3D_SM1_OP_EXP,      1, 2, WINED3DSIH_EXP,          0,                           0                          },
247     {WINED3D_SM1_OP_LOG,      1, 2, WINED3DSIH_LOG,          0,                           0                          },
248     {WINED3D_SM1_OP_EXPP,     1, 2, WINED3DSIH_EXPP,         0,                           0                          },
249     {WINED3D_SM1_OP_LOGP,     1, 2, WINED3DSIH_LOGP,         0,                           0                          },
250     {WINED3D_SM1_OP_LIT,      1, 2, WINED3DSIH_LIT,          0,                           0                          },
251     {WINED3D_SM1_OP_DST,      1, 3, WINED3DSIH_DST,          0,                           0                          },
252     {WINED3D_SM1_OP_LRP,      1, 4, WINED3DSIH_LRP,          0,                           0                          },
253     {WINED3D_SM1_OP_FRC,      1, 2, WINED3DSIH_FRC,          0,                           0                          },
254     {WINED3D_SM1_OP_POW,      1, 3, WINED3DSIH_POW,          0,                           0                          },
255     {WINED3D_SM1_OP_CRS,      1, 3, WINED3DSIH_CRS,          0,                           0                          },
256     {WINED3D_SM1_OP_SGN,      1, 4, WINED3DSIH_SGN,          WINED3D_SHADER_VERSION(2,0), WINED3D_SHADER_VERSION(2,1)},
257     {WINED3D_SM1_OP_SGN,      1, 2, WINED3DSIH_SGN,          WINED3D_SHADER_VERSION(3,0), -1                         },
258     {WINED3D_SM1_OP_NRM,      1, 2, WINED3DSIH_NRM,          0,                           0                          },
259     {WINED3D_SM1_OP_SINCOS,   1, 4, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(2,0), WINED3D_SHADER_VERSION(2,1)},
260     {WINED3D_SM1_OP_SINCOS,   1, 2, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(3,0), -1                         },
261     /* Matrix */
262     {WINED3D_SM1_OP_M4x4,     1, 3, WINED3DSIH_M4x4,         0,                           0                          },
263     {WINED3D_SM1_OP_M4x3,     1, 3, WINED3DSIH_M4x3,         0,                           0                          },
264     {WINED3D_SM1_OP_M3x4,     1, 3, WINED3DSIH_M3x4,         0,                           0                          },
265     {WINED3D_SM1_OP_M3x3,     1, 3, WINED3DSIH_M3x3,         0,                           0                          },
266     {WINED3D_SM1_OP_M3x2,     1, 3, WINED3DSIH_M3x2,         0,                           0                          },
267     /* Declare registers */
268     {WINED3D_SM1_OP_DCL,      0, 2, WINED3DSIH_DCL,          0,                           0                          },
269     /* Constant definitions */
270     {WINED3D_SM1_OP_DEF,      1, 5, WINED3DSIH_DEF,          0,                           0                          },
271     {WINED3D_SM1_OP_DEFB,     1, 2, WINED3DSIH_DEFB,         0,                           0                          },
272     {WINED3D_SM1_OP_DEFI,     1, 5, WINED3DSIH_DEFI,         0,                           0                          },
273     /* Flow control */
274     {WINED3D_SM1_OP_REP,      0, 1, WINED3DSIH_REP,          WINED3D_SHADER_VERSION(2,0), -1                         },
275     {WINED3D_SM1_OP_ENDREP,   0, 0, WINED3DSIH_ENDREP,       WINED3D_SHADER_VERSION(2,0), -1                         },
276     {WINED3D_SM1_OP_IF,       0, 1, WINED3DSIH_IF,           WINED3D_SHADER_VERSION(2,0), -1                         },
277     {WINED3D_SM1_OP_IFC,      0, 2, WINED3DSIH_IFC,          WINED3D_SHADER_VERSION(2,1), -1                         },
278     {WINED3D_SM1_OP_ELSE,     0, 0, WINED3DSIH_ELSE,         WINED3D_SHADER_VERSION(2,0), -1                         },
279     {WINED3D_SM1_OP_ENDIF,    0, 0, WINED3DSIH_ENDIF,        WINED3D_SHADER_VERSION(2,0), -1                         },
280     {WINED3D_SM1_OP_BREAK,    0, 0, WINED3DSIH_BREAK,        WINED3D_SHADER_VERSION(2,1), -1                         },
281     {WINED3D_SM1_OP_BREAKC,   0, 2, WINED3DSIH_BREAKC,       WINED3D_SHADER_VERSION(2,1), -1                         },
282     {WINED3D_SM1_OP_BREAKP,   0, 1, WINED3DSIH_BREAKP,       0,                           0                          },
283     {WINED3D_SM1_OP_CALL,     0, 1, WINED3DSIH_CALL,         WINED3D_SHADER_VERSION(2,0), -1                         },
284     {WINED3D_SM1_OP_CALLNZ,   0, 2, WINED3DSIH_CALLNZ,       WINED3D_SHADER_VERSION(2,0), -1                         },
285     {WINED3D_SM1_OP_LOOP,     0, 2, WINED3DSIH_LOOP,         WINED3D_SHADER_VERSION(2,0), -1                         },
286     {WINED3D_SM1_OP_RET,      0, 0, WINED3DSIH_RET,          WINED3D_SHADER_VERSION(2,0), -1                         },
287     {WINED3D_SM1_OP_ENDLOOP,  0, 0, WINED3DSIH_ENDLOOP,      WINED3D_SHADER_VERSION(2,0), -1                         },
288     {WINED3D_SM1_OP_LABEL,    0, 1, WINED3DSIH_LABEL,        WINED3D_SHADER_VERSION(2,0), -1                         },
289 
290     {WINED3D_SM1_OP_SETP,     1, 3, WINED3DSIH_SETP,         0,                           0                          },
291     {WINED3D_SM1_OP_TEXLDL,   1, 3, WINED3DSIH_TEXLDL,       WINED3D_SHADER_VERSION(3,0), -1                         },
292     {0,                       0, 0, WINED3DSIH_TABLE_SIZE,   0,                           0                          },
293 };
294 
295 static const struct wined3d_sm1_opcode_info ps_opcode_table[] =
296 {
297     /* Arithmetic */
298     {WINED3D_SM1_OP_NOP,      0, 0, WINED3DSIH_NOP,          0,                           0                          },
299     {WINED3D_SM1_OP_MOV,      1, 2, WINED3DSIH_MOV,          0,                           0                          },
300     {WINED3D_SM1_OP_ADD,      1, 3, WINED3DSIH_ADD,          0,                           0                          },
301     {WINED3D_SM1_OP_SUB,      1, 3, WINED3DSIH_SUB,          0,                           0                          },
302     {WINED3D_SM1_OP_MAD,      1, 4, WINED3DSIH_MAD,          0,                           0                          },
303     {WINED3D_SM1_OP_MUL,      1, 3, WINED3DSIH_MUL,          0,                           0                          },
304     {WINED3D_SM1_OP_RCP,      1, 2, WINED3DSIH_RCP,          0,                           0                          },
305     {WINED3D_SM1_OP_RSQ,      1, 2, WINED3DSIH_RSQ,          0,                           0                          },
306     {WINED3D_SM1_OP_DP3,      1, 3, WINED3DSIH_DP3,          0,                           0                          },
307     {WINED3D_SM1_OP_DP4,      1, 3, WINED3DSIH_DP4,          0,                           0                          },
308     {WINED3D_SM1_OP_MIN,      1, 3, WINED3DSIH_MIN,          0,                           0                          },
309     {WINED3D_SM1_OP_MAX,      1, 3, WINED3DSIH_MAX,          0,                           0                          },
310     {WINED3D_SM1_OP_SLT,      1, 3, WINED3DSIH_SLT,          0,                           0                          },
311     {WINED3D_SM1_OP_SGE,      1, 3, WINED3DSIH_SGE,          0,                           0                          },
312     {WINED3D_SM1_OP_ABS,      1, 2, WINED3DSIH_ABS,          0,                           0                          },
313     {WINED3D_SM1_OP_EXP,      1, 2, WINED3DSIH_EXP,          0,                           0                          },
314     {WINED3D_SM1_OP_LOG,      1, 2, WINED3DSIH_LOG,          0,                           0                          },
315     {WINED3D_SM1_OP_EXPP,     1, 2, WINED3DSIH_EXPP,         0,                           0                          },
316     {WINED3D_SM1_OP_LOGP,     1, 2, WINED3DSIH_LOGP,         0,                           0                          },
317     {WINED3D_SM1_OP_DST,      1, 3, WINED3DSIH_DST,          0,                           0                          },
318     {WINED3D_SM1_OP_LRP,      1, 4, WINED3DSIH_LRP,          0,                           0                          },
319     {WINED3D_SM1_OP_FRC,      1, 2, WINED3DSIH_FRC,          0,                           0                          },
320     {WINED3D_SM1_OP_CND,      1, 4, WINED3DSIH_CND,          WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,4)},
321     {WINED3D_SM1_OP_CMP,      1, 4, WINED3DSIH_CMP,          WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(3,0)},
322     {WINED3D_SM1_OP_POW,      1, 3, WINED3DSIH_POW,          0,                           0                          },
323     {WINED3D_SM1_OP_CRS,      1, 3, WINED3DSIH_CRS,          0,                           0                          },
324     {WINED3D_SM1_OP_NRM,      1, 2, WINED3DSIH_NRM,          0,                           0                          },
325     {WINED3D_SM1_OP_SINCOS,   1, 4, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(2,0), WINED3D_SHADER_VERSION(2,1)},
326     {WINED3D_SM1_OP_SINCOS,   1, 2, WINED3DSIH_SINCOS,       WINED3D_SHADER_VERSION(3,0), -1                         },
327     {WINED3D_SM1_OP_DP2ADD,   1, 4, WINED3DSIH_DP2ADD,       WINED3D_SHADER_VERSION(2,0), -1                         },
328     /* Matrix */
329     {WINED3D_SM1_OP_M4x4,     1, 3, WINED3DSIH_M4x4,         0,                           0                          },
330     {WINED3D_SM1_OP_M4x3,     1, 3, WINED3DSIH_M4x3,         0,                           0                          },
331     {WINED3D_SM1_OP_M3x4,     1, 3, WINED3DSIH_M3x4,         0,                           0                          },
332     {WINED3D_SM1_OP_M3x3,     1, 3, WINED3DSIH_M3x3,         0,                           0                          },
333     {WINED3D_SM1_OP_M3x2,     1, 3, WINED3DSIH_M3x2,         0,                           0                          },
334     /* Register declarations */
335     {WINED3D_SM1_OP_DCL,      0, 2, WINED3DSIH_DCL,          0,                           0                          },
336     /* Flow control */
337     {WINED3D_SM1_OP_REP,      0, 1, WINED3DSIH_REP,          WINED3D_SHADER_VERSION(2,1), -1                         },
338     {WINED3D_SM1_OP_ENDREP,   0, 0, WINED3DSIH_ENDREP,       WINED3D_SHADER_VERSION(2,1), -1                         },
339     {WINED3D_SM1_OP_IF,       0, 1, WINED3DSIH_IF,           WINED3D_SHADER_VERSION(2,1), -1                         },
340     {WINED3D_SM1_OP_IFC,      0, 2, WINED3DSIH_IFC,          WINED3D_SHADER_VERSION(2,1), -1                         },
341     {WINED3D_SM1_OP_ELSE,     0, 0, WINED3DSIH_ELSE,         WINED3D_SHADER_VERSION(2,1), -1                         },
342     {WINED3D_SM1_OP_ENDIF,    0, 0, WINED3DSIH_ENDIF,        WINED3D_SHADER_VERSION(2,1), -1                         },
343     {WINED3D_SM1_OP_BREAK,    0, 0, WINED3DSIH_BREAK,        WINED3D_SHADER_VERSION(2,1), -1                         },
344     {WINED3D_SM1_OP_BREAKC,   0, 2, WINED3DSIH_BREAKC,       WINED3D_SHADER_VERSION(2,1), -1                         },
345     {WINED3D_SM1_OP_BREAKP,   0, 1, WINED3DSIH_BREAKP,       0,                           0                          },
346     {WINED3D_SM1_OP_CALL,     0, 1, WINED3DSIH_CALL,         WINED3D_SHADER_VERSION(2,1), -1                         },
347     {WINED3D_SM1_OP_CALLNZ,   0, 2, WINED3DSIH_CALLNZ,       WINED3D_SHADER_VERSION(2,1), -1                         },
348     {WINED3D_SM1_OP_LOOP,     0, 2, WINED3DSIH_LOOP,         WINED3D_SHADER_VERSION(3,0), -1                         },
349     {WINED3D_SM1_OP_RET,      0, 0, WINED3DSIH_RET,          WINED3D_SHADER_VERSION(2,1), -1                         },
350     {WINED3D_SM1_OP_ENDLOOP,  0, 0, WINED3DSIH_ENDLOOP,      WINED3D_SHADER_VERSION(3,0), -1                         },
351     {WINED3D_SM1_OP_LABEL,    0, 1, WINED3DSIH_LABEL,        WINED3D_SHADER_VERSION(2,1), -1                         },
352     /* Constant definitions */
353     {WINED3D_SM1_OP_DEF,      1, 5, WINED3DSIH_DEF,          0,                           0                          },
354     {WINED3D_SM1_OP_DEFB,     1, 2, WINED3DSIH_DEFB,         0,                           0                          },
355     {WINED3D_SM1_OP_DEFI,     1, 5, WINED3DSIH_DEFI,         0,                           0                          },
356     /* Texture */
357     {WINED3D_SM1_OP_TEXCOORD, 1, 1, WINED3DSIH_TEXCOORD,     0,                           WINED3D_SHADER_VERSION(1,3)},
358     {WINED3D_SM1_OP_TEXCOORD, 1, 2, WINED3DSIH_TEXCOORD,     WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
359     {WINED3D_SM1_OP_TEXKILL,  1, 1, WINED3DSIH_TEXKILL,      WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(3,0)},
360     {WINED3D_SM1_OP_TEX,      1, 1, WINED3DSIH_TEX,          0,                           WINED3D_SHADER_VERSION(1,3)},
361     {WINED3D_SM1_OP_TEX,      1, 2, WINED3DSIH_TEX,          WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
362     {WINED3D_SM1_OP_TEX,      1, 3, WINED3DSIH_TEX,          WINED3D_SHADER_VERSION(2,0), -1                         },
363     {WINED3D_SM1_OP_TEXBEM,   1, 2, WINED3DSIH_TEXBEM,       0,                           WINED3D_SHADER_VERSION(1,3)},
364     {WINED3D_SM1_OP_TEXBEML,  1, 2, WINED3DSIH_TEXBEML,      WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
365     {WINED3D_SM1_OP_TEXREG2AR,      1, 2, WINED3DSIH_TEXREG2AR,    WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
366     {WINED3D_SM1_OP_TEXREG2GB,      1, 2, WINED3DSIH_TEXREG2GB,    WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
367     {WINED3D_SM1_OP_TEXREG2RGB,     1, 2, WINED3DSIH_TEXREG2RGB,   WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
368     {WINED3D_SM1_OP_TEXM3x2PAD,     1, 2, WINED3DSIH_TEXM3x2PAD,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
369     {WINED3D_SM1_OP_TEXM3x2TEX,     1, 2, WINED3DSIH_TEXM3x2TEX,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
370     {WINED3D_SM1_OP_TEXM3x3PAD,     1, 2, WINED3DSIH_TEXM3x3PAD,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
371     {WINED3D_SM1_OP_TEXM3x3DIFF,    1, 2, WINED3DSIH_TEXM3x3DIFF,  WINED3D_SHADER_VERSION(0,0), WINED3D_SHADER_VERSION(0,0)},
372     {WINED3D_SM1_OP_TEXM3x3SPEC,    1, 3, WINED3DSIH_TEXM3x3SPEC,  WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
373     {WINED3D_SM1_OP_TEXM3x3VSPEC,   1, 2, WINED3DSIH_TEXM3x3VSPEC, WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
374     {WINED3D_SM1_OP_TEXM3x3TEX,     1, 2, WINED3DSIH_TEXM3x3TEX,   WINED3D_SHADER_VERSION(1,0), WINED3D_SHADER_VERSION(1,3)},
375     {WINED3D_SM1_OP_TEXDP3TEX,      1, 2, WINED3DSIH_TEXDP3TEX,    WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
376     {WINED3D_SM1_OP_TEXM3x2DEPTH,   1, 2, WINED3DSIH_TEXM3x2DEPTH, WINED3D_SHADER_VERSION(1,3), WINED3D_SHADER_VERSION(1,3)},
377     {WINED3D_SM1_OP_TEXDP3,   1, 2, WINED3DSIH_TEXDP3,       WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
378     {WINED3D_SM1_OP_TEXM3x3,  1, 2, WINED3DSIH_TEXM3x3,      WINED3D_SHADER_VERSION(1,2), WINED3D_SHADER_VERSION(1,3)},
379     {WINED3D_SM1_OP_TEXDEPTH, 1, 1, WINED3DSIH_TEXDEPTH,     WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
380     {WINED3D_SM1_OP_BEM,      1, 3, WINED3DSIH_BEM,          WINED3D_SHADER_VERSION(1,4), WINED3D_SHADER_VERSION(1,4)},
381     {WINED3D_SM1_OP_DSX,      1, 2, WINED3DSIH_DSX,          WINED3D_SHADER_VERSION(2,1), -1                         },
382     {WINED3D_SM1_OP_DSY,      1, 2, WINED3DSIH_DSY,          WINED3D_SHADER_VERSION(2,1), -1                         },
383     {WINED3D_SM1_OP_TEXLDD,   1, 5, WINED3DSIH_TEXLDD,       WINED3D_SHADER_VERSION(2,1), -1                         },
384     {WINED3D_SM1_OP_SETP,     1, 3, WINED3DSIH_SETP,         0,                           0                          },
385     {WINED3D_SM1_OP_TEXLDL,   1, 3, WINED3DSIH_TEXLDL,       WINED3D_SHADER_VERSION(3,0), -1                         },
386     {WINED3D_SM1_OP_PHASE,    0, 0, WINED3DSIH_PHASE,        0,                           0                          },
387     {0,                       0, 0, WINED3DSIH_TABLE_SIZE,   0,                           0                          },
388 };
389 
390 static const enum wined3d_shader_resource_type resource_type_table[] =
391 {
392     /* WINED3D_SM1_RESOURCE_UNKNOWN */      WINED3D_SHADER_RESOURCE_NONE,
393     /* WINED3D_SM1_RESOURCE_TEXTURE_1D */   WINED3D_SHADER_RESOURCE_TEXTURE_1D,
394     /* WINED3D_SM1_RESOURCE_TEXTURE_2D */   WINED3D_SHADER_RESOURCE_TEXTURE_2D,
395     /* WINED3D_SM1_RESOURCE_TEXTURE_CUBE */ WINED3D_SHADER_RESOURCE_TEXTURE_CUBE,
396     /* WINED3D_SM1_RESOURCE_TEXTURE_3D */   WINED3D_SHADER_RESOURCE_TEXTURE_3D,
397 };
398 
399 /* Read a parameter opcode from the input stream,
400  * and possibly a relative addressing token.
401  * Return the number of tokens read */
402 static unsigned int shader_get_param(const struct wined3d_sm1_data *priv, const DWORD *ptr,
403         DWORD *token, DWORD *addr_token)
404 {
405     unsigned int count = 1;
406 
407     *token = *ptr;
408 
409     /* PS >= 3.0 have relative addressing (with token)
410      * VS >= 2.0 have relative addressing (with token)
411      * VS >= 1.0 < 2.0 have relative addressing (without token)
412      * The version check below should work in general */
413     if (*ptr & WINED3D_SM1_ADDRESS_MODE_RELATIVE)
414     {
415         if (priv->shader_version.major < 2)
416         {
417             *addr_token = (1u << 31)
418                     | ((WINED3DSPR_ADDR << WINED3D_SM1_REGISTER_TYPE_SHIFT2) & WINED3D_SM1_REGISTER_TYPE_MASK2)
419                     | ((WINED3DSPR_ADDR << WINED3D_SM1_REGISTER_TYPE_SHIFT) & WINED3D_SM1_REGISTER_TYPE_MASK)
420                     | (WINED3DSP_NOSWIZZLE << WINED3D_SM1_SWIZZLE_SHIFT);
421         }
422         else
423         {
424             *addr_token = *(ptr + 1);
425             ++count;
426         }
427     }
428 
429     return count;
430 }
431 
432 static const struct wined3d_sm1_opcode_info *shader_get_opcode(const struct wined3d_sm1_data *priv, DWORD token)
433 {
434     DWORD shader_version = WINED3D_SHADER_VERSION(priv->shader_version.major, priv->shader_version.minor);
435     const struct wined3d_sm1_opcode_info *opcode_table = priv->opcode_table;
436     unsigned int i = 0;
437 
438     while (opcode_table[i].handler_idx != WINED3DSIH_TABLE_SIZE)
439     {
440         if ((token & WINED3D_SM1_OPCODE_MASK) == opcode_table[i].opcode
441                 && shader_version >= opcode_table[i].min_version
442                 && (!opcode_table[i].max_version || shader_version <= opcode_table[i].max_version))
443         {
444             return &opcode_table[i];
445         }
446         ++i;
447     }
448 
449     FIXME("Unsupported opcode %#x, token 0x%08x, shader version %#x.\n",
450             token & WINED3D_SM1_OPCODE_MASK, token, shader_version);
451 
452     return NULL;
453 }
454 
455 /* Return the number of parameters to skip for an opcode */
456 static unsigned int shader_skip_opcode(const struct wined3d_sm1_data *priv,
457         const struct wined3d_sm1_opcode_info *opcode_info, DWORD opcode_token)
458 {
459     unsigned int length;
460     /* Shaders >= 2.0 may contain address tokens, but fortunately they
461      * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
462     length = (opcode_token & WINED3D_SM1_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM1_INSTRUCTION_LENGTH_SHIFT;
463     return (priv->shader_version.major >= 2) ? length : opcode_info->param_count;
464 }
465 
466 static void shader_parse_src_param(DWORD param, const struct wined3d_shader_src_param *rel_addr,
467         struct wined3d_shader_src_param *src)
468 {
469     src->reg.type = ((param & WINED3D_SM1_REGISTER_TYPE_MASK) >> WINED3D_SM1_REGISTER_TYPE_SHIFT)
470             | ((param & WINED3D_SM1_REGISTER_TYPE_MASK2) >> WINED3D_SM1_REGISTER_TYPE_SHIFT2);
471     src->reg.data_type = WINED3D_DATA_FLOAT;
472     src->reg.idx[0].offset = param & WINED3D_SM1_REGISTER_NUMBER_MASK;
473     src->reg.idx[0].rel_addr = rel_addr;
474     src->reg.idx[1].offset = ~0U;
475     src->reg.idx[1].rel_addr = NULL;
476     src->swizzle = (param & WINED3D_SM1_SWIZZLE_MASK) >> WINED3D_SM1_SWIZZLE_SHIFT;
477     src->modifiers = (param & WINED3D_SM1_SRC_MODIFIER_MASK) >> WINED3D_SM1_SRC_MODIFIER_SHIFT;
478 }
479 
480 static void shader_parse_dst_param(DWORD param, const struct wined3d_shader_src_param *rel_addr,
481         struct wined3d_shader_dst_param *dst)
482 {
483     dst->reg.type = ((param & WINED3D_SM1_REGISTER_TYPE_MASK) >> WINED3D_SM1_REGISTER_TYPE_SHIFT)
484             | ((param & WINED3D_SM1_REGISTER_TYPE_MASK2) >> WINED3D_SM1_REGISTER_TYPE_SHIFT2);
485     dst->reg.data_type = WINED3D_DATA_FLOAT;
486     dst->reg.idx[0].offset = param & WINED3D_SM1_REGISTER_NUMBER_MASK;
487     dst->reg.idx[0].rel_addr = rel_addr;
488     dst->reg.idx[1].offset = ~0U;
489     dst->reg.idx[1].rel_addr = NULL;
490     dst->write_mask = (param & WINED3D_SM1_WRITEMASK_MASK) >> WINED3D_SM1_WRITEMASK_SHIFT;
491     dst->modifiers = (param & WINED3D_SM1_DST_MODIFIER_MASK) >> WINED3D_SM1_DST_MODIFIER_SHIFT;
492     dst->shift = (param & WINED3D_SM1_DSTSHIFT_MASK) >> WINED3D_SM1_DSTSHIFT_SHIFT;
493 }
494 
495 /* Read the parameters of an unrecognized opcode from the input stream
496  * Return the number of tokens read.
497  *
498  * Note: This function assumes source or destination token format.
499  * It will not work with specially-formatted tokens like DEF or DCL,
500  * but hopefully those would be recognized */
501 static unsigned int shader_skip_unrecognized(const struct wined3d_sm1_data *priv, const DWORD *ptr)
502 {
503     unsigned int tokens_read = 0, i = 0;
504 
505     /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
506     while (*ptr & 0x80000000)
507     {
508         DWORD token, addr_token = 0;
509         struct wined3d_shader_src_param rel_addr;
510 
511         tokens_read += shader_get_param(priv, ptr, &token, &addr_token);
512         ptr += tokens_read;
513 
514         FIXME("Unrecognized opcode param: token=0x%08x addr_token=0x%08x.\n", token, addr_token);
515 
516         if (token & WINED3D_SM1_ADDRESS_MODE_RELATIVE)
517             shader_parse_src_param(addr_token, NULL, &rel_addr);
518 
519         if (!i)
520         {
521             struct wined3d_shader_dst_param dst;
522 
523             shader_parse_dst_param(token, token & WINED3D_SM1_ADDRESS_MODE_RELATIVE ? &rel_addr : NULL, &dst);
524         }
525         else
526         {
527             struct wined3d_shader_src_param src;
528 
529             shader_parse_src_param(token, token & WINED3D_SM1_ADDRESS_MODE_RELATIVE ? &rel_addr : NULL, &src);
530         }
531         ++i;
532     }
533     return tokens_read;
534 }
535 
536 static void *shader_sm1_init(const DWORD *byte_code, size_t byte_code_size,
537         const struct wined3d_shader_signature *output_signature)
538 {
539     struct wined3d_sm1_data *priv;
540     BYTE major, minor;
541 
542     TRACE("Version: 0x%08x.\n", *byte_code);
543 
544     major = WINED3D_SM1_VERSION_MAJOR(*byte_code);
545     minor = WINED3D_SM1_VERSION_MINOR(*byte_code);
546     if (WINED3D_SHADER_VERSION(major, minor) > WINED3D_SHADER_VERSION(3, 0))
547     {
548         WARN("Invalid shader version %u.%u (%#x).\n", major, minor, *byte_code);
549         return NULL;
550     }
551 
552     if (!(priv = heap_alloc(sizeof(*priv))))
553         return NULL;
554 
555     if (output_signature->element_count)
556         FIXME("SM 1-3 shader shouldn't have output signatures.\n");
557 
558     switch (*byte_code >> 16)
559     {
560         case WINED3D_SM1_VS:
561             priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX;
562             priv->opcode_table = vs_opcode_table;
563             break;
564 
565         case WINED3D_SM1_PS:
566             priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL;
567             priv->opcode_table = ps_opcode_table;
568             break;
569 
570         default:
571             FIXME("Unrecognized shader type %#x.\n", *byte_code >> 16);
572             heap_free(priv);
573             return NULL;
574     }
575     priv->shader_version.major = WINED3D_SM1_VERSION_MAJOR(*byte_code);
576     priv->shader_version.minor = WINED3D_SM1_VERSION_MINOR(*byte_code);
577 
578     priv->start = &byte_code[1];
579 
580     return priv;
581 }
582 
583 static void shader_sm1_free(void *data)
584 {
585     heap_free(data);
586 }
587 
588 static void shader_sm1_read_header(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version)
589 {
590     struct wined3d_sm1_data *priv = data;
591 
592     *ptr = priv->start;
593     *shader_version = priv->shader_version;
594 }
595 
596 static void shader_sm1_read_src_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
597         struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr)
598 {
599     DWORD token, addr_token;
600 
601     *ptr += shader_get_param(priv, *ptr, &token, &addr_token);
602     if (token & WINED3D_SM1_ADDRESS_MODE_RELATIVE)
603     {
604         shader_parse_src_param(addr_token, NULL, src_rel_addr);
605         shader_parse_src_param(token, src_rel_addr, src_param);
606     }
607     else
608     {
609         shader_parse_src_param(token, NULL, src_param);
610     }
611 }
612 
613 static void shader_sm1_read_dst_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
614         struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr)
615 {
616     DWORD token, addr_token;
617 
618     *ptr += shader_get_param(priv, *ptr, &token, &addr_token);
619     if (token & WINED3D_SM1_ADDRESS_MODE_RELATIVE)
620     {
621         shader_parse_src_param(addr_token, NULL, dst_rel_addr);
622         shader_parse_dst_param(token, dst_rel_addr, dst_param);
623     }
624     else
625     {
626         shader_parse_dst_param(token, NULL, dst_param);
627     }
628 }
629 
630 static void shader_sm1_read_semantic(const DWORD **ptr, struct wined3d_shader_semantic *semantic)
631 {
632     enum wined3d_sm1_resource_type resource_type;
633     DWORD usage_token = *(*ptr)++;
634     DWORD dst_token = *(*ptr)++;
635 
636     semantic->usage = (usage_token & WINED3D_SM1_DCL_USAGE_MASK) >> WINED3D_SM1_DCL_USAGE_SHIFT;
637     semantic->usage_idx = (usage_token & WINED3D_SM1_DCL_USAGE_INDEX_MASK) >> WINED3D_SM1_DCL_USAGE_INDEX_SHIFT;
638     resource_type = (usage_token & WINED3D_SM1_RESOURCE_TYPE_MASK) >> WINED3D_SM1_RESOURCE_TYPE_SHIFT;
639     if (resource_type >= ARRAY_SIZE(resource_type_table))
640     {
641         FIXME("Unhandled resource type %#x.\n", resource_type);
642         semantic->resource_type = WINED3D_SHADER_RESOURCE_NONE;
643     }
644     else
645     {
646         semantic->resource_type = resource_type_table[resource_type];
647     }
648     semantic->resource_data_type = WINED3D_DATA_FLOAT;
649     shader_parse_dst_param(dst_token, NULL, &semantic->reg);
650 }
651 
652 static void shader_sm1_read_immconst(const DWORD **ptr, struct wined3d_shader_src_param *src_param,
653         enum wined3d_immconst_type type, enum wined3d_data_type data_type)
654 {
655     unsigned int count = type == WINED3D_IMMCONST_VEC4 ? 4 : 1;
656     src_param->reg.type = WINED3DSPR_IMMCONST;
657     src_param->reg.data_type = data_type;
658     src_param->reg.idx[0].offset = ~0U;
659     src_param->reg.idx[0].rel_addr = NULL;
660     src_param->reg.idx[1].offset = ~0U;
661     src_param->reg.idx[1].rel_addr = NULL;
662     src_param->reg.immconst_type = type;
663     memcpy(src_param->reg.u.immconst_data, *ptr, count * sizeof(DWORD));
664     src_param->swizzle = WINED3DSP_NOSWIZZLE;
665     src_param->modifiers = 0;
666 
667     *ptr += count;
668 }
669 
670 static void shader_sm1_read_comment(const DWORD **ptr)
671 {
672     DWORD token = **ptr;
673     const char *comment;
674     UINT size;
675 
676     while ((token & WINED3D_SM1_OPCODE_MASK) == WINED3D_SM1_OP_COMMENT)
677     {
678         size = (token & WINED3D_SM1_COMMENT_SIZE_MASK) >> WINED3D_SM1_COMMENT_SIZE_SHIFT;
679         comment = (const char *)++(*ptr);
680         *ptr += size;
681 
682         if (size > 1 && *(const DWORD *)comment == WINEMAKEFOURCC('T', 'E', 'X', 'T'))
683         {
684             const char *end = comment + size * sizeof(token);
685             const char *p = comment + sizeof(token);
686             const char *line = p;
687 
688             TRACE("// TEXT\n");
689             while (p != end)
690             {
691                 if (*p == '\n')
692                 {
693                     UINT len = p - line;
694                     if (len && *(p - 1) == '\r') --len;
695                     TRACE("// %s\n", debugstr_an(line, len));
696                     line = ++p;
697                 }
698                 else ++p;
699             }
700             if (line != p)
701                 TRACE("// %s\n", debugstr_an(line, p - line));
702         }
703         else if (size)
704             TRACE("// %s\n", debugstr_an(comment, size * sizeof(token)));
705         else
706             break;
707 
708         token = **ptr;
709     }
710 }
711 
712 static void shader_sm1_validate_instruction(struct wined3d_shader_instruction *ins)
713 {
714     if (ins->handler_idx == WINED3DSIH_BREAKP || ins->handler_idx == WINED3DSIH_IF)
715     {
716         if (ins->flags)
717         {
718             FIXME("Ignoring unexpected instruction flags %#x for %s.\n",
719                     ins->flags, debug_d3dshaderinstructionhandler(ins->handler_idx));
720             ins->flags = 0;
721         }
722     }
723 }
724 
725 static void shader_sm1_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
726 {
727     const struct wined3d_sm1_opcode_info *opcode_info;
728     struct wined3d_sm1_data *priv = data;
729     DWORD opcode_token;
730     unsigned int i;
731     const DWORD *p;
732 
733     shader_sm1_read_comment(ptr);
734 
735     opcode_token = *(*ptr)++;
736     if (!(opcode_info = shader_get_opcode(priv, opcode_token)))
737     {
738         FIXME("Unrecognized opcode: token=0x%08x.\n", opcode_token);
739         ins->handler_idx = WINED3DSIH_TABLE_SIZE;
740         *ptr += shader_skip_unrecognized(priv, *ptr);
741         return;
742     }
743 
744     ins->handler_idx = opcode_info->handler_idx;
745     ins->flags = (opcode_token & WINED3D_SM1_INSTRUCTION_FLAGS_MASK) >> WINED3D_SM1_INSTRUCTION_FLAGS_SHIFT;
746     ins->coissue = opcode_token & WINED3D_SM1_COISSUE;
747     ins->predicate = opcode_token & WINED3D_SM1_INSTRUCTION_PREDICATED ? &priv->pred_param : NULL;
748     ins->dst_count = opcode_info->dst_count ? 1 : 0;
749     ins->dst = &priv->dst_param;
750     ins->src_count = opcode_info->param_count - opcode_info->dst_count;
751     ins->src = priv->src_param;
752     memset(&ins->texel_offset, 0, sizeof(ins->texel_offset));
753 
754     p = *ptr;
755     *ptr += shader_skip_opcode(priv, opcode_info, opcode_token);
756 
757     if (ins->handler_idx == WINED3DSIH_DCL)
758     {
759         shader_sm1_read_semantic(&p, &ins->declaration.semantic);
760     }
761     else if (ins->handler_idx == WINED3DSIH_DEF)
762     {
763         shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
764         shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_VEC4, WINED3D_DATA_FLOAT);
765     }
766     else if (ins->handler_idx == WINED3DSIH_DEFB)
767     {
768         shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
769         shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_SCALAR, WINED3D_DATA_UINT);
770     }
771     else if (ins->handler_idx == WINED3DSIH_DEFI)
772     {
773         shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
774         shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_VEC4, WINED3D_DATA_INT);
775     }
776     else
777     {
778         /* Destination token */
779         if (ins->dst_count)
780             shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
781 
782         /* Predication token */
783         if (ins->predicate)
784             shader_sm1_read_src_param(priv, &p, &priv->pred_param, &priv->pred_rel_addr);
785 
786         /* Other source tokens */
787         for (i = 0; i < ins->src_count; ++i)
788             shader_sm1_read_src_param(priv, &p, &priv->src_param[i], &priv->src_rel_addr[i]);
789     }
790 
791     shader_sm1_validate_instruction(ins);
792 }
793 
794 static BOOL shader_sm1_is_end(void *data, const DWORD **ptr)
795 {
796     shader_sm1_read_comment(ptr);
797 
798     if (**ptr == WINED3D_SM1_END)
799     {
800         ++(*ptr);
801         return TRUE;
802     }
803 
804     return FALSE;
805 }
806 
807 const struct wined3d_shader_frontend sm1_shader_frontend =
808 {
809     shader_sm1_init,
810     shader_sm1_free,
811     shader_sm1_read_header,
812     shader_sm1_read_instruction,
813     shader_sm1_is_end,
814 };
815