public static Number4 ApplyOperandSelectionMode(Number4 value, Operand operand) { switch (operand.SelectionMode) { case Operand4ComponentSelectionMode.Swizzle: case Operand4ComponentSelectionMode.Select1: return Number4.Swizzle(value, operand.Swizzles); default: throw new ArgumentOutOfRangeException(); } }
private static string ApplyOperandSelectionMode(string register, Operand operand, bool forUseInArrayIndex) { switch (operand.SelectionMode) { case Operand4ComponentSelectionMode.Select1: if (forUseInArrayIndex) return string.Format("{0}.Int{1}", register, (int) operand.Swizzles[0]); goto case Operand4ComponentSelectionMode.Swizzle; case Operand4ComponentSelectionMode.Swizzle: if (operand.Swizzles[0] == Operand4ComponentName.X && operand.Swizzles[1] == Operand4ComponentName.Y && operand.Swizzles[2] == Operand4ComponentName.Z && operand.Swizzles[3] == Operand4ComponentName.W) return register; return string.Format("{0}.{1}{2}{3}{4}", register, GetOperand4ComponentName(operand.Swizzles[0]), GetOperand4ComponentName(operand.Swizzles[1]).ToLower(), GetOperand4ComponentName(operand.Swizzles[2]).ToLower(), GetOperand4ComponentName(operand.Swizzles[3]).ToLower()); default : throw new ArgumentOutOfRangeException(); } }
private static string GenerateGetOperandValue(Operand operand, NumberType numberType, string contextName = "context", bool forUseInArrayIndex = false) { switch (operand.OperandType) { case OperandType.Immediate32 : case OperandType.Immediate64: Number4 immediateValues; switch (operand.NumComponents) { case 1: immediateValues = operand.ImmediateValues.Xxxx; break; case 4: immediateValues = operand.ImmediateValues; break; default: throw new NotImplementedException(); } var value = OperandUtility.ApplyOperandModifier(immediateValues, numberType, operand.Modifier); return string.Format("new Number4({0}f, {1}f, {2}f, {3}f)", value.Float0, value.Float1, value.Float2, value.Float3); case OperandType.ConstantBuffer: case OperandType.IndexableTemp: case OperandType.Input: case OperandType.Temp: var swizzled = ApplyOperandSelectionMode(GetRegister(operand, contextName), operand, forUseInArrayIndex); switch (operand.Modifier) { case OperandModifier.None: return swizzled; case OperandModifier.Neg: return string.Format("Number4.Negate{0}({1})", numberType, swizzled); case OperandModifier.Abs: throw new NotImplementedException(); case OperandModifier.AbsNeg: throw new NotImplementedException(); default : throw new ArgumentOutOfRangeException(); } default: throw new ArgumentException("Unsupported operand type: " + operand.OperandType); } }
private static string GetRegisterIndex(Operand operand) { switch (operand.IndexDimension) { case OperandIndexDimension._1D: // Only geometry shaders use 2D input values, but we always need to // use 2D indices because we use a 2D input array. if (operand.OperandType == OperandType.Input) return string.Format("[0][{0}]", GetRegisterIndex(operand.Indices[0])); return string.Format("[{0}]", GetRegisterIndex(operand.Indices[0])); case OperandIndexDimension._2D: return string.Format("[{0}][{1}]", GetRegisterIndex(operand.Indices[0]), GetRegisterIndex(operand.Indices[1])); default: throw new ArgumentOutOfRangeException(); } }
private static string GetRegister(Operand operand, string contextName = "context") { if (operand.OperandType == OperandType.ConstantBuffer) return string.Format("virtualMachine.{0}{1}", GetRegisterName(operand.OperandType), GetRegisterIndex(operand)); return string.Format("{0}.{1}{2}", contextName, GetRegisterName(operand.OperandType), GetRegisterIndex(operand)); }
private static void GenerateSetRegisterValueScalar(StringBuilder sb, Operand operand) { var register = GetRegister(operand); if (operand.ComponentMask.HasFlag(ComponentMask.X)) sb.AppendLineIndent(2, " {0}.Number0 = result;", register); if (operand.ComponentMask.HasFlag(ComponentMask.Y)) sb.AppendLineIndent(2, " {0}.Number1 = result;", register); if (operand.ComponentMask.HasFlag(ComponentMask.Z)) sb.AppendLineIndent(2, " {0}.Number2 = result;", register); if (operand.ComponentMask.HasFlag(ComponentMask.W)) sb.AppendLineIndent(2, " {0}.Number3 = result;", register); }
private static void GenerateSetRegisterValue(StringBuilder sb, Operand operand, string contextName = "context") { var register = GetRegister(operand, contextName); if (operand.ComponentMask.HasFlag(ComponentMask.X) && operand.ComponentMask.HasFlag(ComponentMask.Y) && operand.ComponentMask.HasFlag(ComponentMask.Z) && operand.ComponentMask.HasFlag(ComponentMask.W)) { sb.AppendLineIndent(2, " {0} = result;", register); return; } if (operand.ComponentMask.HasFlag(ComponentMask.X)) sb.AppendLineIndent(2, " {0}.Number0 = result.Number0;", register); if (operand.ComponentMask.HasFlag(ComponentMask.Y)) sb.AppendLineIndent(2, " {0}.Number1 = result.Number1;", register); if (operand.ComponentMask.HasFlag(ComponentMask.Z)) sb.AppendLineIndent(2, " {0}.Number2 = result.Number2;", register); if (operand.ComponentMask.HasFlag(ComponentMask.W)) sb.AppendLineIndent(2, " {0}.Number3 = result.Number3;", register); }
private static void SetRegisterValue(ExecutionContext context, Operand operand, Number4 value) { Number4[] register; int index; GetRegister(context, operand, out register, out index); register[index].WriteMaskedValue(value, operand.ComponentMask); }
private static RegisterIndex GetRegisterIndex(ExecutionContext context, Operand operand) { var result = new RegisterIndex(); switch (operand.IndexDimension) { case OperandIndexDimension._1D: result.Index1D = EvaluateOperandIndex(context, operand.Indices[0]); break; case OperandIndexDimension._2D: result.Index2D_0 = EvaluateOperandIndex(context, operand.Indices[0]); result.Index2D_1 = EvaluateOperandIndex(context, operand.Indices[1]); break; } return result; }
/// <summary> /// Gets potentially-swizzled value for use on RHS of an operation. /// </summary> private static Number4 GetOperandValue(ExecutionContext context, Operand operand, NumberType numberType) { switch (operand.OperandType) { case OperandType.Immediate32: case OperandType.Immediate64: Number4 value; switch (operand.NumComponents) { case 1 : value = operand.ImmediateValues.Xxxx; break; case 4 : value = operand.ImmediateValues; break; default : throw new NotImplementedException(); } return OperandUtility.ApplyOperandModifier(value, numberType, operand.Modifier); case OperandType.ConstantBuffer: case OperandType.IndexableTemp: case OperandType.Input: case OperandType.Temp: Number4[] register; int index; GetRegister(context, operand, out register, out index); var swizzledNumber = OperandUtility.ApplyOperandSelectionMode(register[index], operand); return OperandUtility.ApplyOperandModifier(swizzledNumber, numberType, operand.Modifier); default: throw new ArgumentException("Unsupported operand type: " + operand.OperandType); } }
private static void GetRegister(ExecutionContext context, Operand operand, out Number4[] register, out int index) { var registerIndex = GetRegisterIndex(context, operand); context.GetRegister(operand.OperandType, registerIndex, out register, out index); }
public static Operand Parse(BytecodeReader reader, OpcodeType parentType) { uint token0 = reader.ReadUInt32(); if (token0 == 0) return null; var operand = new Operand(parentType); var numComponents = token0.DecodeValue<OperandNumComponents>(0, 1); switch (numComponents) { case OperandNumComponents.Zero: { operand.NumComponents = 0; break; } case OperandNumComponents.One: { operand.NumComponents = 1; break; } case OperandNumComponents.Four: { operand.NumComponents = 4; operand.SelectionMode = token0.DecodeValue<Operand4ComponentSelectionMode>(2, 3); switch (operand.SelectionMode) { case Operand4ComponentSelectionMode.Mask: { operand.ComponentMask = token0.DecodeValue<ComponentMask>(4, 7); break; } case Operand4ComponentSelectionMode.Swizzle: { var swizzle = token0.DecodeValue(4, 11); Func<uint, byte, Operand4ComponentName> swizzleDecoder = (s, i) => (Operand4ComponentName) ((s >> (i * 2)) & 3); operand.Swizzles[0] = swizzleDecoder(swizzle, 0); operand.Swizzles[1] = swizzleDecoder(swizzle, 1); operand.Swizzles[2] = swizzleDecoder(swizzle, 2); operand.Swizzles[3] = swizzleDecoder(swizzle, 3); break; } case Operand4ComponentSelectionMode.Select1: { var swizzle = token0.DecodeValue<Operand4ComponentName>(4, 5); operand.Swizzles[0] = operand.Swizzles[1] = operand.Swizzles[2] = operand.Swizzles[3] = swizzle; break; } default: { throw new ParseException("Unrecognized selection method: " + operand.SelectionMode); } } break; } case OperandNumComponents.N: { throw new ParseException("OperandNumComponents.N is not currently supported."); } } operand.OperandType = token0.DecodeValue<OperandType>(12, 19); operand.IndexDimension = token0.DecodeValue<OperandIndexDimension>(20, 21); operand.IsExtended = token0.DecodeValue(31, 31) == 1; if (operand.IsExtended) ReadExtendedOperand(operand, reader); Func<uint, byte, OperandIndexRepresentation> indexRepresentationDecoder = (t, i) => (OperandIndexRepresentation) t.DecodeValue((byte) (22 + (i * 3)), (byte) (22 + (i * 3) + 2)); for (byte i = 0; i < (byte) operand.IndexDimension; i++) { operand.Indices[i] = new OperandIndex(); var indexRepresentation = indexRepresentationDecoder(token0, i); operand.Indices[i].Representation = indexRepresentation; switch (indexRepresentation) { case OperandIndexRepresentation.Immediate32: operand.Indices[i].Value = reader.ReadUInt32(); break; case OperandIndexRepresentation.Immediate64: operand.Indices[i].Value = reader.ReadUInt64(); goto default; case OperandIndexRepresentation.Relative: operand.Indices[i].Register = Parse(reader, parentType); break; case OperandIndexRepresentation.Immediate32PlusRelative: operand.Indices[i].Value = reader.ReadUInt32(); goto case OperandIndexRepresentation.Relative; case OperandIndexRepresentation.Immediate64PlusRelative: operand.Indices[i].Value = reader.ReadUInt64(); goto case OperandIndexRepresentation.Relative; default: throw new ParseException("Unrecognised index representation: " + indexRepresentation); } } var numberType = parentType.GetNumberType(); switch (operand.OperandType) { case OperandType.Immediate32: { var immediateValues = new Number4(); for (var i = 0; i < operand.NumComponents; i++) immediateValues.SetNumber(i, Number.Parse(reader)); operand.ImmediateValues = immediateValues; break; } case OperandType.Immediate64: { var immediateValues = new Number4(); for (var i = 0; i < operand.NumComponents; i++) immediateValues.SetDouble(i, reader.ReadDouble()); operand.ImmediateValues = immediateValues; break; } } return operand; }
/// <summary> /// Extended Instruction Operand Format (OperandToken1) /// /// If bit31 of an operand token is set, the /// operand has additional data in a second DWORD /// directly following OperandToken0. Other tokens /// expected for the operand, such as immmediate /// values or relative address operands (full /// operands in themselves) always follow /// OperandToken0 AND OperandToken1..n (extended /// operand tokens, if present). /// /// [05:00] D3D10_SB_EXTENDED_OPERAND_TYPE /// [30:06] if([05:00] == D3D10_SB_EXTENDED_OPERAND_MODIFIER) /// { /// [13:06] D3D10_SB_OPERAND_MODIFIER /// [30:14] Ignored, 0. /// } /// else /// { /// [30:06] Ignored, 0. /// } /// [31] 0 normally. 1 if second order extended operand definition, /// meaning next DWORD contains yet ANOTHER extended operand /// description. Currently no second order extensions defined. /// This would be useful if a particular extended operand does /// not have enough space to store the required information in /// a single token and so is extended further. /// </summary> private static void ReadExtendedOperand(Operand operand, BytecodeReader reader) { uint token1 = reader.ReadUInt32(); switch (token1.DecodeValue<ExtendedOperandType>(0, 5)) { case ExtendedOperandType.Modifier: operand.Modifier = token1.DecodeValue<OperandModifier>(6, 13); break; } }