1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**************************************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2010 Luca Barbieri
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a copy of this software and associated documentation files (the
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sublicense, and/or sell copies of the Software, and to
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * portions of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **************************************************************************/
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "sm4.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "utils.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 1
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define check(x) assert(x)
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define fail(x) assert(0 && (x))
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define check(x) do {if(!(x)) throw(#x);} while(0)
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define fail(x) throw(x)
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct sm4_parser
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned* tokens;
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned* tokens_end;
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	sm4_program& program;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	sm4_parser(sm4_program& program, void* p_tokens, unsigned size)
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	: program(program)
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tokens = (unsigned*)p_tokens;
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tokens_end = (unsigned*)((char*)p_tokens + size);
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* TODO: byteswap if machine is big endian */
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	uint32_t read32()
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		check(tokens < tokens_end);
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return bswap_le32(*tokens++);
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	template<typename T>
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void read_token(T* tok)
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*(unsigned*)tok = read32();
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	uint64_t read64()
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned a = read32();
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned b = read32();
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (uint64_t)a | ((uint64_t)b << 32);
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void skip(unsigned toskip)
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tokens += toskip;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void read_op(sm4_op* pop)
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		sm4_op& op = *pop;
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		sm4_token_operand optok;
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		read_token(&optok);
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		assert(optok.file < SM4_FILE_COUNT);
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.swizzle[0] = 0;
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.swizzle[1] = 1;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.swizzle[2] = 2;
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.swizzle[3] = 3;
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.mask = 0xf;
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		switch(optok.comps_enum)
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case SM4_OPERAND_COMPNUM_0:
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			op.comps = 0;
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case SM4_OPERAND_COMPNUM_1:
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			op.comps = 1;
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = 0;
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case SM4_OPERAND_COMPNUM_4:
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			op.comps = 4;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			op.mode = optok.mode;
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch(optok.mode)
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_MODE_MASK:
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.mask = SM4_OPERAND_SEL_MASK(optok.sel);
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_MODE_SWIZZLE:
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.swizzle[0] = SM4_OPERAND_SEL_SWZ(optok.sel, 0);
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.swizzle[1] = SM4_OPERAND_SEL_SWZ(optok.sel, 1);
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.swizzle[2] = SM4_OPERAND_SEL_SWZ(optok.sel, 2);
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.swizzle[3] = SM4_OPERAND_SEL_SWZ(optok.sel, 3);
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_MODE_SCALAR:
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.swizzle[0] = op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = SM4_OPERAND_SEL_SCALAR(optok.sel);
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case SM4_OPERAND_COMPNUM_N:
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			fail("Unhandled operand component type");
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.file = (sm4_file)optok.file;
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		op.num_indices = optok.num_indices;
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if(optok.extended)
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sm4_token_operand_extended optokext;
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			read_token(&optokext);
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if(optokext.type == 0)
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{}
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if(optokext.type == 1)
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.neg = optokext.neg;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.abs= optokext.abs;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fail("Unhandled extended operand token type");
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(unsigned i = 0; i < op.num_indices; ++i)
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned repr;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if(i == 0)
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				repr = optok.index0_repr;
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if(i == 1)
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				repr = optok.index1_repr;
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if(i == 2)
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				repr = optok.index2_repr;
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fail("Unhandled operand index representation");
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			op.indices[i].disp = 0;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			// TODO: is disp supposed to be signed here??
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch(repr)
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_INDEX_REPR_IMM32:
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.indices[i].disp = (int32_t)read32();
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_INDEX_REPR_IMM64:
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.indices[i].disp = read64();
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_INDEX_REPR_REG:
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgrelative:
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.indices[i].reg.reset(new sm4_op());
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				read_op(&*op.indices[i].reg);
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_INDEX_REPR_REG_IMM32:
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.indices[i].disp = (int32_t)read32();
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				goto relative;
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case SM4_OPERAND_INDEX_REPR_REG_IMM64:
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.indices[i].disp = read64();
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				goto relative;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if(op.file == SM4_FILE_IMMEDIATE32)
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(unsigned i = 0; i < op.comps; ++i)
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.imm_values[i].i32 = read32();
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if(op.file == SM4_FILE_IMMEDIATE64)
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(unsigned i = 0; i < op.comps; ++i)
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				op.imm_values[i].i64 = read64();
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	void do_parse()
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		read_token(&program.version);
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned lentok = read32();
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tokens_end = tokens - 2 + lentok;
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		while(tokens != tokens_end)
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sm4_token_instruction insntok;
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			read_token(&insntok);
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned* insn_end = tokens - 1 + insntok.length;
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sm4_opcode opcode = (sm4_opcode)insntok.opcode;
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			check(opcode < SM4_OPCODE_COUNT);
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if(opcode == SM4_OPCODE_CUSTOMDATA)
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				// immediate constant buffer data
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				unsigned customlen = read32() - 2;
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				sm4_dcl& dcl = *new sm4_dcl;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				program.dcls.push_back(&dcl);
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				dcl.opcode = SM4_OPCODE_CUSTOMDATA;
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				dcl.num = customlen;
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				dcl.data = malloc(customlen * sizeof(tokens[0]));
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				memcpy(dcl.data, &tokens[0], customlen * sizeof(tokens[0]));
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				skip(customlen);
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				continue;
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if(opcode == SM4_OPCODE_HS_FORK_PHASE || opcode == SM4_OPCODE_HS_JOIN_PHASE)
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				// need to interleave these with the declarations or we cannot
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				// assign fork/join phase instance counts to phases
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				sm4_dcl& dcl = *new sm4_dcl;
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				program.dcls.push_back(&dcl);
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				dcl.opcode = opcode;
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if((opcode >= SM4_OPCODE_DCL_RESOURCE && opcode <= SM4_OPCODE_DCL_GLOBAL_FLAGS)
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				|| (opcode >= SM4_OPCODE_DCL_STREAM && opcode <= SM4_OPCODE_DCL_RESOURCE_STRUCTURED))
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				sm4_dcl& dcl = *new sm4_dcl;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				program.dcls.push_back(&dcl);
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				(sm4_token_instruction&)dcl = insntok;
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				sm4_token_instruction_extended exttok;
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				memcpy(&exttok, &insntok, sizeof(exttok));
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				while(exttok.extended)
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				{
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					read_token(&exttok);
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define READ_OP_ANY dcl.op.reset(new sm4_op()); read_op(&*dcl.op);
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define READ_OP(FILE) READ_OP_ANY
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				//check(dcl.op->file == SM4_FILE_##FILE);
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				switch(opcode)
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				{
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_GLOBAL_FLAGS:
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_RESOURCE:
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(RESOURCE);
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					read_token(&dcl.rrt);
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_SAMPLER:
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(SAMPLER);
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT:
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT_PS:
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(INPUT);
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT_SIV:
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT_SGV:
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT_PS_SIV:
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT_PS_SGV:
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(INPUT);
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.sv = (sm4_sv)(uint16_t)read32();
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_OUTPUT:
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(OUTPUT);
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_OUTPUT_SIV:
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_OUTPUT_SGV:
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(OUTPUT);
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.sv = (sm4_sv)(uint16_t)read32();
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INDEX_RANGE:
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP_ANY;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					check(dcl.op->file == SM4_FILE_INPUT || dcl.op->file == SM4_FILE_OUTPUT);
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_TEMPS:
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INDEXABLE_TEMP:
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(INDEXABLE_TEMP);
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.indexable_temp.num = read32();
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.indexable_temp.comps = read32();
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_CONSTANT_BUFFER:
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(CONSTANT_BUFFER);
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_GS_INPUT_PRIMITIVE:
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT:
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_GS_INSTANCE_COUNT:
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT:
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT:
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_TESS_DOMAIN:
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_TESS_PARTITIONING:
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE:
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_HS_MAX_TESSFACTOR:
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.f32 = read32();
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_FUNCTION_BODY:
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_FUNCTION_TABLE:
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.data = malloc(dcl.num * sizeof(uint32_t));
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					for(unsigned i = 0; i < dcl.num; ++i)
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						((uint32_t*)dcl.data)[i] = read32();
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_INTERFACE:
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.intf.id = read32();
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.intf.expected_function_table_length = read32();
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					{
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						uint32_t v = read32();
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						dcl.intf.table_length = v & 0xffff;
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						dcl.intf.array_length = v >> 16;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					}
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.data = malloc(dcl.intf.table_length * sizeof(uint32_t));
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					for(unsigned i = 0; i < dcl.intf.table_length; ++i)
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						((uint32_t*)dcl.data)[i] = read32();
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_THREAD_GROUP:
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.thread_group_size[0] = read32();
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.thread_group_size[1] = read32();
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.thread_group_size[2] = read32();
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED:
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(UNORDERED_ACCESS_VIEW);
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					read_token(&dcl.rrt);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(UNORDERED_ACCESS_VIEW);
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(UNORDERED_ACCESS_VIEW);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.structured.stride = read32();
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW:
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(THREAD_GROUP_SHARED_MEMORY);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.num = read32();
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED:
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(THREAD_GROUP_SHARED_MEMORY);
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.structured.stride = read32();
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.structured.count = read32();
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_RESOURCE_RAW:
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(RESOURCE);
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_RESOURCE_STRUCTURED:
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					READ_OP(RESOURCE);
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					dcl.structured.stride = read32();
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_DCL_STREAM:
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					/* TODO: dcl_stream is undocumented: what is it? */
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fail("Unhandled dcl_stream since it's undocumented");
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				default:
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fail("Unhandled declaration");
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				check(tokens == insn_end);
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			{
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				sm4_insn& insn = *new sm4_insn;
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				program.insns.push_back(&insn);
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				(sm4_token_instruction&)insn = insntok;
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				sm4_token_instruction_extended exttok;
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				memcpy(&exttok, &insntok, sizeof(exttok));
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				while(exttok.extended)
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				{
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					read_token(&exttok);
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_SAMPLE_CONTROLS)
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					{
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.sample_offset[0] = exttok.sample_controls.offset_u;
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.sample_offset[1] = exttok.sample_controls.offset_v;
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.sample_offset[2] = exttok.sample_controls.offset_w;
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					}
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					else if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_DIM)
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.resource_target = exttok.resource_target.target;
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					else if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_RETURN_TYPE)
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					{
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.resource_return_type[0] = exttok.resource_return_type.x;
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.resource_return_type[1] = exttok.resource_return_type.y;
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.resource_return_type[2] = exttok.resource_return_type.z;
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						insn.resource_return_type[3] = exttok.resource_return_type.w;
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					}
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				switch(opcode)
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				{
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case SM4_OPCODE_INTERFACE_CALL:
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					insn.num = read32();
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				default:
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				unsigned op_num = 0;
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				while(tokens != insn_end)
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				{
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					check(tokens < insn_end);
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					check(op_num < SM4_MAX_OPS);
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					insn.ops[op_num].reset(new sm4_op);
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					read_op(&*insn.ops[op_num]);
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					++op_num;
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				insn.num_ops = op_num;
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char* parse()
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		try
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			do_parse();
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return 0;
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		catch(const char* error)
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return error;
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsm4_program* sm4_parse(void* tokens, int size)
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	sm4_program* program = new sm4_program;
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	sm4_parser parser(*program, tokens, size);
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if(!parser.parse())
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return program;
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	delete program;
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 0;
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
446