2 * Copyright 2010 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
25 #define PRINT(args...) debug_printf(args)
28 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
31 static const char *norm
= "\x1b[00m";
32 static const char *gree
= "\x1b[32m";
33 static const char *blue
= "\x1b[34m";
34 static const char *cyan
= "\x1b[36m";
35 static const char *yllw
= "\x1b[33m";
36 static const char *mgta
= "\x1b[35m";
38 static const char *nv_cond_names
[] =
40 "never", "lt" , "eq" , "le" , "gt" , "ne" , "ge" , "",
41 "never", "ltu", "equ", "leu", "gtu", "neu", "geu", "",
45 static const char *nv_modifier_strings
[] =
60 nvc0_opcode_name(uint opcode
)
62 return nvc0_op_info_table
[MIN2(opcode
, NV_OP_COUNT
)].name
;
65 static INLINE
const char *
66 nv_type_name(ubyte type
, ubyte size
)
69 case NV_TYPE_U16
: return "u16";
70 case NV_TYPE_S16
: return "s16";
71 case NV_TYPE_F32
: return "f32";
72 case NV_TYPE_U32
: return "u32";
73 case NV_TYPE_S32
: return "s32";
74 case NV_TYPE_P32
: return "p32";
75 case NV_TYPE_F64
: return "f64";
83 case 12: return "b96";
84 case 16: return "b128";
94 static INLINE
const char *
95 nv_cond_name(ubyte cc
)
97 return nv_cond_names
[MIN2(cc
, 19)];
100 static INLINE
const char *
101 nv_modifier_string(ubyte mod
)
103 return nv_modifier_strings
[MIN2(mod
, 9)];
107 nv_value_id(struct nv_value
*value
)
109 if (value
->join
->reg
.id
>= 0)
110 return value
->join
->reg
.id
;
114 static INLINE boolean
115 nv_value_allocated(struct nv_value
*value
)
117 return (value
->reg
.id
>= 0) ? TRUE
: FALSE
;
121 nv_print_address(const char c
, int buf
, struct nv_value
*a
, int offset
)
123 const char ac
= (a
&& nv_value_allocated(a
)) ? '$' : '%';
134 PRINT(" %s%c%i[", cyan
, c
, buf
);
136 PRINT(" %s%c[", cyan
, c
);
138 PRINT("%s%ca%i%s%c", mgta
, ac
, nv_value_id(a
), cyan
, sg
);
139 PRINT("%s0x%x%s]", yllw
, offset
, cyan
);
143 nv_print_value(struct nv_value
*value
, struct nv_value
*indir
, ubyte type
)
145 char reg_pfx
= nv_value_allocated(value
->join
) ? '$' : '%';
147 if (value
->reg
.file
!= NV_FILE_PRED
)
148 PRINT(" %s%s", gree
, nv_type_name(type
, value
->reg
.size
));
150 switch (value
->reg
.file
) {
152 PRINT(" %s%cr%i", blue
, reg_pfx
, nv_value_id(value
));
153 if (value
->reg
.size
== 8)
155 if (value
->reg
.size
== 16)
159 PRINT(" %s%cp%i", mgta
, reg_pfx
, nv_value_id(value
));
162 PRINT(" %s%cc%i", mgta
, reg_pfx
, nv_value_id(value
));
165 nv_print_address('l', -1, indir
, value
->reg
.address
);
168 nv_print_address('g', -1, indir
, value
->reg
.address
);
171 nv_print_address('a', -1, indir
, value
->reg
.address
);
174 nv_print_address('v', -1, indir
, value
->reg
.address
);
180 PRINT(" %s0x%04x", yllw
, value
->reg
.imm
.u32
);
183 PRINT(" %s%f", yllw
, value
->reg
.imm
.f32
);
186 PRINT(" %s%f", yllw
, value
->reg
.imm
.f64
);
192 PRINT(" %s0x%08x", yllw
, value
->reg
.imm
.u32
);
197 if (value
->reg
.file
>= NV_FILE_MEM_C(0) &&
198 value
->reg
.file
<= NV_FILE_MEM_C(15))
199 nv_print_address('c', value
->reg
.file
- NV_FILE_MEM_C(0), indir
,
202 NOUVEAU_ERR(" BAD_FILE[%i]", nv_value_id(value
));
208 nv_print_ref(struct nv_ref
*ref
, struct nv_value
*indir
, ubyte type
)
210 nv_print_value(ref
->value
, indir
, type
);
214 nvc0_print_instruction(struct nv_instruction
*i
)
218 PRINT("%i: ", i
->serial
);
220 if (i
->predicate
>= 0) {
221 PRINT("%s%s", gree
, i
->cc
? "fl" : "tr");
222 nv_print_ref(i
->src
[i
->predicate
], NULL
, NV_TYPE_U8
);
227 if (NV_BASEOP(i
->opcode
) == NV_OP_SET
)
228 PRINT("%s %s", nvc0_opcode_name(i
->opcode
), nv_cond_name(i
->set_cond
));
231 PRINT("sat %s", nvc0_opcode_name(i
->opcode
));
233 PRINT("%s", nvc0_opcode_name(i
->opcode
));
235 if (i
->opcode
== NV_OP_CVT
)
236 nv_print_value(i
->def
[0], NULL
, i
->ext
.cvt
.d
);
239 nv_print_value(i
->def
[0], NULL
, NV_OPTYPE(i
->opcode
));
242 PRINT(" %s(BB:%i)", yllw
, i
->target
->id
);
246 for (s
= 1; s
< 4 && i
->def
[s
]; ++s
)
247 nv_print_value(i
->def
[s
], NULL
, NV_OPTYPE(i
->opcode
));
251 for (s
= 0; s
< 6 && i
->src
[s
]; ++s
) {
253 if (s
== i
->indirect
|| s
== i
->predicate
)
255 if (i
->opcode
== NV_OP_CVT
)
258 type
= NV_OPTYPE(i
->opcode
);
261 PRINT(" %s%s", gree
, nv_modifier_string(i
->src
[s
]->mod
));
263 if (i
->indirect
>= 0 &&
264 NV_IS_MEMORY_FILE(i
->src
[s
]->value
->reg
.file
))
265 nv_print_ref(i
->src
[s
], i
->src
[i
->indirect
]->value
, type
);
267 nv_print_ref(i
->src
[s
], NULL
, type
);
269 PRINT(" %s\n", norm
);
272 #define NV_MOD_SGN_12 ((NV_MOD_ABS | NV_MOD_NEG) | ((NV_MOD_ABS | NV_MOD_NEG) << 4))
273 #define NV_MOD_NEG_123 (NV_MOD_NEG | (NV_MOD_NEG << 4) | (NV_MOD_NEG << 8))
274 #define NV_MOD_NEG_3 (NV_MOD_NEG << 8)
276 #define NV_MOD_SGN NV_MOD_SGN_12
278 struct nv_op_info nvc0_op_info_table
[NV_OP_COUNT
+ 1] =
280 { NV_OP_UNDEF
, "undef", NV_TYPE_ANY
, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 },
281 { NV_OP_BIND
, "bind", NV_TYPE_ANY
, 0, /* fcvpoi */ 0, 0, 1, 0, 1, 0, 0 },
282 { NV_OP_MERGE
, "merge", NV_TYPE_ANY
, 0, /* fcvpoi */ 0, 0, 1, 0, 1, 0, 0 },
283 { NV_OP_PHI
, "phi", NV_TYPE_ANY
, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 },
284 { NV_OP_SELECT
, "select", NV_TYPE_ANY
, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 },
285 { NV_OP_NOP
, "nop", NV_TYPE_ANY
, 0, /* fcvpoi */ 0, 0, 0, 1, 0, 0, 0 },
287 { NV_OP_LD
, "ld", NV_TYPE_ANY
, 0, 0, 0, 0, 1, 0, 0, 0 },
288 { NV_OP_ST
, "st", NV_TYPE_ANY
, 0, 0, 0, 0, 1, 0, 0, 0 },
289 { NV_OP_MOV
, "mov", NV_TYPE_ANY
, 0, 0, 0, 0, 1, 0, 1, 0 },
290 { NV_OP_AND
, "and", NV_TYPE_U32
, NV_MOD_NOT
, 0, 1, 0, 1, 0, 6, 0 },
291 { NV_OP_OR
, "or", NV_TYPE_U32
, NV_MOD_NOT
, 0, 1, 0, 1, 0, 6, 0 },
292 { NV_OP_XOR
, "xor", NV_TYPE_U32
, NV_MOD_NOT
, 0, 1, 0, 1, 0, 6, 0 },
293 { NV_OP_SHL
, "shl", NV_TYPE_U32
, 0, 0, 0, 0, 1, 0, 1, 0 },
294 { NV_OP_SHR
, "shr", NV_TYPE_U32
, 0, 0, 0, 0, 1, 0, 1, 0 },
295 { NV_OP_NOT
, "not", NV_TYPE_U32
, 0, 0, 0, 0, 1, 0, 0, 0 },
296 { NV_OP_SET
, "set", NV_TYPE_ANY
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
297 { NV_OP_ADD
, "add", NV_TYPE_F32
, NV_MOD_SGN
, 0, 1, 0, 1, 0, 2, 2 },
298 { NV_OP_SUB
, "sub", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 2, 2 },
299 { NV_OP_MUL
, "mul", NV_TYPE_F32
, NV_MOD_NEG_123
, 0, 1, 0, 1, 0, 2, 2 },
300 { NV_OP_MAD
, "mad", NV_TYPE_F32
, NV_MOD_NEG_123
, 0, 1, 0, 1, 0, 2, 2 },
301 { NV_OP_ABS
, "abs", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
302 { NV_OP_NEG
, "neg", NV_TYPE_F32
, NV_MOD_ABS
, 0, 0, 0, 1, 0, 0, 0 },
303 { NV_OP_MAX
, "max", NV_TYPE_F32
, NV_MOD_SGN
, 0, 1, 0, 1, 0, 2, 2 },
304 { NV_OP_MIN
, "min", NV_TYPE_F32
, NV_MOD_SGN
, 0, 1, 0, 1, 0, 2, 2 },
305 { NV_OP_CVT
, "cvt", NV_TYPE_ANY
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
307 { NV_OP_CEIL
, "ceil", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
308 { NV_OP_FLOOR
, "floor", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
309 { NV_OP_TRUNC
, "trunc", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
311 { NV_OP_SAD
, "sad", NV_TYPE_S32
, 0, 0, 1, 0, 1, 0, 0, 0 },
313 { NV_OP_VFETCH
, "vfetch", NV_TYPE_ANY
, 0, 0, 0, 1, 1, 0, 0, 0 },
314 { NV_OP_PFETCH
, "pfetch", NV_TYPE_U32
, 0, 0, 0, 0, 1, 0, 0, 0 },
315 { NV_OP_EXPORT
, "export", NV_TYPE_ANY
, 0, 0, 0, 1, 1, 0, 0, 0 },
316 { NV_OP_LINTERP
, "linterp", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
317 { NV_OP_PINTERP
, "pinterp", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
318 { NV_OP_EMIT
, "emit", NV_TYPE_ANY
, 0, 0, 0, 0, 1, 0, 0, 0 },
319 { NV_OP_RESTART
, "restart", NV_TYPE_ANY
, 0, 0, 0, 0, 1, 0, 0, 0 },
321 { NV_OP_TEX
, "tex", NV_TYPE_F32
, 0, 0, 0, 1, 1, 0, 0, 0 },
322 { NV_OP_TXB
, "texbias", NV_TYPE_F32
, 0, 0, 0, 1, 1, 0, 0, 0 },
323 { NV_OP_TXL
, "texlod", NV_TYPE_F32
, 0, 0, 0, 1, 1, 0, 0, 0 },
324 { NV_OP_TXF
, "texfetch", NV_TYPE_U32
, 0, 0, 0, 1, 1, 0, 0, 0 },
325 { NV_OP_TXQ
, "texquery", NV_TYPE_U32
, 0, 0, 0, 1, 1, 0, 0, 0 },
327 { NV_OP_QUADOP
, "quadop", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
328 { NV_OP_DFDX
, "dfdx", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
329 { NV_OP_DFDY
, "dfdy", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
331 { NV_OP_KIL
, "kil", NV_TYPE_ANY
, 0, 0, 0, 0, 1, 0, 0, 0 },
332 { NV_OP_BRA
, "bra", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
333 { NV_OP_CALL
, "call", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
334 { NV_OP_RET
, "ret", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
335 { NV_OP_RET
, "exit", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
336 { NV_OP_NOP
, "ud", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
337 { NV_OP_NOP
, "ud", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
339 { NV_OP_JOINAT
, "joinat", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
340 { NV_OP_JOIN
, "join", NV_TYPE_ANY
, 0, 1, 0, 0, 1, 0, 0, 0 },
342 { NV_OP_ADD
, "add", NV_TYPE_S32
, 0, 0, 1, 0, 1, 0, 1, 0 },
343 { NV_OP_MUL
, "mul", NV_TYPE_S32
, 0, 0, 1, 0, 1, 0, 1, 0 },
344 { NV_OP_ABS
, "abs", NV_TYPE_S32
, 0, 0, 0, 0, 1, 0, 0, 0 },
345 { NV_OP_NEG
, "neg", NV_TYPE_S32
, 0, 0, 0, 0, 1, 0, 0, 0 },
346 { NV_OP_MAX
, "max", NV_TYPE_S32
, 0, 0, 1, 0, 1, 0, 0, 0 },
347 { NV_OP_MIN
, "max", NV_TYPE_U32
, 0, 0, 1, 0, 1, 0, 0, 0 },
348 { NV_OP_MAX
, "min", NV_TYPE_S32
, 0, 0, 1, 0, 1, 0, 0, 0 },
349 { NV_OP_MIN
, "min", NV_TYPE_U32
, 0, 0, 1, 0, 1, 0, 0, 0 },
350 { NV_OP_SET
, "set", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 2, 2 },
351 { NV_OP_SET
, "set", NV_TYPE_S32
, 0, 0, 0, 0, 1, 0, 2, 2 },
352 { NV_OP_SET
, "set", NV_TYPE_U32
, 0, 0, 0, 0, 1, 0, 2, 2 },
353 { NV_OP_SHR
, "sar", NV_TYPE_S32
, 0, 0, 0, 0, 1, 0, 1, 0 },
354 { NV_OP_RCP
, "rcp", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
355 { NV_OP_RSQ
, "rsqrt", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
356 { NV_OP_LG2
, "lg2", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 0 },
357 { NV_OP_SIN
, "sin", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
358 { NV_OP_COS
, "cos", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
359 { NV_OP_EX2
, "ex2", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
360 { NV_OP_PRESIN
, "presin", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 1 },
361 { NV_OP_PREEX2
, "preex2", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 0, 1 },
362 { NV_OP_SAT
, "sat", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
364 { NV_OP_SET_F32_AND
, "and set", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
365 { NV_OP_SET_F32_OR
, "or set", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
366 { NV_OP_SET_F32_XOR
, "xor set", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 0, 0 },
368 { NV_OP_SELP
, "selp", NV_TYPE_U32
, 0, 0, 0, 0, 1, 0, 0, 0 },
370 { NV_OP_SLCT
, "slct", NV_TYPE_F32
, NV_MOD_NEG_3
, 0, 0, 0, 1, 0, 2, 2 },
371 { NV_OP_SLCT
, "slct", NV_TYPE_S32
, NV_MOD_NEG_3
, 0, 0, 0, 1, 0, 2, 2 },
372 { NV_OP_SLCT
, "slct", NV_TYPE_U32
, NV_MOD_NEG_3
, 0, 0, 0, 1, 0, 2, 2 },
374 { NV_OP_ADD
, "sub", NV_TYPE_F32
, 0, 0, 0, 0, 1, 0, 1, 0 },
376 { NV_OP_SET
, "fset", NV_TYPE_F32
, NV_MOD_SGN
, 0, 0, 0, 1, 0, 2, 2 },
378 { NV_OP_TXG
, "texgrad", NV_TYPE_F32
, 0, 0, 0, 1, 1, 0, 0, 0 },
380 { NV_OP_UNDEF
, "BAD_OP", NV_TYPE_ANY
, 0, 0, 0, 0, 0, 0, 0, 0 }