Exemplo n.º 1
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 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>
        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;
        }
Exemplo n.º 3
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 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);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ExpressionEmittable"/> class.
 /// </summary>
 /// <param name="expression">The expression of the value.</param>
 /// <param name="size">The size of the result.</param>
 public ExpressionEmittable(ReferenceOffset expression, DataSize size)
 {
     Expression = expression;
     Size       = size;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ExpressionEmittable"/> class.
 /// </summary>
 /// <param name="expression">The expression of the value.</param>
 /// <param name="size">The size of the result.</param>
 public ExpressionEmittable(ReferenceOffset expression, DataSize size)
 {
     Expression = expression;
     Size = size;
 }
        /// <summary>
        /// Emits the immediate value as part of the instruction, if any.
        /// </summary>
        /// <param name="writer">The <see cref="BinaryWriter"/> to which the encoded instruction is written.</param>
        /// <param name="instructionOffset">The offset of the instruction in the stream underlying
        /// <paramref name="writer"/>.</param>
        /// <param name="context">The <see cref="Context"/> of the instruction.</param>
        /// <param name="expression">The <see cref="ReferenceOffset"/> to emit.</param>
        /// <param name="size">The size of the value to emit.</param>
        void EmitReferenceOffset(BinaryWriter writer, long instructionOffset, Context context, ReferenceOffset expression, DataSize size)
        {
            if (expression == null)
            {
                return;
            }

            // Number of bytes before the expression.
            var        relocationDiff = (ulong)(writer.BaseStream.Position - instructionOffset);
            Relocation relocation     = null;

            var actualValue = expression.Evaluate(context);

            if (expression.Reference != null)
            {
                relocation = new Relocation(expression.Reference.Symbol, (long)context.Address, actualValue, RelocationType.Default32);
            }

            // Emit the expression's value.
            EmitConstant(writer, size, actualValue);

            // Add the relocation to the context.
            if (relocation != null)
            {
                relocation.Offset += (long)relocationDiff;
                context.RelocationTable.Add(relocation);
            }
        }