diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2007-08-09 11:18:27 +0100 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2007-08-09 11:23:18 +0100 |
commit | c046174eb047c95e25f31390019f04f310ae2b8e (patch) | |
tree | 95b252e771a972459dac347cbebda9aad0d605cc /src/mesa/pipe/i915simple | |
parent | 9526f7445e9acea8553769bf8f86e3c95655cca1 (diff) |
Pull in debug code for human-readable batchbuffer dumps.
Diffstat (limited to 'src/mesa/pipe/i915simple')
-rw-r--r-- | src/mesa/pipe/i915simple/i915_debug.c | 610 | ||||
-rw-r--r-- | src/mesa/pipe/i915simple/i915_debug.h | 17 | ||||
-rw-r--r-- | src/mesa/pipe/i915simple/i915_debug_fp.c | 331 |
3 files changed, 704 insertions, 254 deletions
diff --git a/src/mesa/pipe/i915simple/i915_debug.c b/src/mesa/pipe/i915simple/i915_debug.c index 8d80590396..0951319d38 100644 --- a/src/mesa/pipe/i915simple/i915_debug.c +++ b/src/mesa/pipe/i915simple/i915_debug.c @@ -25,313 +25,415 @@ * **************************************************************************/ -#include <stdio.h> -#include <assert.h> +#include "imports.h" #include "i915_reg.h" +#include "i915_context.h" #include "i915_debug.h" -static const char *opcodes[0x20] = { - "NOP", - "ADD", - "MOV", - "MUL", - "MAD", - "DP2ADD", - "DP3", - "DP4", - "FRC", - "RCP", - "RSQ", - "EXP", - "LOG", - "CMP", - "MIN", - "MAX", - "FLR", - "MOD", - "TRC", - "SGE", - "SLT", - "TEXLD", - "TEXLDP", - "TEXLDB", - "TEXKILL", - "DCL", - "0x1a", - "0x1b", - "0x1c", - "0x1d", - "0x1e", - "0x1f", -}; - - -static const int args[0x20] = { - 0, /* 0 nop */ - 2, /* 1 add */ - 1, /* 2 mov */ - 2, /* 3 m ul */ - 3, /* 4 mad */ - 3, /* 5 dp2add */ - 2, /* 6 dp3 */ - 2, /* 7 dp4 */ - 1, /* 8 frc */ - 1, /* 9 rcp */ - 1, /* a rsq */ - 1, /* b exp */ - 1, /* c log */ - 3, /* d cmp */ - 2, /* e min */ - 2, /* f max */ - 1, /* 10 flr */ - 1, /* 11 mod */ - 1, /* 12 trc */ - 2, /* 13 sge */ - 2, /* 14 slt */ - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -}; - - -static const char *regname[0x8] = { - "R", - "T", - "CONST", - "S", - "OC", - "OD", - "U", - "UNKNOWN", -}; - -static void -print_reg_type_nr(unsigned type, unsigned nr) +static GLboolean debug( struct debug_stream *stream, const char *name, GLuint len ) { - switch (type) { - case REG_TYPE_T: - switch (nr) { - case T_DIFFUSE: - fprintf(stderr, "T_DIFFUSE"); - return; - case T_SPECULAR: - fprintf(stderr, "T_SPECULAR"); - return; - case T_FOG_W: - fprintf(stderr, "T_FOG_W"); - return; - default: - fprintf(stderr, "T_TEX%d", nr); - return; - } - case REG_TYPE_OC: - if (nr == 0) { - fprintf(stderr, "oC"); - return; - } - break; - case REG_TYPE_OD: - if (nr == 0) { - fprintf(stderr, "oD"); - return; - } - break; - default: - break; + GLuint i; + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + + if (len == 0) { + _mesa_printf("Error - zero length packet (0x%08x)\n", stream->ptr[0]); + assert(0); + return GL_FALSE; } - fprintf(stderr, "%s[%d]", regname[type], nr); -} + if (stream->print_addresses) + _mesa_printf("%08x: ", stream->offset); + -#define REG_SWIZZLE_MASK 0x7777 -#define REG_NEGATE_MASK 0x8888 + _mesa_printf("%s (%d dwords):\n", name, len); + for (i = 0; i < len; i++) + _mesa_printf("\t\t0x%08x\n", ptr[i]); + _mesa_printf("\n"); -#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ - (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ - (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ - (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) + stream->offset += len * sizeof(GLuint); + + return GL_TRUE; +} -static void -print_reg_neg_swizzle(unsigned reg) +static const char *get_prim_name( GLuint val ) { - int i; - - if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && - (reg & REG_NEGATE_MASK) == 0) - return; - - fprintf(stderr, "."); - - for (i = 3; i >= 0; i--) { - if (reg & (1 << ((i * 4) + 3))) - fprintf(stderr, "-"); - - switch ((reg >> (i * 4)) & 0x7) { - case 0: - fprintf(stderr, "x"); - break; - case 1: - fprintf(stderr, "y"); - break; - case 2: - fprintf(stderr, "z"); - break; - case 3: - fprintf(stderr, "w"); - break; - case 4: - fprintf(stderr, "0"); - break; - case 5: - fprintf(stderr, "1"); - break; - default: - fprintf(stderr, "?"); - break; - } + switch (val & PRIM3D_MASK) { + case PRIM3D_TRILIST: return "TRILIST"; break; + case PRIM3D_TRISTRIP: return "TRISTRIP"; break; + case PRIM3D_TRISTRIP_RVRSE: return "TRISTRIP_RVRSE"; break; + case PRIM3D_TRIFAN: return "TRIFAN"; break; + case PRIM3D_POLY: return "POLY"; break; + case PRIM3D_LINELIST: return "LINELIST"; break; + case PRIM3D_LINESTRIP: return "LINESTRIP"; break; + case PRIM3D_RECTLIST: return "RECTLIST"; break; + case PRIM3D_POINTLIST: return "POINTLIST"; break; + case PRIM3D_DIB: return "DIB"; break; + case PRIM3D_CLEAR_RECT: return "CLEAR_RECT"; break; + case PRIM3D_ZONE_INIT: return "ZONE_INIT"; break; + default: return "????"; break; } } - -static void -print_src_reg(unsigned dword) +static GLboolean debug_prim( struct debug_stream *stream, const char *name, + GLboolean dump_floats, + GLuint len ) { - unsigned nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; - unsigned type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; - print_reg_type_nr(type, nr); - print_reg_neg_swizzle(dword); + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + const char *prim = get_prim_name( ptr[0] ); + GLuint i; + + + + _mesa_printf("%s %s (%d dwords):\n", name, prim, len); + _mesa_printf("\t\t0x%08x\n", ptr[0]); + for (i = 1; i < len; i++) { + if (dump_floats) + _mesa_printf("\t\t0x%08x // %f\n", ptr[i], *(GLfloat *)&ptr[i]); + else + _mesa_printf("\t\t0x%08x\n", ptr[i]); + } + + + _mesa_printf("\n"); + + stream->offset += len * sizeof(GLuint); + + return GL_TRUE; } + -void -i915_print_ureg(const char *msg, unsigned ureg) + + +static GLboolean debug_program( struct debug_stream *stream, const char *name, GLuint len ) { - fprintf(stderr, "%s: ", msg); - print_src_reg(ureg >> 8); - fprintf(stderr, "\n"); + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + + if (len == 0) { + _mesa_printf("Error - zero length packet (0x%08x)\n", stream->ptr[0]); + assert(0); + return GL_FALSE; + } + + if (stream->print_addresses) + _mesa_printf("%08x: ", stream->offset); + + _mesa_printf("%s (%d dwords):\n", name, len); + i915_disassemble_program( ptr, len ); + + stream->offset += len * sizeof(GLuint); + return GL_TRUE; } -static void -print_dest_reg(unsigned dword) + +static GLboolean debug_chain( struct debug_stream *stream, const char *name, GLuint len ) { - unsigned nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; - unsigned type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; - print_reg_type_nr(type, nr); - if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) - return; - fprintf(stderr, "."); - if (dword & A0_DEST_CHANNEL_X) - fprintf(stderr, "x"); - if (dword & A0_DEST_CHANNEL_Y) - fprintf(stderr, "y"); - if (dword & A0_DEST_CHANNEL_Z) - fprintf(stderr, "z"); - if (dword & A0_DEST_CHANNEL_W) - fprintf(stderr, "w"); -} + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + GLuint old_offset = stream->offset + len * sizeof(GLuint); + GLuint i; + + _mesa_printf("%s (%d dwords):\n", name, len); + for (i = 0; i < len; i++) + _mesa_printf("\t\t0x%08x\n", ptr[i]); + stream->offset = ptr[1] & ~0x3; + + if (stream->offset < old_offset) + _mesa_printf("\n... skipping backwards from 0x%x --> 0x%x ...\n\n", + old_offset, stream->offset ); + else + _mesa_printf("\n... skipping from 0x%x --> 0x%x ...\n\n", + old_offset, stream->offset ); -#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) -#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) -#define GET_SRC2_REG(r) (r) + + return GL_TRUE; +} -static void -print_arith_op(unsigned opcode, const unsigned * program) +static GLboolean debug_variable_length_prim( struct debug_stream *stream ) { - if (opcode != A0_NOP) { - print_dest_reg(program[0]); - if (program[0] & A0_DEST_SATURATE) - fprintf(stderr, " = SATURATE "); - else - fprintf(stderr, " = "); - } + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + const char *prim = get_prim_name( ptr[0] ); + GLuint i, len; - fprintf(stderr, "%s ", opcodes[opcode]); + GLushort *idx = (GLushort *)(ptr+1); + for (i = 0; idx[i] != 0xffff; i++) + ; - print_src_reg(GET_SRC0_REG(program[0], program[1])); - if (args[opcode] == 1) { - fprintf(stderr, "\n"); - return; - } + len = 1+(i+2)/2; - fprintf(stderr, ", "); - print_src_reg(GET_SRC1_REG(program[1], program[2])); - if (args[opcode] == 2) { - fprintf(stderr, "\n"); - return; + _mesa_printf("3DPRIM, %s variable length %d indicies (%d dwords):\n", prim, i, len); + for (i = 0; i < len; i++) + _mesa_printf("\t\t0x%08x\n", ptr[i]); + _mesa_printf("\n"); + + stream->offset += len * sizeof(GLuint); + return GL_TRUE; +} + + +static GLboolean debug_load_immediate( struct debug_stream *stream, + const char *name, + GLuint len ) +{ + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + GLuint bits = (ptr[0] >> 4) & 0xff; + GLuint i, j = 0; + + _mesa_printf("%s (%d dwords, flags: %x):\n", name, len, bits); + _mesa_printf("\t\t0x%08x\n", ptr[j++]); + + for (i = 0; i < 8; i++) { + if (bits & (1<<i)) { + _mesa_printf("\t LIS%d: 0x%08x\n", i, ptr[j++]); + } } - fprintf(stderr, ", "); - print_src_reg(GET_SRC2_REG(program[2])); - fprintf(stderr, "\n"); - return; + _mesa_printf("\n"); + + assert(j == len); + + stream->offset += len * sizeof(GLuint); + + return GL_TRUE; } + -static void -print_tex_op(unsigned opcode, const unsigned * program) +static GLboolean debug_load_indirect( struct debug_stream *stream, + const char *name, + GLuint len ) { - print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); - fprintf(stderr, " = "); + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + GLuint bits = (ptr[0] >> 8) & 0x3f; + GLuint i, j = 0; + + _mesa_printf("%s (%d dwords):\n", name, len); + _mesa_printf("\t\t0x%08x\n", ptr[j++]); + + for (i = 0; i < 6; i++) { + if (bits & (1<<i)) { + switch (1<<(8+i)) { + case LI0_STATE_STATIC_INDIRECT: + _mesa_printf(" STATIC: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; + _mesa_printf(" 0x%08x\n", ptr[j++]); + break; + case LI0_STATE_DYNAMIC_INDIRECT: + _mesa_printf(" DYNAMIC: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; + break; + case LI0_STATE_SAMPLER: + _mesa_printf(" SAMPLER: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; + _mesa_printf(" 0x%08x\n", ptr[j++]); + break; + case LI0_STATE_MAP: + _mesa_printf(" MAP: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; + _mesa_printf(" 0x%08x\n", ptr[j++]); + break; + case LI0_STATE_PROGRAM: + _mesa_printf(" PROGRAM: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; + _mesa_printf(" 0x%08x\n", ptr[j++]); + break; + case LI0_STATE_CONSTANTS: + _mesa_printf(" CONSTANTS: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; + _mesa_printf(" 0x%08x\n", ptr[j++]); + break; + default: + assert(0); + break; + } + } + } - fprintf(stderr, "%s ", opcodes[opcode]); + if (bits == 0) { + _mesa_printf("\t DUMMY: 0x%08x\n", ptr[j++]); + } - fprintf(stderr, "S[%d],", program[0] & T0_SAMPLER_NR_MASK); + _mesa_printf("\n"); - print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & - REG_TYPE_MASK, - (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); - fprintf(stderr, "\n"); + + assert(j == len); + + stream->offset += len * sizeof(GLuint); + + return GL_TRUE; } + -static void -print_dcl_op(unsigned opcode, const unsigned * program) +static GLboolean i915_debug_packet( struct debug_stream *stream ) { - fprintf(stderr, "%s ", opcodes[opcode]); - print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); - fprintf(stderr, "\n"); + GLuint *ptr = (GLuint *)(stream->ptr + stream->offset); + GLuint cmd = *ptr; + + switch (((cmd >> 29) & 0x7)) { + case 0x0: + switch ((cmd >> 23) & 0x3f) { + case 0x0: + return debug(stream, "MI_NOOP", 1); + case 0x3: + return debug(stream, "MI_WAIT_FOR_EVENT", 1); + case 0x4: + return debug(stream, "MI_FLUSH", 1); + case 0xA: + debug(stream, "MI_BATCH_BUFFER_END", 1); + return GL_FALSE; + case 0x22: + return debug(stream, "MI_LOAD_REGISTER_IMM", 3); + case 0x31: + return debug_chain(stream, "MI_BATCH_BUFFER_START", 2); + default: + break; + } + break; + case 0x1: + break; + case 0x2: + switch ((cmd >> 22) & 0xff) { + case 0x50: + return debug(stream, "XY_COLOR_BLT", (cmd & 0xff) + 2); + case 0x53: + return debug(stream, "XY_SRC_COPY_BLT", (cmd & 0xff) + 2); + default: + return debug(stream, "blit command", (cmd & 0xff) + 2); + } + break; + case 0x3: + switch ((cmd >> 24) & 0x1f) { + case 0x6: + return debug(stream, "3DSTATE_ANTI_ALIASING", 1); + case 0x7: + return debug(stream, "3DSTATE_RASTERIZATION_RULES", 1); + case 0x8: + return debug(stream, "3DSTATE_BACKFACE_STENCIL_OPS", 2); + case 0x9: + return debug(stream, "3DSTATE_BACKFACE_STENCIL_MASKS", 1); + case 0xb: + return debug(stream, "3DSTATE_INDEPENDENT_ALPHA_BLEND", 1); + case 0xc: + return debug(stream, "3DSTATE_MODES5", 1); + case 0xd: + return debug(stream, "3DSTATE_MODES4", 1); + case 0x15: + return debug(stream, "3DSTATE_FOG_COLOR", 1); + case 0x16: + return debug(stream, "3DSTATE_COORD_SET_BINDINGS", 1); + case 0x1c: + /* 3DState16NP */ + switch((cmd >> 19) & 0x1f) { + case 0x10: + return debug(stream, "3DSTATE_SCISSOR_ENABLE", 1); + case 0x11: + return debug(stream, "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE", 1); + default: + break; + } + break; + case 0x1d: + /* 3DStateMW */ + switch ((cmd >> 16) & 0xff) { + case 0x0: + return debug(stream, "3DSTATE_MAP_STATE", (cmd & 0x1f) + 2); + case 0x1: + return debug(stream, "3DSTATE_SAMPLER_STATE", (cmd & 0x1f) + 2); + case 0x4: + return debug_load_immediate(stream, "3DSTATE_LOAD_STATE_IMMEDIATE", (cmd & 0xf) + 2); + case 0x5: + return debug_program(stream, "3DSTATE_PIXEL_SHADER_PROGRAM", (cmd & 0x1ff) + 2); + case 0x6: + return debug(stream, "3DSTATE_PIXEL_SHADER_CONSTANTS", (cmd & 0xff) + 2); + case 0x7: + return debug_load_indirect(stream, "3DSTATE_LOAD_INDIRECT", (cmd & 0xff) + 2); + case 0x80: + return debug(stream, "3DSTATE_DRAWING_RECTANGLE", (cmd & 0xffff) + 2); + case 0x81: + return debug(stream, "3DSTATE_SCISSOR_RECTANGLE", (cmd & 0xffff) + 2); + case 0x83: + return debug(stream, "3DSTATE_SPAN_STIPPLE", (cmd & 0xffff) + 2); + case 0x85: + return debug(stream, "3DSTATE_DEST_BUFFER_VARS", (cmd & 0xffff) + 2); + case 0x88: + return debug(stream, "3DSTATE_CONSTANT_BLEND_COLOR", (cmd & 0xffff) + 2); + case 0x89: + return debug(stream, "3DSTATE_FOG_MODE", (cmd & 0xffff) + 2); + case 0x8e: + return debug(stream, "3DSTATE_BUFFER_INFO", (cmd & 0xffff) + 2); + case 0x97: + return debug(stream, "3DSTATE_DEPTH_OFFSET_SCALE", (cmd & 0xffff) + 2); + case 0x98: + return debug(stream, "3DSTATE_DEFAULT_Z", (cmd & 0xffff) + 2); + case 0x99: + return debug(stream, "3DSTATE_DEFAULT_DIFFUSE", (cmd & 0xffff) + 2); + case 0x9a: + return debug(stream, "3DSTATE_DEFAULT_SPECULAR", (cmd & 0xffff) + 2); + case 0x9c: + return debug(stream, "3DSTATE_CLEAR_PARAMETERS", (cmd & 0xffff) + 2); + default: + assert(0); + return 0; + } + break; + case 0x1e: + if (cmd & (1 << 23)) + return debug(stream, "???", (cmd & 0xffff) + 1); + else + return debug(stream, "", 1); + break; + case 0x1f: + if ((cmd & (1 << 23)) == 0) + return debug_prim(stream, "3DPRIM (inline)", 1, (cmd & 0x1ffff) + 2); + else if (cmd & (1 << 17)) + { + if ((cmd & 0xffff) == 0) + return debug_variable_length_prim(stream); + else + return debug_prim(stream, "3DPRIM (indexed)", 0, (((cmd & 0xffff) + 1) / 2) + 1); + } + else + return debug_prim(stream, "3DPRIM (indirect sequential)", 0, 2); + break; + default: + return debug(stream, "", 0); + } + default: + assert(0); + return 0; + } + + assert(0); + return 0; } + void -i915_disassemble_program(const unsigned * program, unsigned sz) +i915_dump_batchbuffer( struct i915_context *i915, + GLuint *start, + GLuint *end ) { - unsigned size = program[0] & 0x1ff; - unsigned i; + struct debug_stream stream; + GLuint bytes = (end - start) * 4; + GLboolean done = GL_FALSE; - fprintf(stderr, "BEGIN\n"); + fprintf(stderr, "\n\nBATCH: (%d)\n", bytes / 4); - if (size + 2 != sz) { - fprintf(stderr, "%s: program size mismatch %d/%d\n", __FUNCTION__, - size + 2, sz); - assert(0); - } + stream.offset = 0; + stream.ptr = (char *)start; + stream.print_addresses = 0; - program++; - for (i = 1; i < sz; i += 3, program += 3) { - unsigned opcode = program[0] & (0x1f << 24); + while (!done && + stream.offset < bytes && + stream.offset >= 0) + { + if (!i915_debug_packet( &stream )) + break; - if ((unsigned) opcode >= A0_NOP && opcode <= A0_SLT) - print_arith_op(opcode >> 24, program); - else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) - print_tex_op(opcode >> 24, program); - else if (opcode == D0_DCL) - print_dcl_op(opcode >> 24, program); - else - fprintf(stderr, "Unknown opcode 0x%x\n", opcode); + assert(stream.offset <= bytes && + stream.offset >= 0); } - fprintf(stderr, "END\n\n"); + fprintf(stderr, "END-BATCH\n\n\n"); } + + diff --git a/src/mesa/pipe/i915simple/i915_debug.h b/src/mesa/pipe/i915simple/i915_debug.h index 47a02401ee..3e01db6434 100644 --- a/src/mesa/pipe/i915simple/i915_debug.h +++ b/src/mesa/pipe/i915simple/i915_debug.h @@ -31,9 +31,26 @@ #ifndef I915_DEBUG_H #define I915_DEBUG_H +struct i915_context; + +struct debug_stream +{ + unsigned offset; /* current gtt offset */ + char *ptr; /* pointer to gtt offset zero */ + char *end; /* pointer to gtt offset zero */ + unsigned print_addresses; +}; + + extern void i915_disassemble_program(const unsigned *program, unsigned sz); extern void i915_print_ureg(const char *msg, unsigned ureg); +void +i915_dump_batchbuffer( struct i915_context *i915, + unsigned *start, + unsigned *end ); + + #endif diff --git a/src/mesa/pipe/i915simple/i915_debug_fp.c b/src/mesa/pipe/i915simple/i915_debug_fp.c new file mode 100644 index 0000000000..f4e8ae95ad --- /dev/null +++ b/src/mesa/pipe/i915simple/i915_debug_fp.c @@ -0,0 +1,331 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> + +#include "i915_reg.h" +#include "i915_debug.h" +//#include "i915_fpc.h" +#include "shader/program.h" +#include "shader/prog_instruction.h" +#include "shader/prog_print.h" + +static const char *opcodes[0x20] = { + "NOP", + "ADD", + "MOV", + "MUL", + "MAD", + "DP2ADD", + "DP3", + "DP4", + "FRC", + "RCP", + "RSQ", + "EXP", + "LOG", + "CMP", + "MIN", + "MAX", + "FLR", + "MOD", + "TRC", + "SGE", + "SLT", + "TEXLD", + "TEXLDP", + "TEXLDB", + "TEXKILL", + "DCL", + "0x1a", + "0x1b", + "0x1c", + "0x1d", + "0x1e", + "0x1f", +}; + + +static const int args[0x20] = { + 0, /* 0 nop */ + 2, /* 1 add */ + 1, /* 2 mov */ + 2, /* 3 m ul */ + 3, /* 4 mad */ + 3, /* 5 dp2add */ + 2, /* 6 dp3 */ + 2, /* 7 dp4 */ + 1, /* 8 frc */ + 1, /* 9 rcp */ + 1, /* a rsq */ + 1, /* b exp */ + 1, /* c log */ + 3, /* d cmp */ + 2, /* e min */ + 2, /* f max */ + 1, /* 10 flr */ + 1, /* 11 mod */ + 1, /* 12 trc */ + 2, /* 13 sge */ + 2, /* 14 slt */ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + + +static const char *regname[0x8] = { + "R", + "T", + "CONST", + "S", + "OC", + "OD", + "U", + "UNKNOWN", +}; + +static void +print_reg_type_nr(GLuint type, GLuint nr) +{ + switch (type) { + case REG_TYPE_T: + switch (nr) { + case T_DIFFUSE: + _mesa_printf("T_DIFFUSE"); + return; + case T_SPECULAR: + _mesa_printf("T_SPECULAR"); + return; + case T_FOG_W: + _mesa_printf("T_FOG_W"); + return; + default: + _mesa_printf("T_TEX%d", nr); + return; + } + case REG_TYPE_OC: + if (nr == 0) { + _mesa_printf("oC"); + return; + } + break; + case REG_TYPE_OD: + if (nr == 0) { + _mesa_printf("oD"); + return; + } + break; + default: + break; + } + + _mesa_printf("%s[%d]", regname[type], nr); +} + +#define REG_SWIZZLE_MASK 0x7777 +#define REG_NEGATE_MASK 0x8888 + +#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ + (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ + (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ + (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) + + +static void +print_reg_neg_swizzle(GLuint reg) +{ + int i; + + if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && + (reg & REG_NEGATE_MASK) == 0) + return; + + _mesa_printf("."); + + for (i = 3; i >= 0; i--) { + if (reg & (1 << ((i * 4) + 3))) + _mesa_printf("-"); + + switch ((reg >> (i * 4)) & 0x7) { + case 0: + _mesa_printf("x"); + break; + case 1: + _mesa_printf("y"); + break; + case 2: + _mesa_printf("z"); + break; + case 3: + _mesa_printf("w"); + break; + case 4: + _mesa_printf("0"); + break; + case 5: + _mesa_printf("1"); + break; + default: + _mesa_printf("?"); + break; + } + } +} + + +static void +print_src_reg(GLuint dword) +{ + GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; + GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; + print_reg_type_nr(type, nr); + print_reg_neg_swizzle(dword); +} + + +static void +print_dest_reg(GLuint dword) +{ + GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; + GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; + print_reg_type_nr(type, nr); + if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) + return; + _mesa_printf("."); + if (dword & A0_DEST_CHANNEL_X) + _mesa_printf("x"); + if (dword & A0_DEST_CHANNEL_Y) + _mesa_printf("y"); + if (dword & A0_DEST_CHANNEL_Z) + _mesa_printf("z"); + if (dword & A0_DEST_CHANNEL_W) + _mesa_printf("w"); +} + + +#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) +#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) +#define GET_SRC2_REG(r) (r) + + +static void +print_arith_op(GLuint opcode, const GLuint * program) +{ + if (opcode != A0_NOP) { + print_dest_reg(program[0]); + if (program[0] & A0_DEST_SATURATE) + _mesa_printf(" = SATURATE "); + else + _mesa_printf(" = "); + } + + _mesa_printf("%s ", opcodes[opcode]); + + print_src_reg(GET_SRC0_REG(program[0], program[1])); + if (args[opcode] == 1) { + _mesa_printf("\n"); + return; + } + + _mesa_printf(", "); + print_src_reg(GET_SRC1_REG(program[1], program[2])); + if (args[opcode] == 2) { + _mesa_printf("\n"); + return; + } + + _mesa_printf(", "); + print_src_reg(GET_SRC2_REG(program[2])); + _mesa_printf("\n"); + return; +} + + +static void +print_tex_op(GLuint opcode, const GLuint * program) +{ + print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); + _mesa_printf(" = "); + + _mesa_printf("%s ", opcodes[opcode]); + + _mesa_printf("S[%d],", program[0] & T0_SAMPLER_NR_MASK); + + print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & + REG_TYPE_MASK, + (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); + _mesa_printf("\n"); +} + +static void +print_dcl_op(GLuint opcode, const GLuint * program) +{ + _mesa_printf("%s ", opcodes[opcode]); + print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); + _mesa_printf("\n"); +} + + +void +i915_disassemble_program(const GLuint * program, GLuint sz) +{ + GLuint size = program[0] & 0x1ff; + GLint i; + + _mesa_printf("\t\tBEGIN\n"); + + assert(size + 2 == sz); + + program++; + for (i = 1; i < sz; i += 3, program += 3) { + GLuint opcode = program[0] & (0x1f << 24); + + _mesa_printf("\t\t"); + + if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT) + print_arith_op(opcode >> 24, program); + else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) + print_tex_op(opcode >> 24, program); + else if (opcode == D0_DCL) + print_dcl_op(opcode >> 24, program); + else + _mesa_printf("Unknown opcode 0x%x\n", opcode); + } + + _mesa_printf("\t\tEND\n\n"); +} + + |