/// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            // Determine the size of the immediate operand. Otherwise the length is not calculated correctly.
            DataSize size = PreferredSize;

            if (size == DataSize.None)
            {
                size = context.AddressingMode;
            }
            if (size >= DataSize.Bit64)
            {
                var bit = ((int)size) << 3;
                throw new AssemblerException($"{bit}-bit operands cannot be encoded.");
            }

            else if (size == DataSize.None)
            {
                throw new AssemblerException("The operand size is not specified.");
            }

            instruction.SetOperandSize(context.AddressingMode, size);
            instruction.ImmediateSize = size;

            // Let's evaluate the expression.
            var result = Expression?.Compile()(context);

            result = new ReferenceOffset(result.Reference, result.Constant - ((long)context.Address + instruction.Length));
            instruction.Immediate = result;
        }
		/// <summary>
		/// Encodes the displacement in the <see cref="EncodedInstruction"/>.
		/// </summary>
		/// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
		/// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
		/// <param name="addressSize">The address size used by the effective address.</param>
		private void EncodeDisplacement(Context context, EncodedInstruction instr, DataSize addressSize)
		{
			#region Contract
			Contract.Requires<ArgumentNullException>(context != null);
			Contract.Requires<ArgumentNullException>(instr != null);
			#endregion

			DataSize displacementSize = DataSize.None;
			SimpleExpression displacementExpression = null;

			if (displacement != null)
			{
				// Let's evaluate the displacement expression.
				displacementExpression = displacement(context);

				// Determine the size of the displacement.
				displacementSize = addressSize;
				if (displacementSize == DataSize.None)
				{
					// Does the result have a (resolved or not resolved) reference?
					if (displacementExpression.Reference != null && !displacementExpression.Reference.Resolved)
						// When the result has a reference, use the architecture's address size.
						displacementSize = context.Representation.Architecture.AddressSize;
					else
						// Otherwise, use the most efficient word size.
						displacementSize = MathExt.GetSizeOfValue(displacementExpression.Evaluate(context));	//.Constant);
				}
			}

			instr.DisplacementSize = displacementSize;
			instr.Displacement = displacementExpression;
		}
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            if (context.AddressingMode != DataSize.Bit64 && Register.Size == DataSize.Bit64)
            {
                throw new AssemblerException($"The 64-bit register {Register} cannot be used with non-64-bit operand sizes.");
            }

            // Encode the register as part of the opcode or ModRM byte.
            switch (Encoding)
            {
            case OperandEncoding.Default:
                instruction.SetModRMByte();
                instruction.ModRM.Reg = Register.Value;
                break;

            case OperandEncoding.AddToOpcode:
                instruction.OpcodeReg = (byte)(Register.Value & 0xF);
                break;

            case OperandEncoding.ModRm:
                instruction.SetModRMByte();
                instruction.ModRM.Mod = 0x03;
                instruction.ModRM.RM  = Register.Value;
                break;

            case OperandEncoding.Ignore:
                // The operand is ignored.
                break;
            }

            // Set the operand size to the size of the register.
            instruction.SetOperandSize(context.AddressingMode, Register.Size);
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            ReferenceOffset offsetResult = Offset.Compile()(context);
            ReferenceOffset selectorResult = Selector?.Compile()(context);

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (offsetResult.Reference != null)
                    // When the result has a reference, use the architecture's operand size.
                    size = context.AddressingMode;
                else
                    // Otherwise, use the most efficient word size.
                    size = Extensions.GetSizeOfValue(offsetResult.Constant);
            }
            if (size <= DataSize.Bit8)
                size = DataSize.Bit16;

            if (size > DataSize.Bit64)
                throw new AssemblerException("The operand cannot be encoded.");

            // Set the parameters.
            instruction.Immediate = offsetResult;
            instruction.ImmediateSize = size;
            instruction.ExtraImmediate = selectorResult;
            instruction.ExtraImmediateSize = (DataSize)2;
            instruction.SetOperandSize(context.AddressingMode, size);
        }
        /// <summary>
        /// Encodes the displacement in the <see cref="EncodedInstruction"/>.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        /// <param name="addressSize">The address size used by the effective address.</param>
        void EncodeDisplacement(Context context, EncodedInstruction instr, DataSize addressSize)
        {
            DataSize        displacementSize       = DataSize.None;
            ReferenceOffset displacementExpression = null;

            if (Displacement != null)
            {
                // Let's evaluate the displacement expression.
                displacementExpression = Displacement.Compile()(context);

                // Determine the size of the displacement.
                displacementSize = addressSize;
                if (displacementSize == DataSize.None)
                {
                    // Does the result have a (resolved or not resolved) reference?
                    if (displacementExpression.Reference != null && !displacementExpression.Reference.Resolved)
                    {
                        // When the result has a reference, use the architecture's address size.
                        displacementSize = context.AddressingMode;
                    }
                    else
                    {
                        // Otherwise, use the most efficient word size.
                        displacementSize = Extensions.GetSizeOfValue(displacementExpression.Evaluate(context));
                    }
                }
            }

            instr.DisplacementSize = displacementSize;
            instr.Displacement     = displacementExpression;
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            if (context.AddressingMode != DataSize.Bit64 && Register.Size == DataSize.Bit64)
                throw new AssemblerException($"The 64-bit register {Register} cannot be used with non-64-bit operand sizes.");

            // Encode the register as part of the opcode or ModRM byte.
            switch (Encoding)
            {
                case OperandEncoding.Default:
                    instruction.SetModRMByte();
                    instruction.ModRM.Reg = Register.Value;
                    break;
                case OperandEncoding.AddToOpcode:
                    instruction.OpcodeReg = (byte)(Register.Value & 0xF);
                    break;
                case OperandEncoding.ModRm:
                    instruction.SetModRMByte();
                    instruction.ModRM.Mod = 0x03;
                    instruction.ModRM.RM = Register.Value;
                    break;
                case OperandEncoding.Ignore:
                    // The operand is ignored.
                    break;
            }

            // Set the operand size to the size of the register.
            instruction.SetOperandSize(context.AddressingMode, Register.Size);
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="X86Context"/> in which the
        /// operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the
        /// operand.</param>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="context"/> is <see langword="null"/>.</para>
        /// -or-
        /// <para><paramref name="instr"/> is <see langword="null"/>.</para>
        /// </exception>
        internal override void Construct(X86Context context, EncodedInstruction instr)
        {
            #region Contract
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (instr == null)
            {
                throw new ArgumentNullException("instr");
            }
            #endregion

            // Let's evaluate the expression.
            ExpressionResult result = new BinaryExpression(
                expression,
                BinaryOperation.Subtract,
                new BinaryExpression(
                    new CurrentPosition(),
                    BinaryOperation.Add,
                    new Constant((long)instr.GetLength()))).Evaluate(context);

            // Determine the size of the immediate operand.
            DataSize size = RequestedSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.HasReference)
                {
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                }
                else
                {
                    // Otherwise, use the most efficient word size.
                    size = result.Constant.GetSize();
                }
            }
            if (size >= DataSize.Bit64)
            {
                throw new AssemblerException(ExceptionStrings.OperandSizeNotEncodable);
            }
            else if (size == DataSize.None)
            {
                throw new AssemblerException(ExceptionStrings.OperandSizeNotSpecified);
            }

            // Set the parameters.
            instr.Immediate     = result;
            instr.ImmediateSize = size;
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
Exemple #8
0
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        internal override void Construct(Context context, EncodedInstruction instr)
        {
            // CONTRACT: Operand

            SimpleExpression offsetResult   = offset(context);
            SimpleExpression selectorResult = selector(context);

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;

            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (offsetResult.Reference != null)
                {
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                }
                else
                {
                    // Otherwise, use the most efficient word size.
                    size = MathExt.GetSizeOfValue(offsetResult.Constant);
                }
            }
            if (size <= DataSize.Bit8)
            {
                size = DataSize.Bit16;
            }

            if (size > DataSize.Bit64)
            {
                throw new AssemblerException("The operand cannot be encoded.");
            }
            else if (size == DataSize.None)
            {
                throw new AssemblerException("The operand size is not specified.");
            }



            // Set the parameters.
            instr.Immediate          = offsetResult;
            instr.ImmediateSize      = size;
            instr.ExtraImmediate     = selectorResult;
            instr.ExtraImmediateSize = (DataSize)2;
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            // Let's evaluate the expression.
            var result = Expression?.Compile()(context);

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;

            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.Reference != null)
                {
                    // When the result has a reference, use the architecture's operand size.
                    size = context.AddressingMode;
                }
                else
                {
                    // Otherwise, use the most efficient word size.
                    size = Extensions.GetSizeOfValue(result.Constant);
                }
            }
            if (size > DataSize.Bit64)
            {
                throw new AssemblerException("Operands with more than 64 bits cannot be encoded.");
            }
            else if (size == DataSize.None)
            {
                throw new AssemblerException("The operand size is not specified.");
            }

            // Set the parameters.
            if (!asExtraImmediate)
            {
                instruction.Immediate     = result;
                instruction.ImmediateSize = size;
            }
            else
            {
                instruction.ExtraImmediate     = result;
                instruction.ExtraImmediateSize = size;
            }
            instruction.SetOperandSize(context.AddressingMode, size);
        }
Exemple #10
0
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        internal override void Construct(Context context, EncodedInstruction instr)
        {
            // CONTRACT: Operand

            // Let's evaluate the expression.
            SimpleExpression result = expression(context);

            result = new SimpleExpression(result.Reference, result.Constant - (context.Address + instr.GetLength()));

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;

            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.Reference != null)
                {
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                }
                else
                {
                    // Otherwise, use the most efficient word size.
                    size = MathExt.GetSizeOfValue(result.Constant);
                }
            }
            if (size >= DataSize.Bit64)
            {
                throw new AssemblerException(String.Format(CultureInfo.InvariantCulture,
                                                           "{0}-bit operands cannot be encoded.",
                                                           ((int)size) << 3));
            }
            else if (size == DataSize.None)
            {
                throw new AssemblerException("The operand size is not specified.");
            }

            // Set the parameters.
            instr.Immediate     = result;
            instr.ImmediateSize = size;
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            DataSize addressSize = GetAddressSize(context);

            instruction.SetOperandSize(context.AddressingMode, Size);

            if (context.AddressingMode != DataSize.Bit64 && Size == DataSize.Bit64)
            {
                throw new AssemblerException("A 64-bit operand cannot be used with non-64-bit operand sizes.");
            }

            if (context.AddressingMode != DataSize.Bit64 && addressSize == DataSize.Bit64)
            {
                throw new AssemblerException("A 64-bit effective address cannot be used with non-64-bit address sizes.");
            }

            EncodeDisplacement(context, instruction, addressSize);

            switch (addressSize)
            {
            case DataSize.Bit16:
                Encode16BitEffectiveAddress(instruction);
                break;

            case DataSize.Bit32:
                Encode32BitEffectiveAddress(instruction);
                break;

            case DataSize.Bit64:
                Encode64BitEffectiveAddress(context, instruction);
                break;

            default:
                throw new NotSupportedException();
            }

            // Address size prefix.
            // When the registers have a width different from the current
            // operating mode width, then we have to add an address size prefix.
            // At this point, we know that the widths are valid.
            instruction.SetAddressSize(context.AddressingMode, addressSize);
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            ReferenceOffset offsetResult   = Offset.Compile()(context);
            ReferenceOffset selectorResult = Selector?.Compile()(context);

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;

            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (offsetResult.Reference != null)
                {
                    // When the result has a reference, use the architecture's operand size.
                    size = context.AddressingMode;
                }
                else
                {
                    // Otherwise, use the most efficient word size.
                    size = Extensions.GetSizeOfValue(offsetResult.Constant);
                }
            }
            if (size <= DataSize.Bit8)
            {
                size = DataSize.Bit16;
            }

            if (size > DataSize.Bit64)
            {
                throw new AssemblerException("The operand cannot be encoded.");
            }

            // Set the parameters.
            instruction.Immediate          = offsetResult;
            instruction.ImmediateSize      = size;
            instruction.ExtraImmediate     = selectorResult;
            instruction.ExtraImmediateSize = (DataSize)2;
            instruction.SetOperandSize(context.AddressingMode, size);
        }
Exemple #13
0
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        internal override void Construct(Context context, EncodedInstruction instr)
        {
            // CONTRACT: Operand

            if (context.Representation.Architecture.OperandSize != DataSize.Bit64 &&
                register.GetSize() == DataSize.Bit64)
            {
                throw new AssemblerException(String.Format(
                                                 "The 64-bit register {0} cannot be used with non-64-bit operand sizes.",
                                                 Enum.GetName(typeof(Register), register)));
            }

            // Encode the register as part of the opcode or ModRM byte.
            switch (encoding)
            {
            case OperandEncoding.Default:
                instr.SetModRMByte();
                instr.ModRM.Reg = Register.GetValue();
                break;

            case OperandEncoding.AddToOpcode:
                instr.OpcodeReg = Register.GetValue();
                break;

            case OperandEncoding.ModRm:
                instr.SetModRMByte();
                instr.ModRM.Mod = 0x03;
                instr.ModRM.RM  = Register.GetValue();
                break;

            case OperandEncoding.Ignore:
                // The operand is ignored.
                break;
            }

            // Set the operand size to the size of the register.
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, Register.GetSize());
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="X86Context"/> in which the
        /// operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the
        /// operand.</param>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="context"/> is <see langword="null"/>.</para>
        /// -or-
        /// <para><paramref name="instr"/> is <see langword="null"/>.</para>
        /// </exception>
        internal override void Construct(X86Context context, EncodedInstruction instr)
        {
            #region Contract
            if (context == null) throw new ArgumentNullException("context");
            if (instr == null) throw new ArgumentNullException("instr");
            #endregion

            // Let's evaluate the expression.
            ExpressionResult result = new BinaryExpression(
                    expression,
                    BinaryOperation.Subtract,
                    new BinaryExpression(
                        new CurrentPosition(),
                        BinaryOperation.Add,
                        new Constant((long)instr.GetLength()))).Evaluate(context);

            // Determine the size of the immediate operand.
            DataSize size = RequestedSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.HasReference)
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                else
                    // Otherwise, use the most efficient word size.
                    size = result.Constant.GetSize();
            }
            if (size >= DataSize.Bit64) throw new AssemblerException(ExceptionStrings.OperandSizeNotEncodable);
            else if (size == DataSize.None) throw new AssemblerException(ExceptionStrings.OperandSizeNotSpecified);

            // Set the parameters.
            instr.Immediate = result;
            instr.ImmediateSize = size;
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
Exemple #15
0
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 internal abstract void Construct(Context context, EncodedInstruction instruction);
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        internal override void Construct(Context context, EncodedInstruction instr)
        {
            // CONTRACT: Operand

            // Let's evaluate the expression.
            SimpleExpression result = expression(context);

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.Reference != null)
                    // When the result has a reference, use the architecture's operand size.
                    size = context.Representation.Architecture.OperandSize;
                else
                    // Otherwise, use the most efficient word size.
                    size = MathExt.GetSizeOfValue(result.Constant);
            }
            if (size >= DataSize.Bit64)
                throw new AssemblerException("64-bit operands cannot be encoded.");
            else if (size == DataSize.None)
                throw new AssemblerException("The operand size is not specified.");

            // Set the parameters.
            if (!asExtraImmediate)
            {
                instr.Immediate = result;
                instr.ImmediateSize = size;
            }
            else
            {
                instr.ExtraImmediate = result;
                instr.ExtraImmediateSize = size;
            }
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, size);
        }
            /// <summary>
            /// Constructs the representation of this instruction variant using the specified operands.
            /// </summary>
            /// <param name="context">The <see cref="Context"/> used.</param>
            /// <param name="operands">The <see cref="Operand"/> objects to encode.</param>
            /// <param name="lockPrefix">Whether to use a lock prefix.</param>
            /// <returns>The encoded instruction.</returns>
            public EncodedInstruction Construct(Context context, IEnumerable<IConstructableOperand> operands, bool lockPrefix)
            {
                #region Contract
                Contract.Requires<ArgumentNullException>(context != null);
                Contract.Requires<ArgumentNullException>(operands != null);
                Contract.Ensures(Contract.Result<EncodedInstruction>() != null);
                #endregion

                EncodedInstruction instr = new EncodedInstruction();

                // Set the lock prefix.
                instr.SetLock(lockPrefix);

                // Set the opcode.
                instr.Opcode = opcode;

                // Set the fixed REG value, if any.
                instr.FixedReg = fixedReg;

                int i = 0;
                foreach(var operand in operands)
                {
                    if (operand == null)
                        // No operand. Nothing to do.
                        continue;
                    if (i >= descriptors.Length)
                        // No descriptors left. Nothing to be done.
                        break;

                    operand.Adjust(descriptors[i]);
                    operand.Construct(context, instr);
                    i++;
                }

                // When the operand size has been explicitly set, set it on the encoded instruction.
                if (operandSize != DataSize.None)
                    instr.SetOperandSize(context.Representation.Architecture.OperandSize, operandSize);

                // We are done.
                return instr;
            }
Exemple #18
0
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 void IConstructableOperand.Construct(Context context, EncodedInstruction instruction)
 {
     this.Construct(context, instruction);
 }
        /// <summary>
        /// Encodes a 64-bit effective address.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        void Encode64BitEffectiveAddress(Context context, EncodedInstruction instr)
        {
            instr.SetModRMByte();

            bool ripRelative      = RelativeAddress ?? context.UseRIPRelativeAddressing;
            bool forceRipRelative = RelativeAddress.HasValue && RelativeAddress == true;

            if (BaseRegister.IsNone && IndexRegister.IsNone)
            {
                if (ripRelative)
                {
                    // [RIP+disp32]

                    instr.ModRM.RM  = 0x05;
                    instr.ModRM.Mod = 0x00;
                }
                else
                {
                    // [disp32]

                    instr.ModRM.RM  = 0x04;
                    instr.ModRM.Mod = 0x00;

                    instr.SetSIBByte();
                    instr.Sib.Base  = 0x05;
                    instr.Sib.Index = 0x04;
                    instr.Sib.Scale = 0x00;
                }

                // Only 32-bit displacements can be encoded without a base and index register.
                instr.DisplacementSize = DataSize.Bit32;
                if (instr.Displacement == null)
                {
                    instr.Displacement = new ReferenceOffset(0);
                }
            }
            else
            {
                if (forceRipRelative)
                {
                    throw new AssemblerException("The effective address cannot be encoded with RIP-relative addressing.");
                }

                if (BaseRegister != Register.RSP && IndexRegister.IsNone)
                {
                    // [REG+...]

                    instr.ModRM.RM = BaseRegister.Value;
                }
                else
                {
                    // [REG+REG*s+...]

                    // Encode the SIB byte too.
                    instr.SetSIBByte();

                    // R/M
                    instr.ModRM.RM = 0x04;

                    // Base
                    if (!BaseRegister.IsNone)
                    {
                        instr.Sib.Base = BaseRegister.Value;
                    }
                    else
                    {
                        instr.Sib.Base = 0x05;
                    }

                    // Index
                    if (!IndexRegister.IsNone)
                    {
                        instr.Sib.Index = IndexRegister.Value;
                    }
                    else
                    {
                        instr.Sib.Index = 0x20;
                    }

                    // Scale
                    instr.Sib.Scale = (byte)((int)Math.Log(Scale, 2));
                }

                if (instr.Displacement == null && BaseRegister == Register.RBP)
                {
                    // [RBP] will be represented as [RBP+disp8].
                    // [RBP+REG*s] will be represented as [RBP+REG*s+disp8].
                    instr.DisplacementSize = DataSize.Bit8;
                    instr.Displacement     = new ReferenceOffset(0);
                }

                switch (instr.DisplacementSize)
                {
                case DataSize.None:
                    instr.ModRM.Mod = 0x00;
                    break;

                case DataSize.Bit8:
                    instr.ModRM.Mod = 0x01;
                    break;

                case DataSize.Bit16:
                case DataSize.Bit32:
                    instr.ModRM.Mod = 0x02;
                    break;

                default:
                    throw new NotSupportedException();
                }
            }
        }
        /// <summary>
        /// Encodes a 16-bit effective address.
        /// </summary>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        void Encode16BitEffectiveAddress(EncodedInstruction instr)
        {
            instr.SetModRMByte();

            // We order the registers in such way that reg1 has the register with the highest number,
            // and reg2 has the register with the lowest number. When a register is not provided, it is put in reg2.
            // This simplifies the following tests, for which the order does not matter.
            var baseReg  = BaseRegister;
            var indexReg = (Scale == 1 ? IndexRegister : Register.None);
            var reg1     = (baseReg.Value >= indexReg.Value ? baseReg : indexReg);
            var reg2     = (baseReg.Value < indexReg.Value ? baseReg : indexReg);

            if (Scale != 1 && Scale != 0)
                throw new AssemblerException("The specified scaling factor is not supported in a 16-bit effective address.");

            // Two cases together deviate from the standard MOD encoding.
            if (reg1 == Register.BP && reg2.IsNone)
            {
                // [BP+...]
                instr.ModRM.RM = 0x06;
                instr.ModRM.Mod = (byte)(instr.DisplacementSize == DataSize.Bit8 ? 0x01 : 0x02);
            }
            else if (reg1.IsNone && reg2.IsNone)
            {
                // [...]
                instr.ModRM.RM = 0x06;
                instr.ModRM.Mod = 0x00;
            }
            else
            {
                // The other cases are straight forward.
                if (reg1 == Register.DI && reg2 == Register.BP)
                    // [BP+DI+...]
                    instr.ModRM.RM = 0x03;
                else if (reg1 == Register.DI && reg2 == Register.BX)
                    // [BX+DI+...]
                    instr.ModRM.RM = 0x01;
                else if (reg1 == Register.DI && reg2.IsNone)
                    // [DI+...]
                    instr.ModRM.RM = 0x05;
                else if (reg1 == Register.SI && reg2 == Register.BP)
                    // [BP+SI+...]
                    instr.ModRM.RM = 0x02;
                else if (reg1 == Register.SI && reg2 == Register.BX)
                    // [BX+SI+...]
                    instr.ModRM.RM = 0x00;
                else if (reg1 == Register.SI && reg2.IsNone)
                    // [SI+...]
                    instr.ModRM.RM = 0x04;
                else if (reg1 == Register.BX && reg2.IsNone)
                    // [BX+...]
                    instr.ModRM.RM = 0x06;
                else
                    throw new AssemblerException("The effective address cannot be encoded");

                switch (instr.DisplacementSize)
                {
                    case DataSize.None:
                        instr.ModRM.Mod = 0x00;
                        break;
                    case DataSize.Bit8:
                        instr.ModRM.Mod = 0x01;
                        break;
                    default:
                        // The default is 16-bit, so larger values get truncated.
                        instr.ModRM.Mod = 0x02;
                        break;
                }
            }
        }
        /// <summary>
        /// Encodes the displacement in the <see cref="EncodedInstruction"/>.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        /// <param name="addressSize">The address size used by the effective address.</param>
        void EncodeDisplacement(Context context, EncodedInstruction instr, DataSize addressSize)
        {
            DataSize displacementSize = DataSize.None;
            ReferenceOffset displacementExpression = null;

            if (Displacement != null)
            {
                // Let's evaluate the displacement expression.
                displacementExpression = Displacement.Compile()(context);

                // Determine the size of the displacement.
                displacementSize = addressSize;
                if (displacementSize == DataSize.None)
                {
                    // Does the result have a (resolved or not resolved) reference?
                    if (displacementExpression.Reference != null && !displacementExpression.Reference.Resolved)
                        // When the result has a reference, use the architecture's address size.
                        displacementSize = context.AddressingMode;
                    else
                        // Otherwise, use the most efficient word size.
                        displacementSize = Extensions.GetSizeOfValue(displacementExpression.Evaluate(context));
                }
            }

            instr.DisplacementSize = displacementSize;
            instr.Displacement = displacementExpression;
        }
Exemple #22
0
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 public abstract void Construct(Context context, EncodedInstruction instruction);
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        internal override void Construct(Context context, EncodedInstruction instr)
        {
            // CONTRACT: Operand

            DataSize addressSize = GetAddressSize(context);

            instr.SetOperandSize(context.Representation.Architecture.OperandSize, Size);

            if (context.Representation.Architecture.OperandSize != DataSize.Bit64 &&
                this.Size == DataSize.Bit64)
                throw new AssemblerException("A 64-bit operand cannot be used with non-64-bit operand sizes.");
            if (context.Representation.Architecture.AddressSize != DataSize.Bit64 &&
                addressSize == DataSize.Bit64)
                throw new AssemblerException("A 64-bit effective address cannot be used with non-64-bit address sizes.");

            EncodeDisplacement(context, instr, addressSize);

            switch(addressSize)
            {
                case DataSize.Bit16:
                    Encode16BitEffectiveAddress(instr);
                    break;
                case DataSize.Bit32:
                    Encode32BitEffectiveAddress(instr);
                    break;
                case DataSize.Bit64:
                    Encode64BitEffectiveAddress(context, instr);
                    break;
                default:
                    throw new NotSupportedException();
            }

            // Address size prefix.
            // When the registers have a width different from the current
            // operating mode width, then we have to add an address size prefix.
            // At this point, we know that the widths are valid.
            instr.SetAddressSize(context.Representation.Architecture.AddressSize, addressSize);
        }
Exemple #24
0
        /// <summary>
        /// Encodes a 32-bit effective address.
        /// </summary>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        private void Encode32BitEffectiveAddress(EncodedInstruction instr)
        {
            instr.SetModRMByte();

            if (baseRegister == Register.None && indexRegister == Register.None)
            {
                // R/M
                instr.ModRM.RM = 0x05;
                // Mod
                instr.ModRM.Mod = 0x00;

                // Only 32-bit displacements can be encoded without a base and index register.
                instr.DisplacementSize = DataSize.Bit32;
                if (instr.Displacement == null)
                {
                    instr.Displacement = new SimpleExpression(0);
                }
            }
            else if (baseRegister != Register.ESP && indexRegister == Register.None)
            {
                // R/M
                instr.ModRM.RM = (byte)((int)baseRegister & 0x07);

                // Displacement.
                if (instr.Displacement == null && baseRegister == Register.EBP)
                {
                    // [EBP] will be represented as [EBP+disp8].
                    instr.DisplacementSize = DataSize.Bit8;
                    instr.Displacement     = new SimpleExpression(0);
                }

                // Mod
                if (instr.DisplacementSize == DataSize.None)
                {
                    instr.ModRM.Mod = 0x00;
                }
                else if (instr.DisplacementSize == DataSize.Bit8)
                {
                    instr.ModRM.Mod = 0x01;
                }
                else if (instr.DisplacementSize <= DataSize.Bit32)
                {
                    instr.ModRM.Mod = 0x02;
                }
            }
            else
            {
                // Encode the SIB byte too.
                instr.SetSIBByte();

                // R/M
                instr.ModRM.RM = 0x04;

                // Displacement
                if (instr.Displacement == null && baseRegister == Register.EBP)
                {
                    // [EBP+REG*s] will be represented as [EBP+REG*s+disp8].
                    instr.DisplacementSize = DataSize.Bit8;
                    instr.Displacement     = new SimpleExpression(0);
                }

                // Mod
                if (instr.DisplacementSize == DataSize.None)
                {
                    instr.ModRM.Mod = 0x00;
                }
                else if (instr.DisplacementSize == DataSize.Bit8)
                {
                    instr.ModRM.Mod = 0x01;
                }
                else if (instr.DisplacementSize <= DataSize.Bit32)
                {
                    instr.ModRM.Mod = 0x02;
                }

                // Base
                instr.Sib.Base = (byte)((int)baseRegister & 0x07);
                if (baseRegister == Register.None)
                {
                    instr.Sib.Base = 0x05;
                }

                // Index
                instr.Sib.Index = (byte)((int)indexRegister & 0x07);
                if (indexRegister == Register.None)
                {
                    instr.Sib.Index = 0x20;
                }

                // Scale
                instr.Sib.Scale = (byte)((int)Math.Log(scale, 2));
            }
        }
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 public override void Construct(Context context, EncodedInstruction instruction)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Encodes a 32-bit effective address.
        /// </summary>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        void Encode32BitEffectiveAddress(EncodedInstruction instr)
        {
            instr.SetModRMByte();

            if (BaseRegister.IsNone && IndexRegister.IsNone)
            {
                // R/M
                instr.ModRM.RM = 0x05;
                // Mod
                instr.ModRM.Mod = 0x00;

                // Only 32-bit displacements can be encoded without a base and index register.
                instr.DisplacementSize = DataSize.Bit32;
                if (instr.Displacement == null)
                    instr.Displacement = new ReferenceOffset(0);
            }
            else if (BaseRegister != Register.ESP && IndexRegister.IsNone)
            {
                // R/M
                instr.ModRM.RM = (byte)(BaseRegister.Full & 0x07);

                // Displacement.
                if (instr.Displacement == null && BaseRegister == Register.EBP)
                {
                    // [EBP] will be represented as [EBP+disp8].
                    instr.DisplacementSize = DataSize.Bit8;
                    instr.Displacement = new ReferenceOffset(0);
                }

                // Mod
                if (instr.DisplacementSize == DataSize.None)
                    instr.ModRM.Mod = 0x00;
                else if (instr.DisplacementSize == DataSize.Bit8)
                    instr.ModRM.Mod = 0x01;
                else if (instr.DisplacementSize <= DataSize.Bit32)
                    instr.ModRM.Mod = 0x02;
            }
            else
            {
                // Encode the SIB byte too.
                instr.SetSIBByte();

                // R/M
                instr.ModRM.RM = 0x04;

                // Displacement
                if (instr.Displacement == null && BaseRegister == Register.EBP)
                {
                    // [EBP+REG*s] will be represented as [EBP+REG*s+disp8].
                    instr.DisplacementSize = DataSize.Bit8;
                    instr.Displacement = new ReferenceOffset(0);
                }

                // Mod
                if (instr.DisplacementSize == DataSize.None)
                    instr.ModRM.Mod = 0x00;
                else if (instr.DisplacementSize == DataSize.Bit8)
                    instr.ModRM.Mod = 0x01;
                else if (instr.DisplacementSize <= DataSize.Bit32)
                    instr.ModRM.Mod = 0x02;

                // Base
                instr.Sib.Base = (byte)(BaseRegister.Full & 0x07);
                if (BaseRegister.IsNone)
                    instr.Sib.Base = 0x05;

                // Index
                instr.Sib.Index = (byte)(IndexRegister.Full & 0x07);
                if (IndexRegister.IsNone)
                    instr.Sib.Index = 0x20;

                // Scale
                instr.Sib.Scale = (byte)((int)Math.Log(Scale, 2));
            }
        }
Exemple #27
0
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 internal abstract void Construct(Context context, EncodedInstruction instruction);
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        public override void Construct(Context context, EncodedInstruction instruction)
        {
            // Let's evaluate the expression.
            var result = Expression?.Compile()(context);

            // Determine the size of the immediate operand.
            DataSize size = PreferredSize;
            if (size == DataSize.None)
            {
                // Does the result have a (resolved or not resolved) reference?
                if (result.Reference != null)
                    // When the result has a reference, use the architecture's operand size.
                    size = context.AddressingMode;
                else
                    // Otherwise, use the most efficient word size.
                    size = Extensions.GetSizeOfValue(result.Constant);
            }
            if (size > DataSize.Bit64)
                throw new AssemblerException("Operands with more than 64 bits cannot be encoded.");
            else if (size == DataSize.None)
                throw new AssemblerException("The operand size is not specified.");

            // Set the parameters.
            if (!asExtraImmediate)
            {
                instruction.Immediate = result;
                instruction.ImmediateSize = size;
            }
            else
            {
                instruction.ExtraImmediate = result;
                instruction.ExtraImmediateSize = size;
            }
            instruction.SetOperandSize(context.AddressingMode, size);
        }
        /// <summary>
        /// Encodes a 64-bit effective address.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        void Encode64BitEffectiveAddress(Context context, EncodedInstruction instr)
        {
            instr.SetModRMByte();

            bool ripRelative = RelativeAddress ?? context.UseRIPRelativeAddressing;
            bool forceRipRelative = RelativeAddress.HasValue && RelativeAddress == true;

            if (BaseRegister.IsNone && IndexRegister.IsNone)
            {
                if (ripRelative)
                {
                    // [RIP+disp32]

                    instr.ModRM.RM = 0x05;
                    instr.ModRM.Mod = 0x00;
                }
                else
                {
                    // [disp32]

                    instr.ModRM.RM = 0x04;
                    instr.ModRM.Mod = 0x00;

                    instr.SetSIBByte();
                    instr.Sib.Base = 0x05;
                    instr.Sib.Index = 0x04;
                    instr.Sib.Scale = 0x00;
                }

                // Only 32-bit displacements can be encoded without a base and index register.
                instr.DisplacementSize = DataSize.Bit32;
                if (instr.Displacement == null)
                    instr.Displacement = new ReferenceOffset(0);
            }
            else
            {
                if (forceRipRelative)
                    throw new AssemblerException("The effective address cannot be encoded with RIP-relative addressing.");

                if (BaseRegister != Register.RSP && IndexRegister.IsNone)
                {
                    // [REG+...]

                    instr.ModRM.RM = BaseRegister.Value;
                }
                else
                {
                    // [REG+REG*s+...]

                    // Encode the SIB byte too.
                    instr.SetSIBByte();

                    // R/M
                    instr.ModRM.RM = 0x04;

                    // Base
                    if (!BaseRegister.IsNone)
                        instr.Sib.Base = BaseRegister.Value;
                    else
                        instr.Sib.Base = 0x05;

                    // Index
                    if (!IndexRegister.IsNone)
                        instr.Sib.Index = IndexRegister.Value;
                    else
                        instr.Sib.Index = 0x20;

                    // Scale
                    instr.Sib.Scale = (byte)((int)Math.Log(Scale, 2));
                }

                if (instr.Displacement == null && BaseRegister == Register.RBP)
                {
                    // [RBP] will be represented as [RBP+disp8].
                    // [RBP+REG*s] will be represented as [RBP+REG*s+disp8].
                    instr.DisplacementSize = DataSize.Bit8;
                    instr.Displacement = new ReferenceOffset(0);
                }

                switch (instr.DisplacementSize)
                {
                    case DataSize.None:
                        instr.ModRM.Mod = 0x00;
                        break;
                    case DataSize.Bit8:
                        instr.ModRM.Mod = 0x01;
                        break;
                    case DataSize.Bit16:
                    case DataSize.Bit32:
                        instr.ModRM.Mod = 0x02;
                        break;
                    default:
                        throw new NotSupportedException();
                }
            }
        }
        /// <summary>
        /// Encodes the displacement in the <see cref="EncodedInstruction"/>.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        /// <param name="addressSize">The address size used by the effective address.</param>
        private void EncodeDisplacement(Context context, EncodedInstruction instr, DataSize addressSize)
        {
            #region Contract
            Contract.Requires<ArgumentNullException>(context != null);
            Contract.Requires<ArgumentNullException>(instr != null);
            #endregion

            DataSize displacementSize = DataSize.None;
            SimpleExpression displacementExpression = null;

            if (displacement != null)
            {
                // Let's evaluate the displacement expression.
                displacementExpression = displacement(context);

                // Determine the size of the displacement.
                displacementSize = addressSize;
                if (displacementSize == DataSize.None)
                {
                    // Does the result have a (resolved or not resolved) reference?
                    if (displacementExpression.Reference != null && !displacementExpression.Reference.Resolved)
                        // When the result has a reference, use the architecture's address size.
                        displacementSize = context.Representation.Architecture.AddressSize;
                    else
                        // Otherwise, use the most efficient word size.
                        displacementSize = MathExt.GetSizeOfValue(displacementExpression.Evaluate(context));	//.Constant);
                }
            }

            instr.DisplacementSize = displacementSize;
            instr.Displacement = displacementExpression;
        }
 public void Construct(Context context, EncodedInstruction instruction)
 {
     Contract.Requires <ArgumentNullException>(context != null);
     Contract.Requires <ArgumentNullException>(instruction != null);
 }
Exemple #32
0
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 void IConstructableOperand.Construct(Context context, EncodedInstruction instruction)
 {
     this.Construct(context, instruction);
 }
 /// <summary>
 /// Constructs the operand's representation.
 /// </summary>
 /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
 /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param>
 public override void Construct(Context context, EncodedInstruction instruction)
 {
     throw new NotImplementedException();
 }
Exemple #34
0
        /// <summary>
        /// Encodes a 16-bit effective address.
        /// </summary>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        void Encode16BitEffectiveAddress(EncodedInstruction instr)
        {
            instr.SetModRMByte();

            // We order the registers in such way that reg1 has the register with the highest number,
            // and reg2 has the register with the lowest number. When a register is not provided, it is put in reg2.
            // This simplifies the following tests, for which the order does not matter.
            var baseReg  = BaseRegister;
            var indexReg = (Scale == 1 ? IndexRegister : Register.None);
            var reg1     = (baseReg.Value >= indexReg.Value ? baseReg : indexReg);
            var reg2     = (baseReg.Value < indexReg.Value ? baseReg : indexReg);

            if (Scale != 1 && Scale != 0)
            {
                throw new AssemblerException("The specified scaling factor is not supported in a 16-bit effective address.");
            }

            // Two cases together deviate from the standard MOD encoding.
            if (reg1 == Register.BP && reg2.IsNone)
            {
                // [BP+...]
                instr.ModRM.RM  = 0x06;
                instr.ModRM.Mod = (byte)(instr.DisplacementSize == DataSize.Bit8 ? 0x01 : 0x02);
            }
            else if (reg1.IsNone && reg2.IsNone)
            {
                // [...]
                instr.ModRM.RM  = 0x06;
                instr.ModRM.Mod = 0x00;
            }
            else
            {
                // The other cases are straight forward.
                if (reg1 == Register.DI && reg2 == Register.BP)
                {
                    // [BP+DI+...]
                    instr.ModRM.RM = 0x03;
                }
                else if (reg1 == Register.DI && reg2 == Register.BX)
                {
                    // [BX+DI+...]
                    instr.ModRM.RM = 0x01;
                }
                else if (reg1 == Register.DI && reg2.IsNone)
                {
                    // [DI+...]
                    instr.ModRM.RM = 0x05;
                }
                else if (reg1 == Register.SI && reg2 == Register.BP)
                {
                    // [BP+SI+...]
                    instr.ModRM.RM = 0x02;
                }
                else if (reg1 == Register.SI && reg2 == Register.BX)
                {
                    // [BX+SI+...]
                    instr.ModRM.RM = 0x00;
                }
                else if (reg1 == Register.SI && reg2.IsNone)
                {
                    // [SI+...]
                    instr.ModRM.RM = 0x04;
                }
                else if (reg1 == Register.BX && reg2.IsNone)
                {
                    // [BX+...]
                    instr.ModRM.RM = 0x06;
                }
                else
                {
                    throw new AssemblerException("The effective address cannot be encoded");
                }

                switch (instr.DisplacementSize)
                {
                case DataSize.None:
                    instr.ModRM.Mod = 0x00;
                    break;

                case DataSize.Bit8:
                    instr.ModRM.Mod = 0x01;
                    break;

                default:
                    // The default is 16-bit, so larger values get truncated.
                    instr.ModRM.Mod = 0x02;
                    break;
                }
            }
        }
        /// <summary>
        /// Constructs the operand's representation.
        /// </summary>
        /// <param name="context">The <see cref="Context"/> in which the operand is used.</param>
        /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param>
        internal override void Construct(Context context, EncodedInstruction instr)
        {
            // CONTRACT: Operand

            if (context.Representation.Architecture.OperandSize != DataSize.Bit64 &&
                register.GetSize() == DataSize.Bit64)
            {
                throw new AssemblerException(String.Format(
                    "The 64-bit register {0} cannot be used with non-64-bit operand sizes.",
                    Enum.GetName(typeof(Register), register)));
            }

            // Encode the register as part of the opcode or ModRM byte.
            switch (encoding)
            {
                case OperandEncoding.Default:
                    instr.SetModRMByte();
                    instr.ModRM.Reg = Register.GetValue();
                    break;
                case OperandEncoding.AddToOpcode:
                    instr.OpcodeReg = Register.GetValue();
                    break;
                case OperandEncoding.ModRm:
                    instr.SetModRMByte();
                    instr.ModRM.Mod = 0x03;
                    instr.ModRM.RM = Register.GetValue();
                    break;
                case OperandEncoding.Ignore:
                    // The operand is ignored.
                    break;
            }

            // Set the operand size to the size of the register.
            instr.SetOperandSize(context.Representation.Architecture.OperandSize, Register.GetSize());
        }