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
29// TODO: we should fix this to output the same syntax as fxc, if sm4_dump_short_syntax is set
30
31bool sm4_dump_short_syntax = true;
32
33std::ostream& operator <<(std::ostream& out, const sm4_op& op)
34{
35	if(op.neg)
36		out << '-';
37	if(op.abs)
38		out << '|';
39	if(op.file == SM4_FILE_IMMEDIATE32)
40	{
41		out << "l(";
42		for(unsigned i = 0; i < op.comps; ++i)
43		{
44			if(i)
45				out << ", ";
46			out << op.imm_values[i].f32;
47		}
48		out << ")";
49	}
50	else if(op.file == SM4_FILE_IMMEDIATE64)
51	{
52		out << "d(";
53		for(unsigned i = 0; i < op.comps; ++i)
54		{
55			if(i)
56				out << ", ";
57			out << op.imm_values[i].f64;
58		}
59		out << ")";
60		return out;
61	}
62	else
63	{
64		bool naked = false;
65		if(sm4_dump_short_syntax)
66		{
67			switch(op.file)
68			{
69			case SM4_FILE_TEMP:
70			case SM4_FILE_INPUT:
71			case SM4_FILE_OUTPUT:
72			case SM4_FILE_CONSTANT_BUFFER:
73			case SM4_FILE_INDEXABLE_TEMP:
74			case SM4_FILE_UNORDERED_ACCESS_VIEW:
75			case SM4_FILE_THREAD_GROUP_SHARED_MEMORY:
76				naked = true;
77				break;
78			default:
79				naked = false;
80				break;
81			}
82		}
83
84		out << (sm4_dump_short_syntax ? sm4_shortfile_names : sm4_file_names)[op.file];
85
86		if(op.indices[0].reg.get())
87			naked = false;
88
89		for(unsigned i = 0; i < op.num_indices; ++i)
90		{
91			if(!naked || i)
92				out << '[';
93			if(op.indices[i].reg.get())
94			{
95				out << *op.indices[i].reg;
96				if(op.indices[i].disp)
97					out << '+' << op.indices[i].disp;
98			}
99			else
100				out << op.indices[i].disp;
101			if(!naked || i)
102				out << ']';
103		}
104		if(op.comps)
105		{
106			switch(op.mode)
107			{
108			case SM4_OPERAND_MODE_MASK:
109				out << (sm4_dump_short_syntax ? '.' : '!');
110				for(unsigned i = 0; i < op.comps; ++i)
111				{
112					if(op.mask & (1 << i))
113						out << "xyzw"[i];
114				}
115				break;
116			case SM4_OPERAND_MODE_SWIZZLE:
117				out << '.';
118				for(unsigned i = 0; i < op.comps; ++i)
119					out << "xyzw"[op.swizzle[i]];
120				break;
121			case SM4_OPERAND_MODE_SCALAR:
122				out << (sm4_dump_short_syntax ? '.' : ':');
123				out << "xyzw"[op.swizzle[0]];
124				break;
125			}
126		}
127	}
128	if(op.abs)
129		out << '|';
130	return out;
131}
132
133std::ostream& operator <<(std::ostream& out, const sm4_dcl& dcl)
134{
135	out << sm4_opcode_names[dcl.opcode];
136	switch(dcl.opcode)
137	{
138	case SM4_OPCODE_DCL_GLOBAL_FLAGS:
139		if(dcl.dcl_global_flags.allow_refactoring)
140			out << " refactoringAllowed";
141		if(dcl.dcl_global_flags.early_depth_stencil)
142			out << " forceEarlyDepthStencil";
143		if(dcl.dcl_global_flags.fp64)
144			out << " enableDoublePrecisionFloatOps";
145		if(dcl.dcl_global_flags.enable_raw_and_structured_in_non_cs)
146			out << " enableRawAndStructuredBuffers";
147		break;
148	case SM4_OPCODE_DCL_INPUT_PS:
149	case SM4_OPCODE_DCL_INPUT_PS_SIV:
150	case SM4_OPCODE_DCL_INPUT_PS_SGV:
151		out << ' ' << sm4_interpolation_names[dcl.dcl_input_ps.interpolation];
152		break;
153	case SM4_OPCODE_DCL_TEMPS:
154		out << ' ' << dcl.num;
155		break;
156	default:
157		break;
158	}
159	if(dcl.op.get())
160		out << ' ' << *dcl.op;
161	switch(dcl.opcode)
162	{
163	case SM4_OPCODE_DCL_CONSTANT_BUFFER:
164		out << ", " << (dcl.dcl_constant_buffer.dynamic ? "dynamicIndexed" : "immediateIndexed");
165		break;
166	case SM4_OPCODE_DCL_INPUT_SIV:
167	case SM4_OPCODE_DCL_INPUT_SGV:
168	case SM4_OPCODE_DCL_OUTPUT_SIV:
169	case SM4_OPCODE_DCL_OUTPUT_SGV:
170	case SM4_OPCODE_DCL_INPUT_PS_SIV:
171	case SM4_OPCODE_DCL_INPUT_PS_SGV:
172		out << ", " << sm4_sv_names[dcl.num];
173		break;
174	}
175
176	return out;
177}
178
179std::ostream& operator <<(std::ostream& out, const sm4_insn& insn)
180{
181	out << sm4_opcode_names[insn.opcode];
182	if(insn.insn.sat)
183		out << "_sat";
184	for(unsigned i = 0; i < insn.num_ops; ++i)
185	{
186		if(i)
187			out << ',';
188		out << ' ' << *insn.ops[i];
189	}
190	return out;
191}
192
193std::ostream& operator <<(std::ostream& out, const sm4_program& program)
194{
195	out << "pvghdc"[program.version.type] << "s_" << program.version.major << "_" << program.version.minor << "\n";
196	for(unsigned i = 0; i < program.dcls.size(); ++i)
197		out << *program.dcls[i] << "\n";
198
199	for(unsigned i = 0; i < program.insns.size(); ++i)
200		out << *program.insns[i] << "\n";
201	return out;
202}
203
204void sm4_op::dump()
205{
206	std::cout << *this;
207}
208
209void sm4_insn::dump()
210{
211	std::cout << *this;
212}
213
214void sm4_dcl::dump()
215{
216	std::cout << *this;
217}
218
219void sm4_program::dump()
220{
221	std::cout << *this;
222}
223