1 /**************************************************************************
2  *
3  * Copyright 2010 Luca Barbieri
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  **************************************************************************/
26 
27 /* Header for Shader Model 4.0, 4.1 and 5.0 */
28 
29 #ifndef SM4_H_
30 #define SM4_H_
31 
32 #include <stdint.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <memory>
36 #include <vector>
37 #include <map>
38 #include <iostream>
39 #include "le32.h"
40 
41 #include "sm4_defs.h"
42 
43 extern const char* sm4_opcode_names[];
44 extern const char* sm4_file_names[];
45 extern const char* sm4_shortfile_names[];
46 extern const char* sm4_target_names[];
47 extern const char* sm4_interpolation_names[];
48 extern const char* sm4_sv_names[];
49 
50 struct sm4_token_version
51 {
52 	unsigned minor : 4;
53 	unsigned major : 4;
54 	unsigned format : 8;
55 	unsigned type : 16;
56 };
57 
58 struct sm4_token_instruction
59 {
60 	// we don't make it an union directly because unions can't be inherited from
61 	union
62 	{
63 		// length and extended are always present, but they are only here to reduce duplication
64 		struct
65 		{
66 			unsigned opcode : 11;
67 			unsigned _11_23 : 13;
68 			unsigned length : 7;
69 			unsigned extended : 1;
70 		};
71 		struct
72 		{
73 			unsigned opcode : 11;
74 			unsigned resinfo_return_type : 2;
75 			unsigned sat : 1;
76 			unsigned _14_17 : 4;
77 			unsigned test_nz : 1; // bit 18
78 			unsigned precise_mask : 4;
79 			unsigned _23 : 1;
80 			unsigned length : 7;
81 			unsigned extended : 1;
82 		} insn;
83 		struct
84 		{
85 			unsigned opcode : 11;
86 			unsigned threads_in_group : 1;
87 			unsigned shared_memory : 1;
88 			unsigned uav_group : 1;
89 			unsigned uav_global : 1;
90 			unsigned _15_17 : 3;
91 		} sync;
92 		struct
93 		{
94 			unsigned opcode : 11;
95 			unsigned allow_refactoring : 1;
96 			unsigned fp64 : 1;
97 			unsigned early_depth_stencil : 1;
98 			unsigned enable_raw_and_structured_in_non_cs : 1;
99 		} dcl_global_flags;
100 		struct
101 		{
102 			unsigned opcode : 11;
103 			unsigned target : 5;
104 			unsigned nr_samples : 7;
105 		} dcl_resource;
106 		struct
107 		{
108 			unsigned opcode : 11;
109 			unsigned shadow : 1;
110 			unsigned mono : 1;
111 		} dcl_sampler;
112 		struct
113 		{
114 			unsigned opcode : 11;
115 			unsigned interpolation : 5;
116 		} dcl_input_ps;
117 		struct
118 		{
119 			unsigned opcode : 11;
120 			unsigned dynamic : 1;
121 		} dcl_constant_buffer;
122 		struct
123 		{
124 			unsigned opcode : 11;
125 			unsigned primitive : 6;
126 		} dcl_gs_input_primitive;
127 		struct
128 		{
129 			unsigned opcode : 11;
130 			unsigned primitive_topology : 7;
131 		} dcl_gs_output_primitive_topology;
132 		struct
133 		{
134 			unsigned opcode : 11;
135 			unsigned control_points : 6;
136 		} dcl_input_control_point_count;
137 		struct
138 		{
139 			unsigned opcode : 11;
140 			unsigned control_points : 6;
141 		} dcl_output_control_point_count;
142 		struct
143 		{
144 			unsigned opcode : 11;
145 			unsigned domain : 3; /* D3D_TESSELLATOR_DOMAIN */
146 		} dcl_tess_domain;
147 		struct
148 		{
149 			unsigned opcode : 11;
150 			unsigned partitioning : 3; /* D3D_TESSELLATOR_PARTITIONING */
151 		} dcl_tess_partitioning;
152 		struct
153 		{
154 			unsigned opcode : 11;
155 			unsigned primitive : 3; /* D3D_TESSELLATOR_OUTPUT_PRIMITIVE */
156 		} dcl_tess_output_primitive;
157 	};
158 };
159 
160 union sm4_token_instruction_extended
161 {
162 	struct
163 	{
164 		unsigned type : 6;
165 		unsigned _6_30 : 25;
166 		unsigned extended :1;
167 	};
168 	struct
169 	{
170 		unsigned type : 6;
171 		unsigned _6_8 : 3;
172 		int offset_u : 4;
173 		int offset_v : 4;
174 		int offset_w : 4;
175 	} sample_controls;
176 	struct
177 	{
178 		unsigned type : 6;
179 		unsigned target : 5;
180 	} resource_target;
181 	struct
182 	{
183 		unsigned type : 6;
184 		unsigned x : 4;
185 		unsigned y : 4;
186 		unsigned z : 4;
187 		unsigned w : 4;
188 	} resource_return_type;
189 };
190 
191 struct sm4_token_resource_return_type
192 {
193 	unsigned x : 4;
194 	unsigned y : 4;
195 	unsigned z : 4;
196 	unsigned w : 4;
197 };
198 
199 struct sm4_token_operand
200 {
201 	unsigned comps_enum : 2; /* sm4_operands_comps */
202 	unsigned mode : 2; /* sm4_operand_mode */
203 	unsigned sel : 8;
204 	unsigned file : 8; /* sm4_file */
205 	unsigned num_indices : 2;
206 	unsigned index0_repr : 3; /* sm4_operand_index_repr */
207 	unsigned index1_repr : 3; /* sm4_operand_index_repr */
208 	unsigned index2_repr : 3; /* sm4_operand_index_repr */
209 	unsigned extended : 1;
210 };
211 
212 #define SM4_OPERAND_SEL_MASK(sel) ((sel) & 0xf)
213 #define SM4_OPERAND_SEL_SWZ(sel, i) (((sel) >> ((i) * 2)) & 3)
214 #define SM4_OPERAND_SEL_SCALAR(sel) ((sel) & 3)
215 
216 struct sm4_token_operand_extended
217 {
218 	unsigned type : 6;
219 	unsigned neg : 1;
220 	unsigned abs : 1;
221 };
222 
223 union sm4_any
224 {
225 	double f64;
226 	float f32;
227 	int64_t i64;
228 	int32_t i32;
229 	uint64_t u64;
230 	int64_t u32;
231 };
232 
233 struct sm4_op;
234 struct sm4_insn;
235 struct sm4_dcl;
236 struct sm4_program;
237 std::ostream& operator <<(std::ostream& out, const sm4_op& op);
238 std::ostream& operator <<(std::ostream& out, const sm4_insn& op);
239 std::ostream& operator <<(std::ostream& out, const sm4_dcl& op);
240 std::ostream& operator <<(std::ostream& out, const sm4_program& op);
241 
242 struct sm4_op
243 {
244 	uint8_t mode;
245 	uint8_t comps;
246 	uint8_t mask;
247 	uint8_t num_indices;
248 	uint8_t swizzle[4];
249 	sm4_file file;
250 	sm4_any imm_values[4];
251 	bool neg;
252 	bool abs;
253 	struct
254 	{
255 		int64_t disp;
256 		std::auto_ptr<sm4_op> reg;
257 	} indices[3];
258 
is_index_simplesm4_op259 	bool is_index_simple(unsigned i) const
260 	{
261 		 return !indices[i].reg.get() && indices[i].disp >= 0 && (int64_t)(int32_t)indices[i].disp == indices[i].disp;
262 	}
263 
has_simple_indexsm4_op264 	bool has_simple_index() const
265 	{
266 		return num_indices == 1 && is_index_simple(0);
267 	}
268 
sm4_opsm4_op269 	sm4_op()
270 	{
271 		memset(this, 0, sizeof(*this));
272 	}
273 
274 	void dump();
275 
276 private:
sm4_opsm4_op277 	sm4_op(const sm4_op& op)
278 	{}
279 };
280 
281 /* for sample_d */
282 #define SM4_MAX_OPS 6
283 
284 struct sm4_insn : public sm4_token_instruction
285 {
286 	int8_t sample_offset[3];
287 	uint8_t resource_target;
288 	uint8_t resource_return_type[4];
289 
290 	unsigned num;
291 	unsigned num_ops;
292 	std::auto_ptr<sm4_op> ops[SM4_MAX_OPS];
293 
sm4_insnsm4_insn294 	sm4_insn()
295 	{
296 		memset(this, 0, sizeof(*this));
297 	}
298 
299 	void dump();
300 
301 private:
sm4_insnsm4_insn302 	sm4_insn(const sm4_insn& op)
303 	{}
304 };
305 
306 struct sm4_dcl : public sm4_token_instruction
307 {
308 	std::auto_ptr<sm4_op> op;
309 	union
310 	{
311 		unsigned num;
312 		float f32;
313 		sm4_sv sv;
314 		struct
315 		{
316 			unsigned id;
317 			unsigned expected_function_table_length;
318 			unsigned table_length;
319 			unsigned array_length;
320 		} intf;
321 		unsigned thread_group_size[3];
322 		sm4_token_resource_return_type rrt;
323 		struct
324 		{
325 			unsigned num;
326 			unsigned comps;
327 		} indexable_temp;
328 		struct
329 		{
330 			unsigned stride;
331 			unsigned count;
332 		} structured;
333 	};
334 
335 	void* data;
336 
sm4_dclsm4_dcl337 	sm4_dcl()
338 	{
339 		memset(this, 0, sizeof(*this));
340 	}
341 
~sm4_dclsm4_dcl342 	~sm4_dcl()
343 	{
344 		free(data);
345 	}
346 
347 	void dump();
348 
349 private:
sm4_dclsm4_dcl350 	sm4_dcl(const sm4_dcl& op)
351 	{}
352 };
353 
354 struct _D3D11_SIGNATURE_PARAMETER_DESC;
355 
356 struct sm4_program
357 {
358 	sm4_token_version version;
359 	std::vector<sm4_dcl*> dcls;
360 	std::vector<sm4_insn*> insns;
361 
362 	_D3D11_SIGNATURE_PARAMETER_DESC* params_in;
363 	_D3D11_SIGNATURE_PARAMETER_DESC* params_out;
364 	_D3D11_SIGNATURE_PARAMETER_DESC* params_patch;
365 	unsigned num_params_in;
366 	unsigned num_params_out;
367 	unsigned num_params_patch;
368 
369 	/* for ifs, the insn number of the else or endif if there is no else
370 	 * for elses, the insn number of the endif
371 	 * for endifs, the insn number of the if
372 	 * for loops, the insn number of the endloop
373 	 * for endloops, the insn number of the loop
374 	 * for all others, -1
375 	 */
376 	std::vector<int> cf_insn_linked;
377 
378 	bool labels_found;
379 	std::vector<int> label_to_insn_num;
380 
sm4_programsm4_program381 	sm4_program()
382 	{
383 		memset(&version, 0, sizeof(version));
384 		labels_found = false;
385 		num_params_in = num_params_out = num_params_patch = 0;
386 	}
387 
~sm4_programsm4_program388 	~sm4_program()
389 	{
390 		for(std::vector<sm4_dcl*>::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i)
391 			delete *i;
392 		for(std::vector<sm4_insn*>::iterator i = insns.begin(), e = insns.end(); i != e; ++i)
393 			delete *i;
394 
395 		if(num_params_in)
396 			free(params_in);
397 		if(num_params_out)
398 			free(params_out);
399 		if(num_params_patch)
400 			free(params_patch);
401 	}
402 
403 	void dump();
404 
405 private:
sm4_programsm4_program406 	sm4_program(const sm4_dcl& op)
407 	{}
408 };
409 
410 sm4_program* sm4_parse(void* tokens, int size);
411 
412 bool sm4_link_cf_insns(sm4_program& program);
413 bool sm4_find_labels(sm4_program& program);
414 
415 #endif /* SM4_H_ */
416 
417