string GetSourceName(InstructionToken instruction, int srcIndex) { string sourceRegisterName = instruction.GetParamRegisterName(srcIndex); sourceRegisterName = ApplyModifier(instruction.GetSourceModifier(srcIndex), sourceRegisterName); sourceRegisterName += instruction.GetSourceSwizzleName(srcIndex); if (instruction.IsRelativeAddressMode(srcIndex)) { sourceRegisterName += $"[{GetSourceName(instruction, srcIndex + 1)}]"; } return(sourceRegisterName); }
public string GetDestinationName(InstructionToken instruction) { int destIndex = instruction.GetDestinationParamIndex(); RegisterKey registerKey = instruction.GetParamRegisterKey(destIndex); string registerName = GetRegisterName(registerKey); registerName = registerName ?? instruction.GetParamRegisterName(destIndex); var registerLength = GetRegisterFullLength(registerKey); string writeMaskName = instruction.GetDestinationWriteMaskName(registerLength, true); return(string.Format("{0}{1}", registerName, writeMaskName)); }
string GetDestinationName(InstructionToken instruction) { var resultModifier = instruction.GetDestinationResultModifier(); int destIndex = instruction.GetDestinationParamIndex(); string registerName = instruction.GetParamRegisterName(destIndex); const int registerLength = 4; string writeMaskName = instruction.GetDestinationWriteMaskName(registerLength, false); string destinationName = $"{registerName}{writeMaskName}"; if (resultModifier != ResultModifier.None) { //destinationName += "TODO:Modifier!!!"; } return(destinationName); }
string GetSourceName(InstructionToken instruction, int srcIndex, bool isLogicalIndex = true) { int dataIndex; if (isLogicalIndex) { // compute the actual data index, which might be different from logical index // because of relative addressing mode. // TODO: Handle relative addressing mode in a better way, // by using `InstructionToken.Operands`: // https://github.com/spacehamster/DXDecompiler/pull/6#issuecomment-782958769 // if instruction has destination, then source starts at the index 1 // here we assume destination won't have relative addressing, // so we assume destination will only occupy 1 slot, // that is, the start index for sources will be 1 if instruction.HasDestination is true. var begin = instruction.HasDestination ? 1 : 0; dataIndex = begin; while (srcIndex > begin) { if (instruction.IsRelativeAddressMode(dataIndex)) { ++dataIndex; } ++dataIndex; --srcIndex; } } else { dataIndex = srcIndex; } string sourceRegisterName = instruction.GetParamRegisterName(dataIndex); sourceRegisterName = ApplyModifier(instruction.GetSourceModifier(dataIndex), sourceRegisterName); if (instruction.IsRelativeAddressMode(dataIndex)) { sourceRegisterName += $"[{GetSourceName(instruction, dataIndex + 1, isLogicalIndex: false)}]"; } sourceRegisterName += instruction.GetSourceSwizzleName(dataIndex); return(sourceRegisterName); }
private void WriteInstruction(InstructionToken instruction) { if (RemoveIndentInstruction(instruction)) { Indent--; } if (instruction.Opcode != Opcode.Comment && instruction.Opcode != Opcode.End) { WriteIndent(); } if (AddIndentInstruction(instruction)) { Indent++; } switch (instruction.Opcode) { case Opcode.Abs: WriteLine("abs{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Add: WriteLine("add{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Cmp: WriteLine("cmp{0} {1}, {2}, {3}, {4}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Dcl: string dclInstruction = "dcl"; var registerType = instruction.GetParamRegisterType(1); if (ShouldDeclareSemantics(instruction, registerType)) { dclInstruction += "_" + instruction.GetDeclSemantic().ToLower(); } WriteLine("{0}{1} {2}", dclInstruction, GetInstructionModifier(instruction), GetDestinationName(instruction)); break; case Opcode.Def: { string modifier = GetInstructionModifier(instruction); string constRegisterName = instruction.GetParamRegisterName(0); string constValue0 = SingleToString(instruction.GetParamBytes(1)); string constValue1 = SingleToString(instruction.GetParamBytes(2)); string constValue2 = SingleToString(instruction.GetParamBytes(3)); string constValue3 = SingleToString(instruction.GetParamBytes(4)); WriteLine("def{0} {1}, {2}, {3}, {4}, {5}", modifier, constRegisterName, constValue0, constValue1, constValue2, constValue3); } break; case Opcode.DefI: { string constRegisterName = instruction.GetParamRegisterName(0); WriteLine("defi{0} {1}, {2}, {3}, {4}, {5}", GetInstructionModifier(instruction), constRegisterName, instruction.Data[1], instruction.Data[2], instruction.Data[3], instruction.Data[4]); } break; case Opcode.DP2Add: WriteLine("dp2add{0} {1}, {2}, {3}, {4}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Dp3: WriteLine("dp3{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Dp4: WriteLine("dp4{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Else: WriteLine("else"); break; case Opcode.Endif: WriteLine("endif"); break; case Opcode.Exp: WriteLine("exp{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Frc: WriteLine("frc{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.If: WriteLine("if {0}", GetSourceName(instruction, 0)); break; case Opcode.IfC: WriteLine("if_{0} {1}, {2}", ((IfComparison)instruction.Modifier).ToString().ToLower(), GetSourceName(instruction, 0), GetSourceName(instruction, 1)); break; case Opcode.Log: WriteLine("log{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Lrp: WriteLine("lrp{0} {1}, {2}, {3}, {4}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Mad: WriteLine("mad{0} {1}, {2}, {3}, {4}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Max: WriteLine("max{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Min: WriteLine("min{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Mov: WriteLine("mov{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.MovA: WriteLine("mova{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Mul: WriteLine("mul{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Nop: WriteLine("nop"); break; case Opcode.Nrm: WriteLine("nrm{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Pow: WriteLine("pow{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Rcp: WriteLine("rcp{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Rsq: WriteLine("rsq{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Sge: WriteLine("sge{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Slt: WriteLine("slt{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.SinCos: if (shader.MajorVersion >= 3) { WriteLine("sincos {0}, {1}", GetDestinationName(instruction), GetSourceName(instruction, 1)); } else { WriteLine("sincos {0}, {1}, {2}, {3}", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); } break; case Opcode.Sub: WriteLine("sub{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Tex: if ((shader.MajorVersion == 1 && shader.MinorVersion >= 4) || (shader.MajorVersion > 1)) { WriteLine("texld {0}, {1}, {2}", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); } else { WriteLine("tex {0}", GetDestinationName(instruction)); } break; case Opcode.TexLDL: WriteLine("texldl {0}, {1}, {2}", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.TexKill: WriteLine("texkill {0}", GetDestinationName(instruction)); break; case Opcode.Rep: WriteLine("rep {0}", GetDestinationName(instruction)); break; case Opcode.EndRep: WriteLine("endrep"); break; case Opcode.DSX: WriteLine("dsx{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.DSY: WriteLine("dsy{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.TexLDD: WriteLine("texldd {0}, {1}, {2}, {3}, {4}", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3), GetSourceName(instruction, 4)); break; case Opcode.BreakC: WriteLine("break_{0} {1}, {2}", ((IfComparison)instruction.Modifier).ToString().ToLower(), GetSourceName(instruction, 0), GetSourceName(instruction, 1)); break; //TODO: Add tests for Loop, and Lit case Opcode.Loop: WriteLine("loop {0}, {1}", GetSourceName(instruction, 0), GetSourceName(instruction, 1)); break; case Opcode.EndLoop: WriteLine("endloop"); break; case Opcode.Lit: WriteLine("lit{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.ExpP: WriteLine("expp{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.LogP: WriteLine("logp{0} {1}, {2}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.M4x4: WriteLine("m4x4{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.M4x3: WriteLine("m4x3{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.M3x3: WriteLine("m3x3{0} {1}, {2}, {3}", GetInstructionModifier(instruction), GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Call: WriteLine("call {0}", GetSourceName(instruction, 0)); break; case Opcode.Ret: WriteLine("ret"); break; case Opcode.Label: WriteLine("label", GetSourceName(instruction, 0)); break; case Opcode.Comment: case Opcode.End: break; default: WriteLine(instruction.Opcode.ToString()); //WriteLine("// Warning - Not Implemented"); throw new NotImplementedException($"Instruction not implemented {instruction.Opcode}"); } }
private void WriteInstruction(InstructionToken instruction) { WriteIndent(); WriteLine($"// {instruction}"); switch (instruction.Opcode) { case Opcode.Def: case Opcode.DefI: case Opcode.Dcl: case Opcode.End: return; // these opcodes doesn't need indents: case Opcode.Else: Indent--; WriteIndent(); WriteLine("} else {"); Indent++; return; case Opcode.Endif: Indent--; WriteIndent(); WriteLine("}"); return; case Opcode.EndRep: Indent--; _iterationDepth--; WriteIndent(); WriteLine("}"); return; } WriteIndent(); switch (instruction.Opcode) { case Opcode.Abs: WriteLine("{0} = abs({1});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Add: WriteLine("{0} = {1} + {2};", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Cmp: // TODO: should be per-component WriteLine("{0} = ({1} >= 0) ? {2} : {3};", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.DP2Add: WriteLine("{0} = dot({1}, {2}) + {3};", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Dp3: WriteLine("{0} = dot({1}, {2});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Dp4: WriteLine("{0} = dot({1}, {2});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Exp: WriteLine("{0} = exp2({1});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Frc: WriteLine("{0} = frac({1});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.If: WriteLine("if ({0}) {{", GetSourceName(instruction, 0)); Indent++; break; case Opcode.IfC: if ((IfComparison)instruction.Modifier == IfComparison.GE && instruction.GetSourceModifier(0) == SourceModifier.AbsAndNegate && instruction.GetSourceModifier(1) == SourceModifier.Abs && instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0) == instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1)) { WriteLine("if ({0} == 0) {{", instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0)); } else if ((IfComparison)instruction.Modifier == IfComparison.LT && instruction.GetSourceModifier(0) == SourceModifier.AbsAndNegate && instruction.GetSourceModifier(1) == SourceModifier.Abs && instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0) == instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1)) { WriteLine("if ({0} != 0) {{", instruction.GetParamRegisterName(0) + instruction.GetSourceSwizzleName(0)); } else { string ifComparison; switch ((IfComparison)instruction.Modifier) { case IfComparison.GT: ifComparison = ">"; break; case IfComparison.EQ: ifComparison = "=="; break; case IfComparison.GE: ifComparison = ">="; break; case IfComparison.LE: ifComparison = "<="; break; case IfComparison.NE: ifComparison = "!="; break; case IfComparison.LT: ifComparison = "<"; break; default: throw new InvalidOperationException(); } WriteLine("if ({0} {2} {1}) {{", GetSourceName(instruction, 0), GetSourceName(instruction, 1), ifComparison); } Indent++; break; case Opcode.Log: WriteLine("{0} = log2({1});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Lrp: WriteLine("{0} = lerp({2}, {3}, {1});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Mad: WriteLine("{0} = {1} * {2} + {3};", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2), GetSourceName(instruction, 3)); break; case Opcode.Max: WriteLine("{0} = max({1}, {2});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Min: WriteLine("{0} = min({1}, {2});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Mov: WriteLine("{0} = {1};", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.MovA: WriteLine("{0} = {1};", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Mul: WriteLine("{0} = {1} * {2};", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Nrm: WriteLine("{0} = normalize({1});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Pow: WriteLine("{0} = pow({1}, {2});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Rcp: WriteLine("{0} = 1 / {1};", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Rsq: WriteLine("{0} = 1 / sqrt({1});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Sge: if (instruction.GetSourceModifier(1) == SourceModifier.AbsAndNegate && instruction.GetSourceModifier(2) == SourceModifier.Abs && instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1) == instruction.GetParamRegisterName(2) + instruction.GetSourceSwizzleName(2)) { WriteLine("{0} = ({1} == 0) ? 1 : 0;", GetDestinationName(instruction), instruction.GetParamRegisterName(1) + instruction.GetSourceSwizzleName(1)); } else { WriteLine("{0} = ({1} >= {2}) ? 1 : 0;", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); } break; case Opcode.Slt: WriteLine("{0} = ({1} < {2}) ? 1 : 0;", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.SinCos: WriteLine("sincos({1}, {0}, {0});", GetDestinationName(instruction), GetSourceName(instruction, 1)); break; case Opcode.Sub: WriteLine("{0} = {1} - {2};", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Tex: if ((_shader.MajorVersion == 1 && _shader.MinorVersion >= 4) || (_shader.MajorVersion > 1)) { WriteLine("{0} = tex2D({2}, {1});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); } else { WriteLine("{0} = tex2D();", GetDestinationName(instruction)); } break; case Opcode.TexLDL: WriteLine("{0} = tex2Dlod({2}, {1});", GetDestinationName(instruction), GetSourceName(instruction, 1), GetSourceName(instruction, 2)); break; case Opcode.Comment: { byte[] bytes = new byte[instruction.Data.Length * sizeof(uint)]; Buffer.BlockCopy(instruction.Data, 0, bytes, 0, bytes.Length); var ascii = FormatUtil.BytesToAscii(bytes); WriteLine($"// Comment: {ascii}"); break; } case Opcode.Rep: WriteLine("for (int it{0} = 0; it{0} < {1}; ++it{0}) {{", _iterationDepth, GetSourceName(instruction, 0)); _iterationDepth++; Indent++; break; case Opcode.TexKill: WriteLine("clip({0});", GetDestinationName(instruction)); break; default: throw new NotImplementedException(instruction.Opcode.ToString()); } }
public string GetSourceName(InstructionToken instruction, int srcIndex) { string sourceRegisterName; RegisterKey registerKey = instruction.GetParamRegisterKey(srcIndex); var registerType = instruction.GetParamRegisterType(srcIndex); switch (registerType) { case RegisterType.Const: case RegisterType.Const2: case RegisterType.Const3: case RegisterType.Const4: case RegisterType.ConstBool: case RegisterType.ConstInt: sourceRegisterName = GetSourceConstantName(instruction, srcIndex); if (sourceRegisterName != null) { return(sourceRegisterName); } ParameterType parameterType; switch (registerType) { case RegisterType.Const: case RegisterType.Const2: case RegisterType.Const3: case RegisterType.Const4: parameterType = ParameterType.Float; break; case RegisterType.ConstBool: parameterType = ParameterType.Bool; break; case RegisterType.ConstInt: parameterType = ParameterType.Int; break; default: throw new NotImplementedException(); } var registerNumber = instruction.GetParamRegisterNumber(srcIndex); ConstantDeclaration decl = FindConstant(registerNumber); if (decl == null) { // Constant register not found in def statements nor the constant table //TODO: return($"Error {registerType}{registerNumber}"); //throw new NotImplementedException(); } var totalOffset = registerNumber - decl.RegisterIndex; var data = decl.GetRegisterTypeByOffset(totalOffset); var offsetFromMember = registerNumber - data.RegisterIndex; sourceRegisterName = decl.GetMemberNameByOffset(totalOffset); if (data.Type.ParameterClass == ParameterClass.MatrixRows) { sourceRegisterName = string.Format("{0}[{1}]", decl.Name, offsetFromMember); } else if (data.Type.ParameterClass == ParameterClass.MatrixColumns) { sourceRegisterName = string.Format("transpose({0})[{1}]", decl.Name, offsetFromMember); } break; default: sourceRegisterName = GetRegisterName(registerKey); break; } sourceRegisterName = sourceRegisterName ?? instruction.GetParamRegisterName(srcIndex); sourceRegisterName += instruction.GetSourceSwizzleName(srcIndex, true); return(ApplyModifier(instruction.GetSourceModifier(srcIndex), sourceRegisterName)); }