Esempio n. 1
0
		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;
		}