de4a1e551e24892518b5c56111612c3547eedfa0
[mesa.git] / src / gallium / state_trackers / d3d1x / d3d1xshader / src / sm4_parse.cpp
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 #include "sm4.h"
28 #include "utils.h"
29
30 #if 1
31 #define check(x) assert(x)
32 #define fail(x) assert(0 && (x))
33 #else
34 #define check(x) do {if(!(x)) throw(#x);} while(0)
35 #define fail(x) throw(x)
36 #endif
37
38 struct sm4_parser
39 {
40 unsigned* tokens;
41 unsigned* tokens_end;
42 sm4_program& program;
43
44 sm4_parser(sm4_program& program, void* p_tokens, unsigned size)
45 : program(program)
46 {
47 tokens = (unsigned*)p_tokens;
48 tokens_end = (unsigned*)((char*)p_tokens + size);
49 }
50
51 /* TODO: byteswap if machine is big endian */
52 uint32_t read32()
53 {
54 check(tokens < tokens_end);
55 return bswap_le32(*tokens++);
56 }
57
58 template<typename T>
59 void read_token(T* tok)
60 {
61 *(unsigned*)tok = read32();
62 }
63
64 uint64_t read64()
65 {
66 unsigned a = read32();
67 unsigned b = read32();
68 return (uint64_t)a | ((uint64_t)b << 32);
69 }
70
71 void skip(unsigned toskip)
72 {
73 tokens += toskip;
74 }
75
76 void read_op(sm4_op* pop)
77 {
78 sm4_op& op = *pop;
79 sm4_token_operand optok;
80 read_token(&optok);
81 assert(optok.file < SM4_FILE_COUNT);
82 op.swizzle[0] = 0;
83 op.swizzle[1] = 1;
84 op.swizzle[2] = 2;
85 op.swizzle[3] = 3;
86 op.mask = 0xf;
87 switch(optok.comps_enum)
88 {
89 case SM4_OPERAND_COMPNUM_0:
90 op.comps = 0;
91 break;
92 case SM4_OPERAND_COMPNUM_1:
93 op.comps = 1;
94 op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = 0;
95 break;
96 case SM4_OPERAND_COMPNUM_4:
97 op.comps = 4;
98 op.mode = optok.mode;
99 switch(optok.mode)
100 {
101 case SM4_OPERAND_MODE_MASK:
102 op.mask = SM4_OPERAND_SEL_MASK(optok.sel);
103 break;
104 case SM4_OPERAND_MODE_SWIZZLE:
105 op.swizzle[0] = SM4_OPERAND_SEL_SWZ(optok.sel, 0);
106 op.swizzle[1] = SM4_OPERAND_SEL_SWZ(optok.sel, 1);
107 op.swizzle[2] = SM4_OPERAND_SEL_SWZ(optok.sel, 2);
108 op.swizzle[3] = SM4_OPERAND_SEL_SWZ(optok.sel, 3);
109 break;
110 case SM4_OPERAND_MODE_SCALAR:
111 op.swizzle[0] = op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = SM4_OPERAND_SEL_SCALAR(optok.sel);
112 break;
113 }
114 break;
115 case SM4_OPERAND_COMPNUM_N:
116 fail("Unhandled operand component type");
117 }
118 op.file = (sm4_file)optok.file;
119 op.num_indices = optok.num_indices;
120
121 if(optok.extended)
122 {
123 sm4_token_operand_extended optokext;
124 read_token(&optokext);
125 if(optokext.type == 0)
126 {}
127 else if(optokext.type == 1)
128 {
129 op.neg = optokext.neg;
130 op.abs= optokext.abs;
131 }
132 else
133 fail("Unhandled extended operand token type");
134 }
135
136 for(unsigned i = 0; i < op.num_indices; ++i)
137 {
138 unsigned repr;
139 if(i == 0)
140 repr = optok.index0_repr;
141 else if(i == 1)
142 repr = optok.index1_repr;
143 else if(i == 2)
144 repr = optok.index2_repr;
145 else
146 fail("Unhandled operand index representation");
147 op.indices[0].disp = 0;
148 // TODO: is disp supposed to be signed here??
149 switch(repr)
150 {
151 case SM4_OPERAND_INDEX_REPR_IMM32:
152 op.indices[i].disp = (int32_t)read32();
153 break;
154 case SM4_OPERAND_INDEX_REPR_IMM64:
155 op.indices[i].disp = read64();
156 break;
157 case SM4_OPERAND_INDEX_REPR_REG:
158 relative:
159 op.indices[i].reg.reset(new sm4_op());
160 read_op(&*op.indices[0].reg);
161 break;
162 case SM4_OPERAND_INDEX_REPR_REG_IMM32:
163 op.indices[i].disp = (int32_t)read32();
164 goto relative;
165 case SM4_OPERAND_INDEX_REPR_REG_IMM64:
166 op.indices[i].disp = read64();
167 goto relative;
168 }
169 }
170
171 if(op.file == SM4_FILE_IMMEDIATE32)
172 {
173 for(unsigned i = 0; i < op.comps; ++i)
174 op.imm_values[i].i32 = read32();
175 }
176 else if(op.file == SM4_FILE_IMMEDIATE64)
177 {
178 for(unsigned i = 0; i < op.comps; ++i)
179 op.imm_values[i].i64 = read64();
180 }
181 }
182
183 void do_parse()
184 {
185 read_token(&program.version);
186
187 unsigned lentok = read32();
188 tokens_end = tokens - 2 + lentok;
189
190 while(tokens != tokens_end)
191 {
192 sm4_token_instruction insntok;
193 read_token(&insntok);
194 unsigned* insn_end = tokens - 1 + insntok.length;
195 sm4_opcode opcode = (sm4_opcode)insntok.opcode;
196 check(opcode < SM4_OPCODE_COUNT);
197
198 if(opcode == SM4_OPCODE_CUSTOMDATA)
199 {
200 unsigned customlen = read32() - 2;
201 skip(customlen);
202 continue;
203 }
204
205 if((opcode >= SM4_OPCODE_DCL_RESOURCE && opcode <= SM4_OPCODE_DCL_GLOBAL_FLAGS)
206 || (opcode >= SM4_OPCODE_DCL_STREAM && opcode <= SM4_OPCODE_DCL_RESOURCE_STRUCTURED))
207 {
208 sm4_dcl& dcl = *new sm4_dcl;
209 program.dcls.push_back(&dcl);
210 (sm4_token_instruction&)dcl = insntok;
211
212 sm4_token_instruction_extended exttok;
213 memcpy(&exttok, &insntok, sizeof(exttok));
214 while(exttok.extended)
215 {
216 read_token(&exttok);
217 }
218
219 #define READ_OP_ANY dcl.op.reset(new sm4_op()); read_op(&*dcl.op);
220 #define READ_OP(FILE) READ_OP_ANY
221 //check(dcl.op->file == SM4_FILE_##FILE);
222
223 switch(opcode)
224 {
225 case SM4_OPCODE_DCL_GLOBAL_FLAGS:
226 break;
227 case SM4_OPCODE_DCL_RESOURCE:
228 READ_OP(RESOURCE);
229 read_token(&dcl.rrt);
230 break;
231 case SM4_OPCODE_DCL_SAMPLER:
232 READ_OP(SAMPLER);
233 break;
234 case SM4_OPCODE_DCL_INPUT:
235 case SM4_OPCODE_DCL_INPUT_PS:
236 READ_OP(INPUT);
237 break;
238 case SM4_OPCODE_DCL_INPUT_SIV:
239 case SM4_OPCODE_DCL_INPUT_SGV:
240 case SM4_OPCODE_DCL_INPUT_PS_SIV:
241 case SM4_OPCODE_DCL_INPUT_PS_SGV:
242 READ_OP(INPUT);
243 dcl.sv = (sm4_sv)(uint16_t)read32();
244 break;
245 case SM4_OPCODE_DCL_OUTPUT:
246 READ_OP(OUTPUT);
247 break;
248 case SM4_OPCODE_DCL_OUTPUT_SIV:
249 case SM4_OPCODE_DCL_OUTPUT_SGV:
250 READ_OP(OUTPUT);
251 dcl.sv = (sm4_sv)(uint16_t)read32();
252 break;
253 case SM4_OPCODE_DCL_INDEX_RANGE:
254 READ_OP_ANY;
255 check(dcl.op->file == SM4_FILE_INPUT || dcl.op->file == SM4_FILE_OUTPUT);
256 dcl.num = read32();
257 break;
258 case SM4_OPCODE_DCL_TEMPS:
259 dcl.num = read32();
260 break;
261 case SM4_OPCODE_DCL_INDEXABLE_TEMP:
262 READ_OP(INDEXABLE_TEMP);
263 dcl.indexable_temp.num = read32();
264 dcl.indexable_temp.comps = read32();
265 break;
266 case SM4_OPCODE_DCL_CONSTANT_BUFFER:
267 READ_OP(CONSTANT_BUFFER);
268 break;
269 case SM4_OPCODE_DCL_GS_INPUT_PRIMITIVE:
270 case SM4_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:
271 break;
272 case SM4_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT:
273 dcl.num = read32();
274 break;
275 case SM4_OPCODE_DCL_GS_INSTANCE_COUNT:
276 dcl.num = read32();
277 break;
278 case SM4_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT:
279 case SM4_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT:
280 case SM4_OPCODE_DCL_TESS_DOMAIN:
281 case SM4_OPCODE_DCL_TESS_PARTITIONING:
282 case SM4_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE:
283 break;
284 case SM4_OPCODE_DCL_HS_MAX_TESSFACTOR:
285 dcl.f32 = read32();
286 break;
287 case SM4_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
288 dcl.num = read32();
289 break;
290 case SM4_OPCODE_DCL_FUNCTION_BODY:
291 dcl.num = read32();
292 break;
293 case SM4_OPCODE_DCL_FUNCTION_TABLE:
294 dcl.num = read32();
295 dcl.data = malloc(dcl.num * sizeof(uint32_t));
296 for(unsigned i = 0; i < dcl.num; ++i)
297 ((uint32_t*)dcl.data)[i] = read32();
298 break;
299 case SM4_OPCODE_DCL_INTERFACE:
300 dcl.intf.id = read32();
301 dcl.intf.expected_function_table_length = read32();
302 {
303 uint32_t v = read32();
304 dcl.intf.table_length = v & 0xffff;
305 dcl.intf.array_length = v >> 16;
306 }
307 dcl.data = malloc(dcl.intf.table_length * sizeof(uint32_t));
308 for(unsigned i = 0; i < dcl.intf.table_length; ++i)
309 ((uint32_t*)dcl.data)[i] = read32();
310 break;
311 case SM4_OPCODE_DCL_THREAD_GROUP:
312 dcl.thread_group_size[0] = read32();
313 dcl.thread_group_size[1] = read32();
314 dcl.thread_group_size[2] = read32();
315 break;
316 case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED:
317 READ_OP(UNORDERED_ACCESS_VIEW);
318 read_token(&dcl.rrt);
319 break;
320 case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
321 READ_OP(UNORDERED_ACCESS_VIEW);
322 break;
323 case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
324 READ_OP(UNORDERED_ACCESS_VIEW);
325 dcl.structured.stride = read32();
326 break;
327 case SM4_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW:
328 READ_OP(THREAD_GROUP_SHARED_MEMORY);
329 dcl.num = read32();
330 break;
331 case SM4_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED:
332 READ_OP(THREAD_GROUP_SHARED_MEMORY);
333 dcl.structured.stride = read32();
334 dcl.structured.count = read32();
335 break;
336 case SM4_OPCODE_DCL_RESOURCE_RAW:
337 READ_OP(RESOURCE);
338 break;
339 case SM4_OPCODE_DCL_RESOURCE_STRUCTURED:
340 READ_OP(RESOURCE);
341 dcl.structured.stride = read32();
342 break;
343 case SM4_OPCODE_DCL_STREAM:
344 /* TODO: dcl_stream is undocumented: what is it? */
345 fail("Unhandled dcl_stream since it's undocumented");
346 default:
347 fail("Unhandled declaration");
348 }
349
350 check(tokens == insn_end);
351 }
352 else
353 {
354 sm4_insn& insn = *new sm4_insn;
355 program.insns.push_back(&insn);
356 (sm4_token_instruction&)insn = insntok;
357
358 sm4_token_instruction_extended exttok;
359 memcpy(&exttok, &insntok, sizeof(exttok));
360 while(exttok.extended)
361 {
362 read_token(&exttok);
363 if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_SAMPLE_CONTROLS)
364 {
365 insn.sample_offset[0] = exttok.sample_controls.offset_u;
366 insn.sample_offset[1] = exttok.sample_controls.offset_v;
367 insn.sample_offset[2] = exttok.sample_controls.offset_w;
368 }
369 else if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_DIM)
370 insn.resource_target = exttok.resource_target.target;
371 else if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_RETURN_TYPE)
372 {
373 insn.resource_return_type[0] = exttok.resource_return_type.x;
374 insn.resource_return_type[1] = exttok.resource_return_type.y;
375 insn.resource_return_type[2] = exttok.resource_return_type.z;
376 insn.resource_return_type[3] = exttok.resource_return_type.w;
377 }
378 }
379
380 switch(opcode)
381 {
382 case SM4_OPCODE_INTERFACE_CALL:
383 insn.num = read32();
384 break;
385 default:
386 break;
387 }
388
389 unsigned op_num = 0;
390 while(tokens != insn_end)
391 {
392 check(tokens < insn_end);
393 check(op_num < SM4_MAX_OPS);
394 insn.ops[op_num].reset(new sm4_op);
395 read_op(&*insn.ops[op_num]);
396 ++op_num;
397 }
398 insn.num_ops = op_num;
399 }
400 }
401 }
402
403 const char* parse()
404 {
405 try
406 {
407 do_parse();
408 return 0;
409 }
410 catch(const char* error)
411 {
412 return error;
413 }
414 }
415 };
416
417 sm4_program* sm4_parse(void* tokens, int size)
418 {
419 sm4_program* program = new sm4_program;
420 sm4_parser parser(*program, tokens, size);
421 if(!parser.parse())
422 return program;
423 delete program;
424 return 0;
425 }