nv50: handle TGSI_OPCODE_ROUND
[mesa.git] / src / gallium / drivers / nv50 / nv50_pc_print.c
1 /*
2 * Copyright 2010 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "nv50_context.h"
24 #include "nv50_pc.h"
25
26 #define NVXX_DEBUG 0
27
28 #define PRINT(args...) debug_printf(args)
29
30 #ifndef ARRAY_SIZE
31 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
32 #endif
33
34 static const char *norm = "\x1b[00m";
35 static const char *gree = "\x1b[32m";
36 static const char *blue = "\x1b[34m";
37 static const char *cyan = "\x1b[36m";
38 static const char *orng = "\x1b[33m";
39 static const char *mgta = "\x1b[35m";
40
41 static const char *nv_opcode_names[NV_OP_COUNT + 1] = {
42 "phi",
43 "extract",
44 "combine",
45 "lda",
46 "sta",
47 "mov",
48 "add",
49 "sub",
50 "neg",
51 "mul",
52 "mad",
53 "cvt",
54 "sat",
55 "not",
56 "and",
57 "or",
58 "xor",
59 "shl",
60 "shr",
61 "rcp",
62 "undef",
63 "rsqrt",
64 "lg2",
65 "sin",
66 "cos",
67 "ex2",
68 "presin",
69 "preex2",
70 "min",
71 "max",
72 "set",
73 "sad",
74 "kil",
75 "bra",
76 "call",
77 "ret",
78 "break",
79 "breakaddr",
80 "joinat",
81 "tex",
82 "texbias",
83 "texlod",
84 "texfetch",
85 "texsize",
86 "dfdx",
87 "dfdy",
88 "quadop",
89 "linterp",
90 "pinterp",
91 "abs",
92 "ceil",
93 "floor",
94 "trunc",
95 "nop",
96 "select",
97 "export",
98 "join",
99 "round",
100 "BAD_OP"
101 };
102
103 static const char *nv_cond_names[] =
104 {
105 "never", "lt" , "eq" , "le" , "gt" , "ne" , "ge" , "",
106 "never", "ltu", "equ", "leu", "gtu", "neu", "geu", "",
107 "o", "c", "a", "s"
108 };
109
110 static const char *nv_modifier_strings[] =
111 {
112 "",
113 "neg",
114 "abs",
115 "neg abs",
116 "not",
117 "not neg"
118 "not abs",
119 "not neg abs",
120 "sat",
121 "BAD_MOD"
122 };
123
124 const char *
125 nv_opcode_name(uint opcode)
126 {
127 return nv_opcode_names[MIN2(opcode, ARRAY_SIZE(nv_opcode_names) - 1)];
128 }
129
130 static INLINE const char *
131 nv_type_name(ubyte type)
132 {
133 switch (type) {
134 case NV_TYPE_U16: return "u16";
135 case NV_TYPE_S16: return "s16";
136 case NV_TYPE_F32: return "f32";
137 case NV_TYPE_U32: return "u32";
138 case NV_TYPE_S32: return "s32";
139 case NV_TYPE_P32: return "p32";
140 case NV_TYPE_F64: return "f64";
141 default:
142 return "BAD_TYPE";
143 }
144 }
145
146 static INLINE const char *
147 nv_cond_name(ubyte cc)
148 {
149 return nv_cond_names[MIN2(cc, 19)];
150 }
151
152 static INLINE const char *
153 nv_modifier_string(ubyte mod)
154 {
155 return nv_modifier_strings[MIN2(mod, 9)];
156 }
157
158 static INLINE int
159 nv_value_id(struct nv_value *value)
160 {
161 if (value->join->reg.id >= 0)
162 return value->join->reg.id;
163 return value->n;
164 }
165
166 static INLINE boolean
167 nv_value_allocated(struct nv_value *value)
168 {
169 return (value->reg.id >= 0) ? TRUE : FALSE;
170 }
171
172 static INLINE void
173 nv_print_address(const char c, int buf, struct nv_value *a, int offset)
174 {
175 const char ac = (a && nv_value_allocated(a)) ? '$' : '%';
176
177 if (buf >= 0)
178 PRINT(" %s%c%i[", cyan, c, buf);
179 else
180 PRINT(" %s%c[", cyan, c);
181 if (a)
182 PRINT("%s%ca%i%s+", mgta, ac, nv_value_id(a), cyan);
183 PRINT("%s0x%x%s]", orng, offset, cyan);
184 }
185
186 static INLINE void
187 nv_print_cond(struct nv_instruction *nvi)
188 {
189 char pfx = nv_value_allocated(nvi->flags_src->value->join) ? '$' : '%';
190
191 PRINT("%s%s %s%cc%i ",
192 gree, nv_cond_name(nvi->cc),
193 mgta, pfx, nv_value_id(nvi->flags_src->value));
194 }
195
196 static INLINE void
197 nv_print_value(struct nv_value *value, struct nv_value *ind, ubyte type)
198 {
199 char reg_pfx = '$';
200
201 if (type == NV_TYPE_ANY)
202 type = value->reg.type;
203
204 if (value->reg.file != NV_FILE_FLAGS)
205 PRINT(" %s%s", gree, nv_type_name(type));
206
207 if (!nv_value_allocated(value->join))
208 reg_pfx = '%';
209
210 switch (value->reg.file) {
211 case NV_FILE_GPR:
212 PRINT(" %s%cr%i", blue, reg_pfx, nv_value_id(value));
213 break;
214 case NV_FILE_OUT:
215 PRINT(" %s%co%i", mgta, reg_pfx, nv_value_id(value));
216 break;
217 case NV_FILE_ADDR:
218 PRINT(" %s%ca%i", mgta, reg_pfx, nv_value_id(value));
219 break;
220 case NV_FILE_FLAGS:
221 PRINT(" %s%cc%i", mgta, reg_pfx, nv_value_id(value));
222 break;
223 case NV_FILE_MEM_L:
224 nv_print_address('l', -1, ind, nv_value_id(value));
225 break;
226 case NV_FILE_MEM_S:
227 nv_print_address('s', -1, ind, 4 * nv_value_id(value));
228 break;
229 case NV_FILE_MEM_P:
230 nv_print_address('p', -1, ind, 4 * nv_value_id(value));
231 break;
232 case NV_FILE_MEM_V:
233 nv_print_address('v', -1, ind, 4 * nv_value_id(value));
234 break;
235 case NV_FILE_IMM:
236 switch (type) {
237 case NV_TYPE_U16:
238 case NV_TYPE_S16:
239 PRINT(" %s0x%04x", orng, value->reg.imm.u32);
240 break;
241 case NV_TYPE_F32:
242 PRINT(" %s%f", orng, value->reg.imm.f32);
243 break;
244 case NV_TYPE_F64:
245 PRINT(" %s%f", orng, value->reg.imm.f64);
246 break;
247 case NV_TYPE_U32:
248 case NV_TYPE_S32:
249 case NV_TYPE_P32:
250 PRINT(" %s0x%08x", orng, value->reg.imm.u32);
251 break;
252 }
253 break;
254 default:
255 if (value->reg.file >= NV_FILE_MEM_G(0) &&
256 value->reg.file <= NV_FILE_MEM_G(15))
257 nv_print_address('g', value->reg.file - NV_FILE_MEM_G(0), ind,
258 nv_value_id(value) * 4);
259 else
260 if (value->reg.file >= NV_FILE_MEM_C(0) &&
261 value->reg.file <= NV_FILE_MEM_C(15))
262 nv_print_address('c', value->reg.file - NV_FILE_MEM_C(0), ind,
263 nv_value_id(value) * 4);
264 else
265 NOUVEAU_ERR(" BAD_FILE[%i]", nv_value_id(value));
266 break;
267 }
268 }
269
270 static INLINE void
271 nv_print_ref(struct nv_ref *ref, struct nv_value *ind)
272 {
273 nv_print_value(ref->value, ind, ref->typecast);
274 }
275
276 void
277 nv_print_instruction(struct nv_instruction *i)
278 {
279 int j;
280
281 PRINT("%i: ", i->serial);
282
283 if (i->flags_src)
284 nv_print_cond(i);
285
286 PRINT("%s", gree);
287 if (i->opcode == NV_OP_SET)
288 PRINT("set %s", nv_cond_name(i->set_cond));
289 else
290 if (i->saturate)
291 PRINT("sat %s", nv_opcode_name(i->opcode));
292 else
293 PRINT("%s", nv_opcode_name(i->opcode));
294
295 if (i->flags_def)
296 nv_print_value(i->flags_def, NULL, NV_TYPE_ANY);
297
298 /* Only STORE & STA can write to MEM, and they do not def
299 * anything, so the address is thus part of the source.
300 */
301 if (i->def[0])
302 nv_print_value(i->def[0], NULL, NV_TYPE_ANY);
303 else
304 if (i->target)
305 PRINT(" %s(BB:%i)", orng, i->target->id);
306 else
307 PRINT(" #");
308
309 for (j = 0; j < 4; ++j) {
310 if (!i->src[j])
311 continue;
312
313 if (i->src[j]->mod)
314 PRINT(" %s%s", gree, nv_modifier_string(i->src[j]->mod));
315
316 nv_print_ref(i->src[j],
317 (j == nv50_indirect_opnd(i)) ?
318 i->src[4]->value : NULL);
319 }
320 PRINT(" %s%c\n", norm, i->is_long ? 'l' : 's');
321 }