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; }