void svga_shader_dump( const unsigned *assem, unsigned dwords, unsigned do_binary ) { boolean finished = FALSE; struct dump_info di; di.version = *assem++; di.is_ps = (di.version & 0xFFFF0000) == 0xFFFF0000; di.indent = 0; _debug_printf( "%s_%u_%u\n", di.is_ps ? "ps" : "vs", (di.version >> 8) & 0xff, di.version & 0xff ); while (!finished) { struct sh_op op = *(struct sh_op *) assem; switch (op.opcode) { case SVGA3DOP_DCL: { struct sh_dcl dcl = *(struct sh_dcl *) assem; _debug_printf( "dcl" ); switch (sh_dstreg_type(dcl.reg)) { case SVGA3DREG_INPUT: if ((di.is_ps && di.version >= SVGA3D_PS_30) || (!di.is_ps && di.version >= SVGA3D_VS_30)) { dump_semantic(dcl.u.semantic.usage, dcl.u.semantic.usage_index); } break; case SVGA3DREG_TEXCRDOUT: if (!di.is_ps && di.version >= SVGA3D_VS_30) { dump_semantic(dcl.u.semantic.usage, dcl.u.semantic.usage_index); } break; case SVGA3DREG_SAMPLER: dump_sampleinfo( dcl.u.sampleinfo ); break; } dump_dstreg(dcl.reg, NULL, &di); _debug_printf( "\n" ); assem += sizeof( struct sh_dcl ) / sizeof( unsigned ); } break; case SVGA3DOP_DEFB: { struct sh_defb defb = *(struct sh_defb *) assem; _debug_printf( "defb " ); dump_reg( defb.reg, NULL, &di ); _debug_printf( ", " ); dump_bdata( defb.data ); _debug_printf( "\n" ); assem += sizeof( struct sh_defb ) / sizeof( unsigned ); } break; case SVGA3DOP_DEFI: { struct sh_defi defi = *(struct sh_defi *) assem; _debug_printf( "defi " ); dump_reg( defi.reg, NULL, &di ); _debug_printf( ", " ); dump_idata( defi.idata ); _debug_printf( "\n" ); assem += sizeof( struct sh_defi ) / sizeof( unsigned ); } break; case SVGA3DOP_TEXCOORD: { struct sh_opcode_info info = *svga_opcode_info(op.opcode); assert(di.is_ps); if (di.version > SVGA3D_PS_13) { assert(info.num_src == 0); info.num_src = 1; } dump_inst(&di, &assem, op, &info); } break; case SVGA3DOP_TEX: { struct sh_opcode_info info = *svga_opcode_info(op.opcode); assert(di.is_ps); if (di.version > SVGA3D_PS_13) { assert(info.num_src == 0); if (di.version > SVGA3D_PS_14) { info.num_src = 2; info.mnemonic = "texld"; } else { info.num_src = 1; } } dump_inst(&di, &assem, op, &info); } break; case SVGA3DOP_DEF: { struct sh_def def = *(struct sh_def *) assem; _debug_printf( "def " ); dump_reg( def.reg, NULL, &di ); _debug_printf( ", " ); dump_cdata( def.cdata ); _debug_printf( "\n" ); assem += sizeof( struct sh_def ) / sizeof( unsigned ); } break; case SVGA3DOP_SINCOS: { struct sh_opcode_info info = *svga_opcode_info(op.opcode); if ((di.is_ps && di.version >= SVGA3D_PS_30) || (!di.is_ps && di.version >= SVGA3D_VS_30)) { assert(info.num_src == 3); info.num_src = 1; } dump_inst(&di, &assem, op, &info); } break; case SVGA3DOP_PHASE: _debug_printf( "phase\n" ); assem += sizeof( struct sh_op ) / sizeof( unsigned ); break; case SVGA3DOP_COMMENT: { struct sh_comment comment = *(struct sh_comment *)assem; /* Ignore comment contents. */ assem += sizeof(struct sh_comment) / sizeof(unsigned) + comment.size; } break; case SVGA3DOP_END: finished = TRUE; break; default: { const struct sh_opcode_info *info = svga_opcode_info(op.opcode); dump_inst(&di, &assem, op, info); } } } }
void svga_shader_dump( const unsigned *assem, unsigned dwords, unsigned do_binary ) { const unsigned *start = assem; boolean finished = FALSE; struct dump_info di; unsigned i; if (do_binary) { for (i = 0; i < dwords; i++) debug_printf(" 0x%08x,\n", assem[i]); debug_printf("\n\n"); } di.version.value = *assem++; di.is_ps = (di.version.type == SVGA3D_PS_TYPE); debug_printf( "%s_%u_%u\n", di.is_ps ? "ps" : "vs", di.version.major, di.version.minor ); while (!finished) { struct sh_op op = *(struct sh_op *) assem; if (assem - start >= dwords) { debug_printf("... ran off end of buffer\n"); assert(0); return; } switch (op.opcode) { case SVGA3DOP_DCL: { struct sh_dcl dcl = *(struct sh_dcl *) assem; debug_printf( "dcl" ); if (sh_dstreg_type( dcl.reg ) == SVGA3DREG_SAMPLER) dump_sampleinfo( dcl.u.ps.sampleinfo ); else if (di.is_ps) { if (di.version.major == 3 && sh_dstreg_type( dcl.reg ) != SVGA3DREG_MISCTYPE) dump_usageinfo( dcl.u.vs.semantic ); } else dump_usageinfo( dcl.u.vs.semantic ); dump_dstreg( dcl.reg, &di ); debug_printf( "\n" ); assem += sizeof( struct sh_dcl ) / sizeof( unsigned ); } break; case SVGA3DOP_DEFB: { struct sh_defb defb = *(struct sh_defb *) assem; debug_printf( "defb " ); dump_reg( defb.reg, NULL, &di ); debug_printf( ", " ); dump_bdata( defb.data ); debug_printf( "\n" ); assem += sizeof( struct sh_defb ) / sizeof( unsigned ); } break; case SVGA3DOP_DEFI: { struct sh_defi defi = *(struct sh_defi *) assem; debug_printf( "defi " ); dump_reg( defi.reg, NULL, &di ); debug_printf( ", " ); dump_idata( defi.idata ); debug_printf( "\n" ); assem += sizeof( struct sh_defi ) / sizeof( unsigned ); } break; case SVGA3DOP_TEXCOORD: assert( di.is_ps ); dump_op( op, "texcoord" ); if (0) { struct sh_dstop dstop = *(struct sh_dstop *) assem; dump_dstreg( dstop.dst, &di ); assem += sizeof( struct sh_dstop ) / sizeof( unsigned ); } else { struct sh_unaryop unaryop = *(struct sh_unaryop *) assem; dump_dstreg( unaryop.dst, &di ); debug_printf( ", " ); dump_srcreg( unaryop.src, NULL, &di ); assem += sizeof( struct sh_unaryop ) / sizeof( unsigned ); } debug_printf( "\n" ); break; case SVGA3DOP_TEX: assert( di.is_ps ); if (0) { dump_op( op, "tex" ); if (0) { struct sh_dstop dstop = *(struct sh_dstop *) assem; dump_dstreg( dstop.dst, &di ); assem += sizeof( struct sh_dstop ) / sizeof( unsigned ); } else { struct sh_unaryop unaryop = *(struct sh_unaryop *) assem; dump_dstreg( unaryop.dst, &di ); debug_printf( ", " ); dump_srcreg( unaryop.src, NULL, &di ); assem += sizeof( struct sh_unaryop ) / sizeof( unsigned ); } } else { struct sh_binaryop binaryop = *(struct sh_binaryop *) assem; dump_op( op, "texld" ); dump_dstreg( binaryop.dst, &di ); debug_printf( ", " ); dump_srcreg( binaryop.src0, NULL, &di ); debug_printf( ", " ); dump_srcreg( binaryop.src1, NULL, &di ); assem += sizeof( struct sh_binaryop ) / sizeof( unsigned ); } debug_printf( "\n" ); break; case SVGA3DOP_DEF: { struct sh_def def = *(struct sh_def *) assem; debug_printf( "def " ); dump_reg( def.reg, NULL, &di ); debug_printf( ", " ); dump_cdata( def.cdata ); debug_printf( "\n" ); assem += sizeof( struct sh_def ) / sizeof( unsigned ); } break; case SVGA3DOP_PHASE: debug_printf( "phase\n" ); assem += sizeof( struct sh_op ) / sizeof( unsigned ); break; case SVGA3DOP_COMMENT: { struct sh_comment comment = *(struct sh_comment *)assem; /* Ignore comment contents. */ assem += sizeof(struct sh_comment) / sizeof(unsigned) + comment.size; } break; case SVGA3DOP_RET: debug_printf( "ret\n" ); assem += sizeof( struct sh_op ) / sizeof( unsigned ); break; case SVGA3DOP_END: debug_printf( "end\n" ); finished = TRUE; break; default: { const struct sh_opcode_info *info = svga_opcode_info( op.opcode ); uint i; uint num_src = info->num_src + op.predicated; boolean not_first_arg = FALSE; assert( info->num_dst <= 1 ); if (op.opcode == SVGA3DOP_SINCOS && di.version.major < 3) num_src += 2; dump_comp_op( op, info->mnemonic ); assem += sizeof( struct sh_op ) / sizeof( unsigned ); if (info->num_dst > 0) { struct sh_dstreg dstreg = *(struct sh_dstreg *) assem; dump_dstreg( dstreg, &di ); assem += sizeof( struct sh_dstreg ) / sizeof( unsigned ); not_first_arg = TRUE; } for (i = 0; i < num_src; i++) { struct sh_srcreg srcreg; struct sh_srcreg indreg; srcreg = *(struct sh_srcreg *) assem; assem += sizeof( struct sh_srcreg ) / sizeof( unsigned ); if (srcreg.relative && !di.is_ps && di.version.major >= 2) { indreg = *(struct sh_srcreg *) assem; assem += sizeof( struct sh_srcreg ) / sizeof( unsigned ); } if (not_first_arg) debug_printf( ", " ); else debug_printf( " " ); dump_srcreg( srcreg, &indreg, &di ); not_first_arg = TRUE; } debug_printf( "\n" ); } } } }