예제 #1
0
파일: Xor.cs 프로젝트: zrbruce/FlingOS
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Add floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Xor()
                    {
                        Src = "EBX", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the same size.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Pop item B to ecx:ebx
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    //Pop item A to edx:eax
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });
                    //Or ecx:ebx with edx:eax
                    conversionState.Append(new ASMOps.Xor()
                    {
                        Src = "EBX", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Xor()
                    {
                        Src = "ECX", Dest = "EDX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
            }
        }
예제 #2
0
파일: Ldelem.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            Type elementType = null;
            bool pushValue   = true;
            int  sizeToPush  = 4;
            bool signExtend  = true;
            bool isFloat     = false;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldelem:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            }
            break;

            case OpCodes.Ldelema:
            {
                signExtend = false;
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

                pushValue = false;
            }
            break;

            case OpCodes.Ldelem_R4:
            case OpCodes.Ldelem_R8:
                //TODO - Add more LdElem op variants support
                throw new NotSupportedException("Ldelem op variant not supported yet!");

            case OpCodes.Ldelem_I1:
                sizeToPush  = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Ldelem_I2:
                sizeToPush  = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Ldelem_U1:
                sizeToPush  = 1;
                signExtend  = false;
                elementType = typeof(byte);
                break;

            case OpCodes.Ldelem_U2:
                sizeToPush  = 2;
                signExtend  = false;
                elementType = typeof(UInt16);
                break;

            case OpCodes.Ldelem_Ref:
                signExtend  = false;
                elementType = null;
                break;

            case OpCodes.Ldelem_U4:
                signExtend  = false;
                elementType = typeof(UInt32);
                break;

            case OpCodes.Ldelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Ldelem_I8:
                sizeToPush  = 8;
                elementType = typeof(Int64);
                break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("LdElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Push the element onto the stack

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Index of element to get as Int32 (word)
            // 1. Array object reference as address (word)

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();

            // 1. Check array reference is not null
            //      1.1. Move array ref into $t0
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            //      1.1. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", BranchType = ASMOps.BranchOp.BranchNotZero, DestILPosition = currOpPosition, Extension = "Continue1", UnsignedTest = true
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue1"
            });

            // 2. Check array element type is correct
            //      2.1. Move element type ref into $t0
            //      2.2. Move element type ref from array object into $t1
            //      2.3. Compare $t0 to $t1
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into $t0
            int elemTypeOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "elemType").OffsetInBytes;

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into $t0
            //      3.2. Move array length into $t1
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            //      3.1. Move index into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      3.2. Move array length into $t2
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            //              - Move array ref into $t1
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "4($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //              - Move length value (offset($t1)) into $t1
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = lengthOffset.ToString() + "($t1)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t1", lengthOffset, 4);
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "$zero", BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, DestILPosition = currOpPosition, Extension = "Continue3_1", UnsignedTest = false
            });
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t0", Src2 = "$t1", BranchType = ASMOps.BranchOp.BranchLessThan, DestILPosition = currOpPosition, Extension = "Continue3_2", UnsignedTest = false
            });
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_2"
            });
            // 4. Calculate address of element
            //      4.1. Pop index into $t1
            //      4.2. Pop array ref into $t0
            //      4.3. Move element type ref (from array ref) into $t0
            //      4.4. Move IsValueType (from element ref type) into $t2
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            //      4.6. Move Size (from element type ref) into $t0
            //      4.7. Skip over 4.8.
            //      4.8. Move StackSize (from element type ref) into $t0
            //      4.9. Mulitply $t0 by $t1 (index by element size)
            //      4.10. Move array ref into $t1
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            //      4.12. Add $t0 and $t1 (array ref + fields + (index * element size))

            //      4.1. Pop index into $t1
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });
            //      4.2. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      4.3. Move element type ref (from array ref) into $t0
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = elemTypeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", elemTypeOffset, 4);
            //      4.4. Move IsValueType (from element ref type) into $t2
            int isValueTypeOffset = conversionState.GetTypeFieldOffset("IsValueType");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
            });
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = isValueTypeOffset.ToString() + "($t0)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t2", isValueTypeOffset, 1);
            //      4.5. If IsValueType, continue to 4.6., else goto 4.8.
            conversionState.Append(new ASMOps.Branch()
            {
                Src1 = "$t2", BranchType = ASMOps.BranchOp.BranchZero, DestILPosition = currOpPosition, Extension = "Continue4_1", UnsignedTest = true
            });
            //      4.6. Move Size (from element type ref) into $t0
            int sizeOffset = conversionState.GetTypeFieldOffset("Size");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = sizeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", sizeOffset, 4);
            //      4.7. Skip over 4.8.
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Continue4_2"
            });
            //      4.8. Move StackSize (from element type ref) into $t0
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_1"
            });
            int stackSizeOffset = conversionState.GetTypeFieldOffset("StackSize");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = stackSizeOffset + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", stackSizeOffset, 4);
            //      4.9. Mulitply $t0 by $t1 (index by element size)
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_2"
            });
            conversionState.Append(new ASMOps.Mul()
            {
                Src1 = "$t1", Src2 = "$t0", Signed = true
            });
            //      4.10. Pop array ref into $t1
            conversionState.Append(new ASMOps.Mflo()
            {
                Dest = "$t0"
            });
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });
            //      4.11. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;

            #region Offset calculation
            {
                Types.FieldInfo highestOffsetFieldInfo = arrayTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderByDescending(x => x.OffsetInBytes).First();
                Types.TypeInfo  fieldTypeInfo          = conversionState.TheILLibrary.GetTypeInfo(highestOffsetFieldInfo.UnderlyingInfo.FieldType);
                allFieldsOffset = highestOffsetFieldInfo.OffsetInBytes + (fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes);
            }
            #endregion
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t1", Src2 = allFieldsOffset.ToString(), Dest = "$t1"
            });
            //      4.12. Add $t0 and $t1 (array ref + fields + (index * element size))
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t1", Src2 = "$t0", Dest = "$t0"
            });

            // 5. Push the element onto the stack
            //      5.1. Push value at ($t0) (except for LdElemA op in which case just push address)
            if (pushValue)
            {
                switch (sizeToPush)
                {
                case 1:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 1, signExtend);
                    break;

                case 2:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Halfword, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 2, signExtend);

                    break;

                case 4:
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    break;

                case 8:
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4);
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg });
                    GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t2", 4, 4);
                    break;
                }
                if (sizeToPush == 8)
                {
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t2"
                    });
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t1"
                });
            }
            else
            {
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0"
                });
            }

            Types.TypeInfo elemTypeInfo = elementType == null ? null : conversionState.TheILLibrary.GetTypeInfo(elementType);

            //      5.2. Pop index and array ref from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat            = isFloat,
                isNewGCObject      = false,
                isGCManaged        = pushValue ? (elementType == null || elemTypeInfo.IsGCManaged) : false,
                isValue            = pushValue ? (elementType != null && elemTypeInfo.IsValueType) : false
            });
        }
예제 #3
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if field to load is a floating value or the field to load
        /// is not of size 4 or 8 bytes.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Get the field's token that is used to get FieldInfo from the assembly
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            //Get the field info from the referencing assembly
            FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            //Get the database type information about the object that contains the field
            Types.TypeInfo objTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.DeclaringType);
            int            offset      = conversionState.TheILLibrary.GetFieldInfo(objTypeInfo, theField.Name).OffsetInBytes;

            //Is the value to load a floating pointer number?
            bool valueisFloat = Utilities.IsFloat(theField.FieldType);

            //Get the size of the value to load (in bytes, as it will appear on the stack)
            Types.TypeInfo fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
            int            stackSize     = fieldTypeInfo.SizeOnStackInBytes;
            int            memSize       = theField.FieldType.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : stackSize;

            //Pop the object pointer from our stack
            StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop();

            //If the value to load is a float, erm...abort...
            if (valueisFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Loading fields of type float not supported yet!");
            }

            //Pop object pointer
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "ECX"
            });
            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldflda)
            {
                conversionState.Append(new ASMOps.Add()
                {
                    Src = offset.ToString(), Dest = "ECX"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "ECX"
                });

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false
                });
            }
            else
            {
                //Push value at pointer+offset
                int sizeNotInMem = stackSize - memSize;
                int sizeToSub    = (sizeNotInMem / 2) * 2; //Rounds down
                for (int i = 0; i < sizeToSub; i += 2)
                {
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0"
                    });
                }
                for (int i = memSize + (memSize % 2); i > 0; i -= 2)
                {
                    if (sizeToSub != sizeNotInMem)
                    {
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "0", Dest = "AX"
                        });
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "[ECX+" + (offset + i - 2).ToString() + "]", Dest = "AL"
                        });
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "AX"
                        });
                    }
                    else
                    {
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "[ECX+" + (offset + i - 2).ToString() + "]", Dest = "AX"
                        });
                        conversionState.Append(new ASMOps.Push()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "AX"
                        });
                    }
                }

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = valueisFloat,
                    sizeOnStackInBytes = stackSize,
                    isGCManaged        = fieldTypeInfo.IsGCManaged
                });
            }
        }
예제 #4
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Stores the integer value to push onto the stack
            long iValue = 0;
            //Stores the float value to push onto the stack
            double fValue = 0;
            //Indicates whether we should be pushing a float or integer value
            bool isFloat = false;
            //The number of bytes to push (e.g. 4 for Int32, 8 for Int64)
            int numBytes = 0;

            //Load the constant and type of constant
            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldc_I4:
                iValue   = Utilities.ReadInt32(theOp.ValueBytes, 0);
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_0:
                iValue   = 0;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_1:
                iValue   = 1;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_2:
                iValue   = 2;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_3:
                iValue   = 3;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_4:
                iValue   = 4;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_5:
                iValue   = 5;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_6:
                iValue   = 6;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_7:
                iValue   = 7;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_8:
                iValue   = 8;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_M1:
                iValue   = -1;
                numBytes = 4;
                break;

            case OpCodes.Ldc_I4_S:
                iValue   = (Int32)(sbyte)theOp.ValueBytes[0];
                numBytes = 4;
                break;

            case OpCodes.Ldc_I8:
                iValue   = Utilities.ReadInt64(theOp.ValueBytes, 0);
                numBytes = 8;
                break;

            case OpCodes.Ldc_R4:
                fValue   = Utilities.ReadFloat32(theOp.ValueBytes, 0);
                numBytes = 4;
                isFloat  = true;
                break;

            case OpCodes.Ldc_R8:
                fValue   = Utilities.ReadFloat64(theOp.ValueBytes, 0);
                numBytes = 8;
                isFloat  = true;
                break;
            }

            //Stores the bytes to be pushed onto the stack
            byte[] valueBytes = new byte[0];
            if (isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Float constants not supported yet!");
            }
            else
            {
                //Get the bytes for the value
                valueBytes = BitConverter.GetBytes(iValue);
            }

            //If pushing Int64:
            if (numBytes == 8)
            {
                //Push the high-bits as a dword

                //Start the push (0x indicates what follows is a hex number)
                string valueToPush = "0x";
                //High bits
                //Process bits in reverse order i.e. highest bit first
                for (int i = numBytes - 1; i > 3; i--)
                {
                    valueToPush += valueBytes[i].ToString("X2");
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = valueToPush
                });

                //Then push the low-bits as a dword
                //See above
                valueToPush = "0x";
                //Low bits
                for (int i = numBytes - 4 - 1; i > -1; i--)
                {
                    valueToPush += valueBytes[i].ToString("X2");
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = valueToPush
                });
            }
            else
            {
                //See above

                string valueToPush = "0x";
                for (int i = numBytes - 1; i > -1; i--)
                {
                    valueToPush += valueBytes[i].ToString("X2");
                }
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = valueToPush
                });
            }

            //Push the constant onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = numBytes,
                isFloat            = isFloat,
                isGCManaged        = false,
                isValue            = true
            });
        }
예제 #5
0
        /// <summary>
        /// See base class documentation.
        /// <para>To Do's:</para>
        /// <list type="bullet">
        /// <item>
        /// <term>To do</term>
        /// <description>Implement loading of float arguments.</description>
        /// </item>
        /// </list>
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a float argument is required as it currently hasn't been
        /// implemented.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Thrown when an invalid number of bytes is specified for the argument to load.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Get the index of the argument to load
            Int16 index = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldarg:
                index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                break;

            case OpCodes.Ldarg_0:
                index = 0;
                break;

            case OpCodes.Ldarg_1:
                index = 1;
                break;

            case OpCodes.Ldarg_2:
                index = 2;
                break;

            case OpCodes.Ldarg_3:
                index = 3;
                break;

            case OpCodes.Ldarg_S:
                index = (Int16)theOp.ValueBytes[0];
                break;

            case OpCodes.Ldarga:
                index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                break;

            case OpCodes.Ldarga_S:
                index = (Int16)theOp.ValueBytes[0];
                break;
            }

            Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index];
            if (Utilities.IsFloat(argInfo.TheTypeInfo.UnderlyingType))
            {
                //SUPPORT - floats
                throw new NotSupportedException("Float arguments not supported yet!");
            }

            //Used to store the number of bytes to add to EBP to get to the arg
            int BytesOffsetFromEBP = argInfo.Offset;

            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga ||
                (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S)
            {
                //Push the address of the argument onto the stack

                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$fp", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                });
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$t2", Src2 = BytesOffsetFromEBP.ToString(), Dest = "$t2"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t2"
                });

                //Push the address onto our stack
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    sizeOnStackInBytes = 4,
                    isFloat            = false,
                    isGCManaged        = false,
                    isValue            = false
                });
            }
            else
            {
                //Push the argument onto the stack
                Types.TypeInfo paramTypeInfo = argInfo.TheTypeInfo;
                int            bytesForArg   = paramTypeInfo.SizeOnStackInBytes;

                if (bytesForArg % 4 != 0)
                {
                    throw new ArgumentException("Cannot load arg! Don't understand byte size of the arg! Size:" + bytesForArg);
                }

                while (bytesForArg > 0)
                {
                    bytesForArg -= 4;

                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = (BytesOffsetFromEBP + bytesForArg).ToString() + "($fp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });
                }

                //Push the arg onto our stack
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    sizeOnStackInBytes = paramTypeInfo.SizeOnStackInBytes,
                    isFloat            = false,
                    isGCManaged        = paramTypeInfo.IsGCManaged,
                    isValue            = paramTypeInfo.IsValueType
                });
            }
        }
예제 #6
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if attempt to add a floating point number since floats are not supported yet.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either stack argument is &lt; 4 bytes in size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop the operands from our stack in reverse order
            //i.e. second operand was pushed last so comes off the
            //top of the stack first

            //Pop item B - one of the items to add
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            //Pop item A - the other item to add
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            //If either item item is < 4 bytes then we have a stack error.
            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            //If either item is floating point, we must use floating point conversions
            //and floating point arithmetic
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                //  - We need to convert items to float if necessary
                //  - Then use floating point arithmetic
                //  - Then push the result onto the stack and mark it as float
                // Note: Check but I think floating point arithmetic is done using
                //       XMM registers and their specific ops.
                throw new NotSupportedException("Add floats is unsupported!");
            }
            else
            {
                //If both items are Int32s (or UInt32s - it is irrelevant)
                //Note: IL handles type conversions using other ops
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    //Add the two
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t0", Src2 = "$t1", Dest = "$t1"
                    });
                    //Push the result onto the stack
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t1"
                    });

                    //Push the result onto our stack
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false
                    });
                }
                //Invalid if the operands are of different sizes.
                //Note: This usually occurs when a previous IL op failed to process properly.
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the same size.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Pop item B to $t2:$t1
                    //Pop low bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    //Pop high bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t2"
                    });
                    //Pop item A to $t3:$t0
                    //Pop low bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    //Pop high bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t3"
                    });
                    //Add $t2:$t1 to $t3:$t0
                    //Add low bits
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t1", Src2 = "$t0", Dest = "$t4", Unsigned = true
                    });
                    //Add carry bit to $t5
                    conversionState.Append(new ASMOps.Sltu()
                    {
                        Src1 = "$t4", Src2 = "$t1", Dest = "$t5"
                    });
                    //Add high bits including any carry from
                    //when low bits were added
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t5", Src2 = "$t3", Dest = "$t5", Unsigned = true
                    });
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src1 = "$t5", Src2 = "$t2", Dest = "$t3", Unsigned = true
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t4", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                    });
                    //Push the result
                    //Push high bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t3"
                    });
                    //Push low bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    //Push the result onto our stack
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false
                    });
                }
            }
        }
예제 #7
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            Type elementType = null;

            Types.TypeInfo elemTypeInfo = null;
            //bool pushValue = true;
            int  sizeOnHeap  = 4;
            int  sizeOnStack = 4;
            bool isFloat     = false;

            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Stelem:
            {
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType  = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
                elemTypeInfo = conversionState.TheILLibrary.GetTypeInfo(elementType);
                sizeOnStack  = elemTypeInfo.SizeOnStackInBytes;
                sizeOnHeap   = elemTypeInfo.IsValueType ? elemTypeInfo.SizeOnHeapInBytes : elemTypeInfo.SizeOnStackInBytes;
            }
            break;

            case OpCodes.Stelem_R4:
            case OpCodes.Stelem_R8:
                //TODO - Add more StElem op variants support
                throw new NotSupportedException("Stelem op variant not supported yet!");

            case OpCodes.Stelem_I1:
                sizeOnHeap  = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Stelem_I2:
                sizeOnHeap  = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Stelem_Ref:
                elementType = null;
                break;

            case OpCodes.Stelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Stelem_I8:
                sizeOnHeap  = 8;
                sizeOnStack = 8;
                elementType = typeof(Int64);
                break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("StElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Pop the value from the stack into the element

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Value to store (dword or 2 dwords)
            // 1. Index of element to get as Int32 (dword)
            // 2. Array object reference as address (dword)

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();

            // 1. Check array reference is not null
            //      1.1. Move array ref into EAX
            //      1.2. Compare EAX (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            //      1.1. Move array ref into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + (sizeOnStack + 4) + "]", Dest = "EAX"
            });
            //      1.2. Compare EAX (array ref) to 0
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "Continue1"
            });
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue1"
            });

            // 2. Check array element type is correct
            //      2.1. Move element type ref into EAX
            //      2.2. Move element type ref from array object into EBX
            //      2.3. Compare EAX to EBX
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into EAX
            //if (elementType != null)
            //{
            //    result.AppendLine(string.Format("mov EAX, {0}", conversionState.GetTypeIdString(conversionState.GetTypeID(elementType))));
            //}
            //else
            //{
            //    //Should be the same for all classes since they are (indirectly) derived from ObjectWithType
            //    int typeOffset = conversionState.GetFieldOffset(arrayDBType, "_Type");

            //    //      - Move value (which is a ref) into EAX
            //    GlobalMethods.CheckAddrFromRegister(conversionState, "ESP", 0);
            //    result.AppendLine("mov EAX, [ESP]");
            //    //      - Move value type ref (from value (ref)) into EAX
            //    GlobalMethods.CheckAddrFromRegister(conversionState, "EAX", typeOffset);
            //    result.AppendLine(string.Format("mov EAX, [EAX+{0}]", typeOffset));
            //}
            ////      2.2. Move element type ref from array object into EBX
            ////              - Move array ref into EBX
            //GlobalMethods.CheckAddrFromRegister(conversionState, "ESP", sizeToPop == 8 ? 12 : 8);
            //result.AppendLine(string.Format("mov EBX, [ESP+{0}]", sizeToPop == 8 ? 12 : 8));
            ////              - Move elemType ref ([EBX+offset]) into EBX
            int elemTypeOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "elemType").OffsetInBytes;

            //GlobalMethods.CheckAddrFromRegister(conversionState, "EBX", elemTypeOffset);
            //result.AppendLine(string.Format("mov EBX, [EBX+{0}]", elemTypeOffset));
            ////      2.3. Compare EAX to EBX
            //result.AppendLine("cmp EAX, EBX");
            ////      2.4. If the same, jump to continue execution further down
            //result.AppendLine("je " + ContinueExecutionLabel2);
            ////      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException
            //result.AppendLine(string.Format("call {0}", conversionState.GetMethodID(conversionState.ThrowArrayTypeMismatchExceptionMethod)));
            //result.AppendLine(ContinueExecutionLabel2 + ":");

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into EAX
            //      3.2. Move array length into EBX
            //      3.2. Compare EAX to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare EAX to EBX
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            //      3.1. Move index into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + sizeOnStack + "]", Dest = "EAX"
            });
            //      3.2. Move array length into ECX
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            //              - Move array ref into EBX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + (sizeOnStack + 4) + "]", Dest = "EBX"
            });
            //              - Move length value ([EBX+offset]) into EBX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EBX+" + lengthOffset.ToString() + "]", Dest = "EBX"
            });
            //      3.2. Compare EAX to 0
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "0"
            });
            //      3.3. Jump if greater than to next test condition (3.5)
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpGreaterThanEqual, DestILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.5. Compare EAX to EBX
            conversionState.Append(new ASMOps.Cmp()
            {
                Arg1 = "EAX", Arg2 = "EBX"
            });
            //      3.6. Jump if less than to continue execution further down
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpLessThan, DestILPosition = currOpPosition, Extension = "Continue3_2"
            });
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_2"
            });

            // 4. Calculate address of element
            //      4.1. Move index into EDX
            //      4.2. Move array ref into EAX
            //      4.3. Move element type ref (from array ref) into EAX
            //      4.4. Push EAX
            //      4.5. Move IsValueType (from element ref type) into EAX
            //      4.6. If IsValueType, continue to 4.7., else goto 4.10.
            //      4.7. Pop EAX
            //      4.8. Move Size (from element type ref) into EAX
            //      4.9. Skip over 4.9. and 4.10.
            //      4.10. Pop EAX
            //      4.11. Move StackSize (from element type ref) into EAX
            //      4.12. Mulitply EAX by EDX (index by element size)
            //      4.13. Move array ref into EDX
            //      4.14. Add enough to go past Kernel.FOS_System.Array fields
            //      4.15. Add EAX and EBX (array ref + fields + (index * element size))


            //      4.1. Move index into EDX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + sizeOnStack + "]", Dest = "EDX"
            });
            //      4.2. Move array ref into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + (sizeOnStack + 4) + "]", Dest = "EAX"
            });
            //      4.3. Move element type ref (from array ref) into EAX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + elemTypeOffset.ToString() + "]", Dest = "EAX"
            });
            //      4.4. Push EAX
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = "EAX"
            });
            //      4.5. Move IsValueType (from element ref type) into EAX
            int isValueTypeOffset = conversionState.GetTypeFieldOffset("IsValueType");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Byte, Src = "[EAX+" + isValueTypeOffset.ToString() + "]", Dest = "AL"
            });
            //      4.6. If IsValueType, continue to 4.7., else goto 4.9.
            conversionState.Append(new ASMOps.Test()
            {
                Arg1 = "EAX", Arg2 = "1"
            });
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.JumpZero, DestILPosition = currOpPosition, Extension = "Continue4_1"
            });
            //      4.7. Pop EAX
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
            });
            //      4.8. Move Size (from element type ref) into EAX
            int sizeOffset = conversionState.GetTypeFieldOffset("Size");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + sizeOffset.ToString() + "]", Dest = "EAX"
            });
            //      4.9. Skip over 4.9. and 4.10.
            conversionState.Append(new ASMOps.Jmp()
            {
                JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "Continue4_2"
            });
            //      4.10. Pop EAX
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_1"
            });
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "EAX"
            });
            //      4.11. Move StackSize (from element type ref) into EAX
            int stackSizeOffset = conversionState.GetTypeFieldOffset("StackSize");

            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + stackSizeOffset.ToString() + "]", Dest = "EAX"
            });
            //      4.12. Mulitply EAX by EDX (index by element size)
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_2"
            });
            conversionState.Append(new ASMOps.Mul()
            {
                Arg = "EDX"
            });
            //      4.13. Move array ref into EDX
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Dword, Dest = "EDX", Src = "[ESP+" + (sizeOnStack + 4) + "]"
            });
            //      4.14. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;

            #region Offset calculation
            {
                Types.FieldInfo highestOffsetFieldInfo = arrayTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderByDescending(x => x.OffsetInBytes).First();
                Types.TypeInfo  fieldTypeInfo          = conversionState.TheILLibrary.GetTypeInfo(highestOffsetFieldInfo.UnderlyingInfo.FieldType);
                allFieldsOffset = highestOffsetFieldInfo.OffsetInBytes + (fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes);
            }
            #endregion
            conversionState.Append(new ASMOps.Add()
            {
                Src = allFieldsOffset.ToString(), Dest = "EDX"
            });
            //      4.15. Add EAX and EDX (array ref + fields + (index * element size))
            conversionState.Append(new ASMOps.Add()
            {
                Src = "EDX", Dest = "EAX"
            });

            // 5. Pop the element from the stack to array
            //      5.1. Pop value bytes from stack to array
            //      5.2. Add 8 to ESP to remove Index and Array ref
            for (int i = 0; i < sizeOnStack; i += 4)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                });

                switch (sizeOnHeap)
                {
                case 1:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "CL", Dest = "[EAX+" + i + "]"
                    });
                    break;

                case 2:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "CX", Dest = "[EAX+" + i + "]"
                    });
                    break;

                case 3:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "CL", Dest = "[EAX+" + i + "]"
                    });
                    conversionState.Append(new ASMOps.Shr()
                    {
                        Src = "16", Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "CX", Dest = "[EAX+" + (i + 1) + "]"
                    });
                    break;

                default:
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "ECX", Dest = "[EAX+" + i + "]"
                    });
                    break;
                }

                sizeOnHeap -= 4;
            }

            //      5.2. Add 8 to ESP to remove Index and Array ref
            conversionState.Append(new ASMOps.Add()
            {
                Src = "8", Dest = "ESP"
            });

            //      5.2. Pop index, array ref and value from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
        }
예제 #8
0
파일: Br.cs 프로젝트: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if branch test operand value is a floating point value.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //This will store the offset from the current next op's position
            //to the IL op to jump to.
            int ILOffset = 0;

            //This will store the jump operation - by default, the basic jump op
            ASMOps.JmpOp jumpOp       = ASMOps.JmpOp.Jump;
            bool         UnsignedTest = false;

            ASMOps.JmpOp inverseJumpOp  = ASMOps.JmpOp.None;
            bool         isNegativeTest = false;

            //The value for the jump op to test against - currently always "0" since on jnz and jz ops are used.
            string testVal = "0";

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Br:
                //Load the IL offset as signed Int 32 from the value bytes.
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                break;

            case OpCodes.Br_S:
                //Load the IL offset as signed Int 8 from the value bytes.
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                break;

            case OpCodes.Brtrue:
                //See above.
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-true means we want to do the jump if the operand is not equal to 0
                //i.e. not false
                //Set the jump op to jnz - Jump if Not Zero
                jumpOp = ASMOps.JmpOp.JumpNotZero;
                break;

            case OpCodes.Brtrue_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp = ASMOps.JmpOp.JumpNotZero;
                break;

            case OpCodes.Brfalse:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-true means we want to do the jump if the operand is equal to 0
                //i.e. is false
                //Set the jump op to jz - Jump if Zero
                jumpOp = ASMOps.JmpOp.JumpZero;
                break;

            case OpCodes.Brfalse_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp = ASMOps.JmpOp.JumpZero;
                break;

            case OpCodes.Beq:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-equal means we want to do the jump if the operand is equal to the other operand
                //i.e. A == B
                //Set the jump op to je - Jump if equal
                jumpOp        = ASMOps.JmpOp.JumpEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpNotEqual;
                break;

            case OpCodes.Beq_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp        = ASMOps.JmpOp.JumpEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpNotEqual;
                break;

            case OpCodes.Bne_Un:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-equal means we want to do the jump if the operand is equal to the other operand
                //i.e. A == B
                //Set the jump op to je - Jump if not equal
                jumpOp         = ASMOps.JmpOp.JumpNotEqual;
                isNegativeTest = true;
                break;

            case OpCodes.Bne_Un_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp         = ASMOps.JmpOp.JumpNotEqual;
                isNegativeTest = true;
                break;

            case OpCodes.Bge:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-greater-than-or-equal means we want to do the jump if the operand is greater than equal to
                //the other operand
                //i.e. A >= B
                //Set the jump op to jge - Jump if greater than or equal
                jumpOp        = ASMOps.JmpOp.JumpGreaterThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpLessThan;
                break;

            case OpCodes.Bge_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp        = ASMOps.JmpOp.JumpGreaterThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpLessThan;
                break;

            case OpCodes.Bge_Un:
                //See above : This is unsigned variant
                ILOffset     = Utilities.ReadInt32(theOp.ValueBytes, 0);
                UnsignedTest = true;
                //See above
                jumpOp        = ASMOps.JmpOp.JumpGreaterThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpLessThan;
                break;

            case OpCodes.Bge_Un_S:
                //See above
                ILOffset     = (int)(sbyte)theOp.ValueBytes[0];
                UnsignedTest = true;
                //See above
                jumpOp        = ASMOps.JmpOp.JumpGreaterThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpLessThan;
                break;

            case OpCodes.Ble:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-less-than-or-equal means we want to do the jump if the operand is less than equal to
                //the other operand
                //i.e. A <= B
                //Set the jump op to jle - Jump if less than or equal
                jumpOp        = ASMOps.JmpOp.JumpLessThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpGreaterThan;
                break;

            case OpCodes.Ble_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp        = ASMOps.JmpOp.JumpLessThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpGreaterThan;
                break;

            case OpCodes.Ble_Un:
                //See above : This is unsigned variant
                ILOffset     = Utilities.ReadInt32(theOp.ValueBytes, 0);
                UnsignedTest = true;
                //See above
                jumpOp        = ASMOps.JmpOp.JumpLessThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpGreaterThan;
                break;

            case OpCodes.Ble_Un_S:
                //See above
                ILOffset     = (int)(sbyte)theOp.ValueBytes[0];
                UnsignedTest = true;
                //See above
                jumpOp        = ASMOps.JmpOp.JumpLessThanEqual;
                inverseJumpOp = ASMOps.JmpOp.JumpGreaterThan;
                break;

            case OpCodes.Blt:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-less-than means we want to do the jump if the operand is less than
                //the other operand
                //i.e. A < B
                //Set the jump op to jl - Jump if less than
                jumpOp         = ASMOps.JmpOp.JumpLessThan;
                isNegativeTest = true;
                break;

            case OpCodes.Blt_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp         = ASMOps.JmpOp.JumpLessThan;
                isNegativeTest = true;
                break;

            case OpCodes.Blt_Un:
                //See above : This is unsigned variant
                ILOffset     = Utilities.ReadInt32(theOp.ValueBytes, 0);
                UnsignedTest = true;
                //See above
                jumpOp         = ASMOps.JmpOp.JumpLessThan;
                isNegativeTest = true;
                break;

            case OpCodes.Blt_Un_S:
                //See above
                ILOffset     = (int)(sbyte)theOp.ValueBytes[0];
                UnsignedTest = true;
                //See above
                jumpOp         = ASMOps.JmpOp.JumpLessThan;
                isNegativeTest = true;
                break;

            case OpCodes.Bgt:
                //See above
                ILOffset = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Branch-if-greater-than means we want to do the jump if the operand is greater than
                //the other operand
                //i.e. A > B
                //Set the jump op to jg - Jump if greater than
                jumpOp         = ASMOps.JmpOp.JumpGreaterThan;
                isNegativeTest = true;
                break;

            case OpCodes.Bgt_S:
                //See above
                ILOffset = (int)(sbyte)theOp.ValueBytes[0];
                //See above
                jumpOp         = ASMOps.JmpOp.JumpGreaterThan;
                isNegativeTest = true;
                break;

            case OpCodes.Bgt_Un:
                //See above : This is unsigned variant
                ILOffset     = Utilities.ReadInt32(theOp.ValueBytes, 0);
                UnsignedTest = true;
                //See above
                jumpOp         = ASMOps.JmpOp.JumpGreaterThan;
                isNegativeTest = true;
                break;

            case OpCodes.Bgt_Un_S:
                //See above
                ILOffset     = (int)(sbyte)theOp.ValueBytes[0];
                UnsignedTest = true;
                //See above
                jumpOp         = ASMOps.JmpOp.JumpGreaterThan;
                isNegativeTest = true;
                break;
            }

            if (ILOffset == 0)
            {
                //Err..why bother jumping at all if the offset is 0?
                conversionState.Append(new ASMOps.Comment("No jump insert - pointless 0 distance jump"));
            }
            else
            {
                //Get the IL number of the next op
                int startILNum = theOp.NextOffset;
                //Add the offset to get the IL op num to jump to
                int ILNumToGoTo = startILNum + ILOffset;

                //Find the IL op to jump to
                ILOp opToGoTo         = conversionState.Input.At(ILNumToGoTo);
                int  opToGoToPosition = conversionState.PositionOf(opToGoTo);
                int  currOpPosition   = conversionState.PositionOf(theOp);

                //If the jump op is not a straightforward jump i.e. has one or more conditions
                if (jumpOp == ASMOps.JmpOp.JumpZero || jumpOp == ASMOps.JmpOp.JumpNotZero)
                {
                    //Pop from our stack the test item to use in the condition
                    StackItem testItem = conversionState.CurrentStackFrame.Stack.Pop();

                    if (testItem.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Branch test based on float not supported!");
                    }
                    //If the test item is Int64 or UInt64
                    else if (testItem.sizeOnStackInBytes == 8)
                    {
                        //Compare first 32 bits (low bits)
                        //Then (if necessary) compare second 32 bits (high bits)

                        //Pop the low bits
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                        });
                        //Compare the low bits to the test value
                        conversionState.Append(new ASMOps.Cmp()
                        {
                            Arg2 = testVal, Arg1 = "EAX"
                        });
                        //Pre-emptively pop the high bits
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                        });

                        //If we are testing for not equal to zero:
                        if (jumpOp == ASMOps.JmpOp.JumpNotZero)
                        {
                            //If the low bits are not zero, do the jump
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = jumpOp, DestILPosition = opToGoToPosition
                            });
                            //Otherwise, test if the high bits are not 0
                            //We use "cmp" not "test" as "cmp" uses +/- test val, "test" uses & with test val.
                            conversionState.Append(new ASMOps.Cmp()
                            {
                                Arg2 = testVal, Arg1 = "EAX"
                            });
                            //If the high bits are not zero, do the jump
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = jumpOp, DestILPosition = opToGoToPosition
                            });
                        }
                        //If we are testing for equal to zero:
                        else if (jumpOp == ASMOps.JmpOp.JumpZero)
                        {
                            //If the low bits are not zero, jump to the end of these test as condition has not been met
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "End"
                            });
                            //Otherwise, test if the high bits are zero
                            conversionState.Append(new ASMOps.Cmp()
                            {
                                Arg2 = testVal, Arg1 = "EAX"
                            });
                            //If they are, do the jump
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = jumpOp, DestILPosition = opToGoToPosition
                            });
                            //Insert the end label to be jumped to if condition is not met (see above)
                            conversionState.Append(new ASMOps.Label()
                            {
                                ILPosition = currOpPosition, Extension = "End"
                            });
                        }
                        else
                        {
                            //Check that no extra ops have been added in the switch block above!
                            throw new NotSupportedException("Unsupported 64-bit branch op!");
                        }
                    }
                    //If the test item is Int32 or UInt32
                    else if (testItem.sizeOnStackInBytes == 4)
                    {
                        //Pop the test item
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                        });
                        //Compare the test item to the test value
                        conversionState.Append(new ASMOps.Cmp()
                        {
                            Arg2 = testVal, Arg1 = "EAX"
                        });
                        //Do the specified jump
                        conversionState.Append(new ASMOps.Jmp()
                        {
                            JumpType = jumpOp, DestILPosition = opToGoToPosition
                        });
                    }
                    else
                    {
                        throw new InvalidOperationException("Invalid stack operand sizes!");
                    }
                }
                else if (jumpOp == ASMOps.JmpOp.JumpEqual || jumpOp == ASMOps.JmpOp.JumpNotEqual ||
                         jumpOp == ASMOps.JmpOp.JumpGreaterThanEqual ||
                         jumpOp == ASMOps.JmpOp.JumpLessThanEqual ||
                         jumpOp == ASMOps.JmpOp.JumpLessThan ||
                         jumpOp == ASMOps.JmpOp.JumpGreaterThan)
                {
                    //Pop from our stack the test items to use in the condition
                    StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
                    StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

                    if (itemA.isFloat || itemB.isFloat)
                    {
                        //SUPPORT - floats
                        throw new NotSupportedException("Branch test based on float not supported!");
                    }
                    else if (itemA.sizeOnStackInBytes != itemB.sizeOnStackInBytes)
                    {
                        throw new InvalidOperationException("Branch test operands must be same size!");
                    }
                    else if (itemA.sizeOnStackInBytes == 8)
                    {
                        //Pop the test item B
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                        });
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                        });
                        //Pop the test item A
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                        });
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                        });

                        if (!isNegativeTest)
                        {
                            //Compare test item A high bits to test item B high bits
                            conversionState.Append(new ASMOps.Cmp()
                            {
                                Arg2 = "ECX", Arg1 = "EDX"
                            });
                            //If they are not equal, abort the testing
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = inverseJumpOp, DestILPosition = currOpPosition, Extension = "End", UnsignedTest = UnsignedTest
                            });
                            //Else the igh bits are equal so test low bits
                            //Compare test item A low bits to test item B low bits
                            conversionState.Append(new ASMOps.Cmp()
                            {
                                Arg2 = "EBX", Arg1 = "EAX"
                            });
                            //Do the specified jump
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = jumpOp, DestILPosition = opToGoToPosition, UnsignedTest = UnsignedTest
                            });

                            //Insert the end label to be jumped to if condition is not met (see above)
                            conversionState.Append(new ASMOps.Label()
                            {
                                ILPosition = currOpPosition, Extension = "End"
                            });
                        }
                        else
                        {
                            //Compare test item A high bits to test item B high bits
                            conversionState.Append(new ASMOps.Cmp()
                            {
                                Arg2 = "ECX", Arg1 = "EDX"
                            });
                            //Do the specified jump
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = jumpOp, DestILPosition = opToGoToPosition, UnsignedTest = UnsignedTest
                            });
                            //Compare test item A low bits to test item B low bits
                            conversionState.Append(new ASMOps.Cmp()
                            {
                                Arg2 = "EBX", Arg1 = "EAX"
                            });
                            //Do the specified jump
                            conversionState.Append(new ASMOps.Jmp()
                            {
                                JumpType = jumpOp, DestILPosition = opToGoToPosition, UnsignedTest = UnsignedTest
                            });
                        }
                    }
                    else if (itemA.sizeOnStackInBytes == 4)
                    {
                        //Pop the test item B
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                        });
                        //Pop the test item A
                        conversionState.Append(new ASMOps.Pop()
                        {
                            Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                        });
                        //Compare test item A to test item B
                        conversionState.Append(new ASMOps.Cmp()
                        {
                            Arg2 = "EBX", Arg1 = "EAX"
                        });
                        //Do the specified jump
                        conversionState.Append(new ASMOps.Jmp()
                        {
                            JumpType = jumpOp, DestILPosition = opToGoToPosition, UnsignedTest = UnsignedTest
                        });
                    }
                    else
                    {
                        throw new NotSupportedException("Branch test based on supplied stack item sizes not supported!");
                    }
                }
                else
                {
                    //Do the straightforward jump...
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = jumpOp, DestILPosition = opToGoToPosition
                    });
                }
            }
        }
예제 #9
0
        public static void LoadData(ILConversionState conversionState, ILOp theOp,
            string addressReg, string valueReg, int offset, int size, bool SignExtend = false)
        {
            if (size == 1)
            {
                conversionState.Append(new ASMOps.Mov() { Src = offset + "(" + addressReg + ")", Dest = "$t6", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg, Size = ASMOps.OperandSize.Byte, SignExtend = SignExtend });
            }
            else
            {
                conversionState.Append(new ASMOps.Xor() { Src1 = "$t6", Src2 = "$t6", Dest = "$t6" });
                int shiftBits = 0;
                if (offset % 2 == 1)
                {
                    conversionState.Append(new ASMOps.Mov() { Src = offset + "(" + addressReg + ")", Dest = "$t7", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg, Size = ASMOps.OperandSize.Byte });
                    conversionState.Append(new ASMOps.Or() { Src1 = "$t7", Src2 = "$t6", Dest = "$t6" });

                    size -= 1;
                    offset += 1;
                    shiftBits += 8;
                }

                while (size > 1)
                {
                    conversionState.Append(new ASMOps.Mov() { Src = offset + "(" + addressReg + ")", Dest = "$t7", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg, Size = ASMOps.OperandSize.Halfword, SignExtend = (SignExtend && size == 2) });
                    if (shiftBits > 0)
                    {
                        conversionState.Append(new ASMOps.Sll() { Src = "$t7", Dest = "$t7", Bits = shiftBits });
                    }
                    conversionState.Append(new ASMOps.Or() { Src1 = "$t7", Src2 = "$t6", Dest = "$t6" });

                    size -= 2;
                    offset += 2;
                    shiftBits += 16;
                }

                if (size == 1)
                {
                    conversionState.Append(new ASMOps.Mov() { Src = offset + "(" + addressReg + ")", Dest = "$t7", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg, Size = ASMOps.OperandSize.Byte, SignExtend = SignExtend });
                    if (shiftBits > 0)
                    {
                        conversionState.Append(new ASMOps.Sll() { Src = "$t7", Dest = "$t7", Bits = shiftBits });
                    }
                    conversionState.Append(new ASMOps.Or() { Src1 = "$t7", Src2 = "$t6", Dest = "$t6" });

                    size -= 1;
                    offset += 1;
                    shiftBits += 8;
                }
            }

            conversionState.Append(new ASMOps.Mov() { Src = "$t6", Dest = valueReg, Size = ASMOps.OperandSize.Word, MoveType = ASMOps.Mov.MoveTypes.RegToReg });
        }
예제 #10
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// If either value is &lt; 4 bytes in length or
        /// operands are not of the same size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop item to negate
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Negate float vals not suppported yet!");
            }

            // Two's Complement negation
            //  - "Not" value then add 1

            if (itemA.sizeOnStackInBytes == 4)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Neg()
                {
                    Arg = "EAX"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                });
            }
            else if (itemA.sizeOnStackInBytes == 8)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                });
                // Not the value
                conversionState.Append(new ASMOps.Not()
                {
                    Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Not()
                {
                    Dest = "EDX"
                });

                // Then add 1
                conversionState.Append(new ASMOps.Mov()
                {
                    Src = "1", Dest = "EBX", Size = ASMOps.OperandSize.Dword
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Src = "0", Dest = "ECX", Size = ASMOps.OperandSize.Dword
                });

                //Add ecx:ebx to edx:eax
                //Add low bits
                conversionState.Append(new ASMOps.Add()
                {
                    Src = "EBX", Dest = "EAX"
                });
                //Add high bits including any carry from
                //when low bits were added
                conversionState.Append(new ASMOps.Add()
                {
                    Src = "ECX", Dest = "EDX", WithCarry = true
                });

                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EDX"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX"
                });
            }
            else
            {
                throw new NotSupportedException("Stack item size not supported by neg op!");
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged        = itemA.isGCManaged,
                isValue            = itemA.isValue
            });
        }
예제 #11
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if the value to store is floating point.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            Types.FieldInfo theFieldInfo     = conversionState.GetFieldInfo(theField.DeclaringType, theField.Name);
            Types.TypeInfo  theFieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theFieldInfo.FieldType);

            string fieldId = theFieldInfo.ID;
            int    size    = /*theFieldTypeInfo.IsValueType ? theFieldTypeInfo.SizeOnHeapInBytes : */ theFieldTypeInfo.SizeOnStackInBytes;
            bool   isFloat = Utilities.IsFloat(theField.FieldType);

            conversionState.AddExternalLabel(fieldId);

            StackItem value = conversionState.CurrentStackFrame.Stack.Pop();

            if (isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing static fields of type float not supported yet!");
            }

            if (size == 1)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[" + fieldId + "]"
                });
            }
            else if (size == 2)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[" + fieldId + "]"
                });
            }
            else if (size == 4)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[" + fieldId + "]"
                });
            }
            else if (size == 8)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[" + fieldId + "]"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[" + fieldId + "+4]"
                });
            }
            else
            {
                throw new ArgumentOutOfRangeException("Storing static field that has stack size greater than 8 not supported!");
            }

            if (value.sizeOnStackInBytes - size > 0)
            {
                conversionState.Append(new ASMOps.Add()
                {
                    Src = (value.sizeOnStackInBytes - size).ToString(), Dest = "ESP"
                });
            }
        }
예제 #12
0
파일: Rem.cs 프로젝트: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if divide operands are floating point numbers or if attempting to divide 64-bit numbers.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either operand is &lt; 4 bytes long.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();


            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Divide floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    if ((OpCodes)theOp.opCode.Value == OpCodes.Rem_Un)
                    {
                        //Unsigned extend A to EAX:EDX
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EDX"
                        });
                        //Do the division
                        conversionState.Append(new ASMOps.Div()
                        {
                            Arg = "EBX"
                        });
                    }
                    else
                    {
                        //Sign extend A to EAX:EDX
                        conversionState.Append(new ASMOps.Cdq());
                        //Do the division
                        conversionState.Append(new ASMOps.Div()
                        {
                            Arg = "EBX", Signed = true
                        });
                    }
                    //Result stored in edx
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the 32-32 or 64-64.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //SUPPORT - 64-bit division
                    throw new NotSupportedException("64-bit by 64-bit modulo not supported yet!");
                }
            }
        }
예제 #13
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if either or both values to shift left are floating point values or
        /// if the values are 8 bytes in size.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either or both values to multiply are not 4 or 8 bytes
        /// in size or if the values are of different size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            int currOpPosition = conversionState.PositionOf(theOp);

            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Shift left on floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t2"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t0", BitsReg = "$t2", Dest = "$t0",
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! 4,8 not supported.");
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4))
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t2"
                    });
                    //Pop item A (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t3"
                    });

                    //Check shift size
                    conversionState.Append(new ASMOps.Branch()
                    {
                        Src1 = "$t2", Src2 = "32", BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, DestILPosition = currOpPosition, Extension = "ShiftMoreThan32", UnsignedTest = true
                    });

                    //Shld (< 32)
                    //Works for shifting 64 bit values
                    //Left shift high bits ($t3) by $t2
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t3", BitsReg = "$t2", Dest = "$t3"
                    });
                    //Right shift low bits ($t0) by (32-$t2) into temp ($t1)
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "32", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src1 = "$t1", Src2 = "$t2", Dest = "$t1"
                    });
                    conversionState.Append(new ASMOps.Srlv()
                    {
                        Src = "$t0", BitsReg = "$t1", Dest = "$t1"
                    });                                                                                         //$t1 = temp
                    //Copy temp to high bits
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t1", Src2 = "$t3", Dest = "$t3"
                    });
                    //Left shift low bytes by $t2
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t0", BitsReg = "$t2", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                    });

                    //Shld (>= 32)
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ShiftMoreThan32"
                    });
                    //Move low bits ($t0) to high bits ($t3)
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "$t3", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                    });
                    //Zero out low bits
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //Left shift high bits by (t2-32)
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src1 = "$t2", Src2 = "32", Dest = "$t2"
                    });
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t3", BitsReg = "$t2", Dest = "$t3"
                    });

                    //Push result
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t3"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Note: Shifting by more than 64 bits is pointless since the value will be annihilated entirely.
                    //          "64" fits well within the low 32-bits
                    //      So for this op, we do the same as the 8-4 byte version but discard the top four bytes
                    //          of the second operand
                    //      Except we must check the high bytes for non-zero value. If they are non-zero, we simply
                    //          push a result of zero.

                    //Pop item B (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t2"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t1"
                    });
                    //Pop item A (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Word, Dest = "$t3"
                    });
                    //Check high 4 bytes of second param
                    conversionState.Append(new ASMOps.Branch()
                    {
                        Src1 = "$t1", BranchType = ASMOps.BranchOp.BranchZero, DestILPosition = currOpPosition, Extension = "Zero"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$zero"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$zero"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End2"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "zero"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        Src1 = "$t2", Src2 = "32", BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, DestILPosition = currOpPosition, Extension = "ShiftMoreThan32", UnsignedTest = true
                    });

                    //Shld (< 32)
                    //Works for shifting 64 bit values
                    //Left shift high bits ($t3) by $t2
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t3", BitsReg = "$t2", Dest = "$t3"
                    });
                    //Right shift low bits ($t0) by (32-$t2)
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "32", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src1 = "$t1", Src2 = "$t2", Dest = "$t1"
                    });
                    conversionState.Append(new ASMOps.Srlv()
                    {
                        Src = "$t0", BitsReg = "$t1", Dest = "$t1"
                    });                                                                                         //$t1 = temp
                    //Copy temp to high bits
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t1", Src2 = "$t3", Dest = "$t3"
                    });
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t0", BitsReg = "$t2", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End1"
                    });

                    //Shl (>= 32)
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ShiftMoreThan32"
                    });
                    //Move low bits ($t0) to high bits ($t3)
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "$t3", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                    });
                    //Zero out low bits
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                    });
                    //Left shift high bits by (t2-32)
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src1 = "$t2", Src2 = "32", Dest = "$t2"
                    });
                    conversionState.Append(new ASMOps.Sllv()
                    {
                        Src = "$t3", BitsReg = "$t2", Dest = "$t3"
                    });

                    //Push result
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End1"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t3"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End2"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
            }
        }
예제 #14
0
파일: Ret.cs 프로젝트: zrbruce/FlingOS
 /// <summary>
 /// See base class documentation.
 /// </summary>
 /// <param name="theOp">See base class documentation.</param>
 /// <param name="conversionState">See base class documentation.</param>
 /// <returns>See base class documentation.</returns>
 public override void Convert(ILConversionState conversionState, ILOp theOp)
 {
     conversionState.Append(new ASMOps.Ret());
 }
예제 #15
0
파일: Sub.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if the either of the values to add are floating point.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if the either of the values to add are less than 4 bytes in size
        /// or if they are of different sizes.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop the operands from our stack in reverse order
            //i.e. second operand was pushed last so comes off the
            //top of the stack first

            //Pop item B - one of the items to subtract
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            //Pop item A - the other item to subtract
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            //If either item item is < 4 bytes then we have a stack error.
            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            //If either item is floating point, we must use floating point conversions
            //and floating point arithmetic
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                //  - We need to convert items to float if necessary
                //  - Then use floating point arithmetic
                //  - Then push the result onto the stack and mark it as float
                // Note: Check but I think floating point arithmetic is done using
                //       XMM registers and their specific ops.
                throw new NotSupportedException("Sub floats is unsupported!");
            }
            else
            {
                //If both items are Int32s (or UInt32s - it is irrelevant)
                //Note: IL handles type conversions using other ops
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    //Subtract the two
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "EBX", Dest = "EAX"
                    });
                    //Push the result onto the stack
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    //Push the result onto our stack
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                //Invalid if the operands are of different sizes.
                //Note: This usually occurs when a previous IL op failed to process properly.
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4) ||
                         (itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! They should be the same size.");
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Pop item B to ecx:ebx
                    //Pop low bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    //Pop high bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    //Pop item A to edx:eax
                    //Pop low bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    //Pop high bits
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });
                    //Sub ecx:ebx from edx:eax
                    //Sub low bits
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "EBX", Dest = "EAX"
                    });
                    //Sub high bits including any borrow from
                    //when low bits were subtracted
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "ECX", Dest = "EDX", WithBorrow = true
                    });
                    //Push the result
                    //Push high bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });
                    //Push low bits
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    //Push the result onto our stack
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
            }
        }
예제 #16
0
파일: Convu.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            StackItem itemToConvert       = conversionState.CurrentStackFrame.Stack.Pop();
            int       numBytesToConvertTo = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Conv_U:
                numBytesToConvertTo = 4;
                break;

            case OpCodes.Conv_U1:
                numBytesToConvertTo = 1;
                break;

            case OpCodes.Conv_U2:
                numBytesToConvertTo = 2;
                break;

            case OpCodes.Conv_U4:
                numBytesToConvertTo = 4;
                break;

            case OpCodes.Conv_U8:
                numBytesToConvertTo = 8;
                break;
            }

            int  bytesPopped = 0;
            bool pushEDX     = false;

            switch (numBytesToConvertTo)
            {
            case 1:
                //Convert to UInt8 (byte)
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "AX"
                });
                conversionState.Append(new ASMOps.And()
                {
                    Src = "0x000000FF", Dest = "EAX"
                });
                bytesPopped = 2;
                break;

            case 2:
                //Convert to UInt16 (word)
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "AX"
                });
                bytesPopped = 2;
                break;

            case 4:
                //Convert to UInt32 (dword)
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                bytesPopped = 4;
                break;

            case 8:
                //Convert to UInt64
                if (itemToConvert.sizeOnStackInBytes == 8)
                {
                    //Result stored in EAX:EDX
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });
                    bytesPopped = 8;
                }
                else
                {
                    //Result stored in EAX:EDX
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EDX"
                    });
                    bytesPopped = 4;
                }
                pushEDX = true;
                break;
            }

            int bytesDiff = itemToConvert.sizeOnStackInBytes - bytesPopped;

            if (bytesDiff > 0)
            {
                conversionState.Append(new ASMOps.Add()
                {
                    Src = bytesDiff.ToString(), Dest = "ESP"
                });
            }

            if (pushEDX)
            {
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Dword, Src = "EDX"
                });
            }
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = "EAX"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = (pushEDX ? 8 : 4),
                isFloat            = false,
                isGCManaged        = false,
                isValue            = true
            });
        }
예제 #17
0
파일: Ldind.cs 프로젝트: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Load indirect
            //Pop address
            //Push [address]

            StackItem addressItem = conversionState.CurrentStackFrame.Stack.Pop();
            int       bytesToLoad = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldind_U1:
            case OpCodes.Ldind_I1:
                bytesToLoad = 1;
                break;

            case OpCodes.Ldind_U2:
            case OpCodes.Ldind_I2:
                bytesToLoad = 2;
                break;

            case OpCodes.Ldind_U4:
            case OpCodes.Ldind_I4:
            case OpCodes.Ldind_I:
                bytesToLoad = 4;
                break;

            case OpCodes.Ldind_I8:
                bytesToLoad = 8;
                break;

            case OpCodes.Ldind_Ref:
                bytesToLoad = Options.AddressSizeInBytes;
                break;
            }

            int currOpPosition = conversionState.PositionOf(theOp);

            //Pop address
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t1"
            });

            if (bytesToLoad != 1)
            {
                // Alignment tests
                conversionState.Append(new ASMOps.And()
                {
                    Src1 = "$t1", Src2 = "3", Dest = "$t5"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchEqual, Src1 = "$t5", Src2 = "1", DestILPosition = currOpPosition, Extension = "ByteAligned"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchEqual, Src1 = "$t5", Src2 = "2", DestILPosition = currOpPosition, Extension = "HalfwordAligned"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchEqual, Src1 = "$t5", Src2 = "3", DestILPosition = currOpPosition, Extension = "ByteAligned"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "WordAligned"
                });
            }

            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldind_Ref)
            {
                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "ByteAligned"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "3($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Sll()
                {
                    Src = "$t0", Dest = "$t0", Bits = 24
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "2($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Sll()
                {
                    Src = "$t4", Dest = "$t4", Bits = 16
                });
                conversionState.Append(new ASMOps.Or()
                {
                    Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "1($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Sll()
                {
                    Src = "$t4", Dest = "$t4", Bits = 8
                });
                conversionState.Append(new ASMOps.Or()
                {
                    Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Or()
                {
                    Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                });

                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "HalfwordAligned"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Halfword, Src = "2($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Sll()
                {
                    Src = "$t0", Dest = "$t0", Bits = 16
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Halfword, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Or()
                {
                    Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                });

                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "WordAligned"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
            }
            else
            {
                if (bytesToLoad == 1)
                {
                    conversionState.Append(new ASMOps.Xor()
                    {
                        Src1 = "$t0", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                }
                else if (bytesToLoad == 2)
                {
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ByteAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "1($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 8
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                    });

                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "HalfwordAligned"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "WordAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                }
                else if (bytesToLoad == 4)
                {
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ByteAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "3($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 24
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "2($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t4", Dest = "$t4", Bits = 16
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "1($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t4", Dest = "$t4", Bits = 8
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                    });

                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "HalfwordAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "2($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 16
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                    });

                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "WordAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                }
                else if (bytesToLoad == 8)
                {
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ByteAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "7($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 24
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "6($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t4", Dest = "$t4", Bits = 16
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "4($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t4", Dest = "$t4", Bits = 8
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "5($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });

                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "3($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 24
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "2($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t4", Dest = "$t4", Bits = 16
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "1($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t4", Dest = "$t4", Bits = 8
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Byte, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                    });


                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "HalfwordAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "6($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 16
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "4($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });

                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });

                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "2($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Sll()
                    {
                        Src = "$t0", Dest = "$t0", Bits = 16
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Halfword, Src = "0($t1)", Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Or()
                    {
                        Src1 = "$t4", Src2 = "$t0", Dest = "$t0"
                    });
                    conversionState.Append(new ASMOps.Branch()
                    {
                        BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                    });


                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "WordAligned"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "4($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "0($t1)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                }
            }

            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "End"
            });
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$t0"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = bytesToLoad == 8 ? 8 : 4,
                isFloat            = false,
                isGCManaged        = false
            });
        }
예제 #18
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if compare operands are floating point numbers or if either value is &lt; 4 bytes in length or
        /// operands are not of the same size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            bool unsignedComparison = (OpCodes)theOp.opCode.Value == OpCodes.Clt_Un;
            int  currOpPosition     = conversionState.PositionOf(theOp);

            if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Add floats is unsupported!");
            }
            else if (itemA.sizeOnStackInBytes == 4 && itemB.sizeOnStackInBytes == 4)
            {
                //Pop item B
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t1"
                });
                //Pop item A
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                //If A >= B, jump to Else (not-true case)
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, Src1 = "$t0", Src2 = "$t1", DestILPosition = currOpPosition, Extension = "Else", UnsignedTest = unsignedComparison
                });
                //Otherwise, A < B, so push true (true=1)
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t4", Src = "1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t4"
                });
                //And then jump to the end of this IL op.
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                });
                //Insert the Else label.
                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "Else"
                });
                //Else case - Push false (false=0)
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$zero"
                });

                //Push the result onto our stack
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat            = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false
                });
            }
            else if (itemA.sizeOnStackInBytes == 8 && itemB.sizeOnStackInBytes == 8)
            {
                //Pop item B
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t1"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t2"
                });
                //Pop item A
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t3"
                });
                //If A high bytes < B high bytes : True
                //If A high bytes = B high bytes : Check, if A low bytes < B low bytes : True
                //Else : False

                //A high bytes < B high bytes? Branch to true case.
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchLessThan, Src1 = "$t3", Src2 = "$t2", DestILPosition = currOpPosition, Extension = "True", UnsignedTest = unsignedComparison
                });
                //A high bytes > B high bytes? Branch to else case.
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchGreaterThan, Src1 = "$t3", Src2 = "$t2", DestILPosition = currOpPosition, Extension = "Else", UnsignedTest = unsignedComparison
                });
                //Otherwise, A high bytes = B high bytes
                //A low bytes >= B low bytes? Branch to else case.
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, Src1 = "$t0", Src2 = "$t1", DestILPosition = currOpPosition, Extension = "Else", UnsignedTest = unsignedComparison
                });
                //Otherwise A < B.

                //Insert True case label
                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "True"
                });
                //True case - Push true (true=1)
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t4", Src = "1", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t4"
                });
                //And then jump to the end of this IL op.
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "End"
                });
                //Insert Else case label
                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "Else"
                });
                //Else case - Push false (false=0)
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$zero"
                });

                //Push the result onto our stack
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    // Yes, this is supposed to be 4 - the value that just got pushed was a
                    // true / false integer
                    sizeOnStackInBytes = 4,
                    isGCManaged        = false
                });
            }
            else
            {
                throw new NotSupportedException("Unsupported number of bytes for compare less than!");
            }

            //Always append the end label
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "End"
            });
        }
예제 #19
0
        /// <summary>
        /// See base class documentation.
        /// <para>To Do's:</para>
        /// <list type="bullet">
        /// <item>
        /// <term>To do</term>
        /// <description>Implement loading of float arguments.</description>
        /// </item>
        /// </list>
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown when loading a float argument is required as it currently hasn't been
        /// implemented.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Thrown when an invalid number of bytes is specified for the argument to load.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Get the index of the argument to load
            Int16 index = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Ldarg:
                index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                break;

            case OpCodes.Ldarg_0:
                index = 0;
                break;

            case OpCodes.Ldarg_1:
                index = 1;
                break;

            case OpCodes.Ldarg_2:
                index = 2;
                break;

            case OpCodes.Ldarg_3:
                index = 3;
                break;

            case OpCodes.Ldarg_S:
                index = (Int16)theOp.ValueBytes[0];
                break;

            case OpCodes.Ldarga:
                index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                break;

            case OpCodes.Ldarga_S:
                index = (Int16)theOp.ValueBytes[0];
                break;
            }

            //Used to store the number of bytes to add to EBP to get to the arg
            int BytesOffsetFromEBP = 0;
            //Get all the params for the current method
            List <Type> allParams = conversionState.Input.TheMethodInfo.UnderlyingInfo.GetParameters().Select(x => x.ParameterType).ToList();

            if (!conversionState.Input.TheMethodInfo.IsStatic)
            {
                allParams.Insert(0, conversionState.Input.TheMethodInfo.UnderlyingInfo.DeclaringType);
            }
            //Check whether the arg we are going to load is float or not
            if (Utilities.IsFloat(allParams[index]))
            {
                //SUPPORT - floats
                throw new NotSupportedException("Float arguments not supported yet!");
            }
            //For all the parameters pushed on the stack after the param we want
            for (int i = allParams.Count - 1; i > -1 && i > index; i--)
            {
                //Add the param stack size to the EBP offset
                BytesOffsetFromEBP += conversionState.TheILLibrary.GetTypeInfo(allParams[i]).SizeOnStackInBytes;
            }

            //Add 8 for return address and value of EBP (both pushed at start of method call)
            BytesOffsetFromEBP += 8;

            //We must check the return value to see if it has a size on the stack
            //Get the return type
            Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
                            typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);
            //Get the size of the return type
            int retSize = conversionState.TheILLibrary.GetTypeInfo(retType).SizeOnStackInBytes;

            //Add it to EBP offset
            BytesOffsetFromEBP += retSize;

            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga ||
                (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S)
            {
                //Push the address of the argument onto the stack

                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$fp", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.RegToReg
                });
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$t2", Src2 = BytesOffsetFromEBP.ToString(), Dest = "$t2"
                });
                conversionState.Append(new ASMOps.Push()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t2"
                });

                //Push the address onto our stack
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    sizeOnStackInBytes = 4,
                    isFloat            = false,
                    isGCManaged        = false
                });
            }
            else
            {
                //Push the argument onto the stack
                Types.TypeInfo paramTypeInfo = conversionState.TheILLibrary.GetTypeInfo(allParams[index]);
                int            bytesForArg   = paramTypeInfo.SizeOnStackInBytes;
                if (bytesForArg == 4)
                {
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = BytesOffsetFromEBP.ToString() + "($fp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });
                }
                else if (bytesForArg == 8)
                {
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = (BytesOffsetFromEBP + 4).ToString() + "($fp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Word, Src = BytesOffsetFromEBP.ToString() + "($fp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Word, Src = "$t0"
                    });
                }
                else
                {
                    throw new ArgumentException("Cannot load arg! Don't understand byte size of the arg!");
                }

                //Push the arg onto our stack
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    sizeOnStackInBytes = bytesForArg,
                    isFloat            = false,
                    isGCManaged        = paramTypeInfo.IsGCManaged
                });
            }
        }
예제 #20
0
파일: Stsfld.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if the value to store is floating point.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            Types.FieldInfo theFieldInfo     = conversionState.GetFieldInfo(theField.DeclaringType, theField.Name);
            Types.TypeInfo  theFieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theFieldInfo.FieldType);

            string fieldId = theFieldInfo.ID;
            int    size    = theFieldTypeInfo.IsValueType ? theFieldTypeInfo.SizeOnHeapInBytes : theFieldTypeInfo.SizeOnStackInBytes;
            bool   isFloat = Utilities.IsFloat(theField.FieldType);

            conversionState.AddExternalLabel(fieldId);

            StackItem value = conversionState.CurrentStackFrame.Stack.Pop();

            if (isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing static fields of type float not supported yet!");
            }

            if (size == 1)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[" + fieldId + "]"
                });
            }
            else if (size == 2)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[" + fieldId + "]"
                });
            }
            else if (size >= 4)
            {
                for (int i = 0; i < size; i += 4)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });

                    switch (size - i)
                    {
                    case 1:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[" + fieldId + "+" + i + "]"
                        });
                        break;

                    case 2:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[" + fieldId + "+" + i + "]"
                        });
                        break;

                    case 3:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[" + fieldId + "+" + i + "]"
                        });
                        conversionState.Append(new ASMOps.Shr()
                        {
                            Src = "16", Dest = "EAX"
                        });
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[" + fieldId + "+" + (i + 1) + "]"
                        });
                        break;

                    default:
                        conversionState.Append(new ASMOps.Mov()
                        {
                            Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[" + fieldId + "+" + i + "]"
                        });
                        break;
                    }
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException("Storing static field with unsupported size! Size: " + size.ToString());
            }
        }
예제 #21
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if either or both values to shift left are floating point values or
        /// if the values are 8 bytes in size.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if either or both values to multiply are not 4 or 8 bytes
        /// in size or if the values are of different size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            int currOpPosition = conversionState.PositionOf(theOp);

            if (itemB.sizeOnStackInBytes < 4 ||
                itemA.sizeOnStackInBytes < 4)
            {
                throw new InvalidOperationException("Invalid stack operand sizes!");
            }
            else if (itemB.isFloat || itemA.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Shift left on floats is unsupported!");
            }
            else
            {
                if (itemA.sizeOnStackInBytes == 4 &&
                    itemB.sizeOnStackInBytes == 4)
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    //Pop item A
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 4,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if ((itemA.sizeOnStackInBytes == 4 &&
                          itemB.sizeOnStackInBytes == 8))
                {
                    throw new InvalidOperationException("Invalid stack operand sizes! 4,8 not supported.");
                }
                else if ((itemA.sizeOnStackInBytes == 8 &&
                          itemB.sizeOnStackInBytes == 4))
                {
                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    //Pop item A (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });

                    //Check shift size
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "ECX", Arg2 = "32"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpGreaterThanEqual, DestILPosition = currOpPosition, Extension = "ShiftMoreThan32", UnsignedTest = true
                    });

                    //Shld (< 32)
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "EAX", Dest = "EDX", Count = "CL"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "End"
                    });

                    //Shld (>= 32)
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ShiftMoreThan32"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "EDX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "32", Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EDX"
                    });

                    //Push result
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
                else if (itemA.sizeOnStackInBytes == 8 &&
                         itemB.sizeOnStackInBytes == 8)
                {
                    //Note: Shifting by more than 64 bits is pointless since the value will be annihilated entirely.
                    //          "64" fits well within the low 32-bits
                    //      So for this op, we do the same as the 8-4 byte version but discard the top four bytes
                    //          of the second operand
                    //      Except we must check the high bytes for non-zero value. If they are non-zero, we simply
                    //          push a result of zero.

                    //Pop item B
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EBX"
                    });
                    //Pop item A (8 bytes)
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Dword, Dest = "EDX"
                    });
                    //Check high 4 bytes of second param
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "EBX", Arg2 = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpZero, DestILPosition = currOpPosition, Extension = "Zero"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "End2"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "Zero"
                    });

                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "ECX", Arg2 = "32"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpGreaterThanEqual, DestILPosition = currOpPosition, Extension = "ShiftMoreThan32", UnsignedTest = true
                    });

                    //Shld (< 32)
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "EAX", Dest = "EDX", Count = "CL"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "End1"
                    });

                    //Shl (>= 32)
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "ShiftMoreThan32"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "EDX"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "0", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Sub()
                    {
                        Src = "32", Dest = "ECX"
                    });
                    conversionState.Append(new ASMOps.Shl()
                    {
                        Src = "CL", Dest = "EDX"
                    });

                    //Push result
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End1"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EDX"
                    });
                    conversionState.Append(new ASMOps.Push()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EAX"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "End2"
                    });

                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat            = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged        = false,
                        isValue            = itemA.isValue && itemB.isValue
                    });
                }
            }
        }
예제 #22
0
파일: Starg.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// <para>To Do's:</para>
        /// <list type="bullet">
        /// <item>
        /// <term>To do</term>
        /// <description>Implement storing of float arguments.</description>
        /// </item>
        /// </list>
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotImplementedException">
        /// Thrown when storing a float argument is required as it currently hasn't been
        /// implemented.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Thrown when an invalid number of bytes is specified for the argument to store.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Get the index of the argument to load
            Int16 index = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Starg:
                index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                break;

            case OpCodes.Starg_S:
                index = (Int16)theOp.ValueBytes[0];
                break;
            }

            //Used to store the number of bytes to subtract from $fp to get to the arg
            int BytesOffsetFromFp = 0;
            //Get all the params for the current method
            List <Type> allParams = conversionState.Input.TheMethodInfo.UnderlyingInfo.GetParameters().Select(x => x.ParameterType).ToList();

            if (!conversionState.Input.TheMethodInfo.IsStatic)
            {
                allParams.Insert(0, conversionState.Input.TheMethodInfo.UnderlyingInfo.DeclaringType);
            }
            //Check whether the arg we are going to load is float or not
            if (Utilities.IsFloat(allParams[index]))
            {
                //SUPPORT - floats
                throw new NotSupportedException("Float arguments not supported yet!");
            }
            //For all the parameters pushed on the stack after the param we want
            for (int i = allParams.Count - 1; i > -1 && i > index; i--)
            {
                //Add the param stack size to the $fp offset
                BytesOffsetFromFp += conversionState.TheILLibrary.GetTypeInfo(allParams[i]).SizeOnStackInBytes;
            }

            //Add 8 for return address and value of $fp (both pushed at start of method call)
            BytesOffsetFromFp += 8;

            //We must check the return value to see if it has a size on the stack
            //Get the return type
            Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
                            typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);
            //Get the size of the return type
            int retSize = conversionState.TheILLibrary.GetTypeInfo(retType).SizeOnStackInBytes;

            //Add it to $fp offset
            BytesOffsetFromFp += retSize;

            //Pop the argument value from the stack
            int bytesForArg = conversionState.TheILLibrary.GetTypeInfo(allParams[index]).SizeOnStackInBytes;

            if (bytesForArg == 4)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = BytesOffsetFromFp.ToString() + "($fp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
            }
            else if (bytesForArg == 8)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = BytesOffsetFromFp.ToString() + "($fp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t0"
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = (BytesOffsetFromFp + 4).ToString() + "($fp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
            }
            else
            {
                throw new ArgumentException("Cannot store arg! Don't understand byte size of the arg!");
            }

            //Pop the arg value from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
        }
예제 #23
0
파일: Callvirt.cs 프로젝트: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if any argument or the return value is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;

            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);

            //The method to call is a method base
            //A method base can be either a method info i.e. a normal method
            //or a constructor method. The two types are treated separately.
            if (methodToCall is MethodInfo)
            {
                //Need to do callvirt related stuff to load address of method to call
                // - Check for invoke of a delegate - if so, treat rather differently from normal callvirt

                if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType))
                {
                    //Callvirt to delegate method
                    // - We only support calls to Invoke at the moment
                    if (methodToCall.Name != "Invoke")
                    {
                        throw new NotSupportedException("Callvirt to Delegate method not supported! Method name: " + methodToCall.Name);
                    }
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum();

                    // - Move into eax address of function to call from stack - delegate reference is function pointer

                    //All the parameters for the method that was called
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();

                    int bytesForParams = allParams.Select(x => conversionState.TheILLibrary.GetTypeInfo(x).SizeOnStackInBytes).Sum();
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + bytesForParams + "]", Dest = "EAX"
                    });


                    //Allocate space on the stack for the return value as necessary
                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else
                        {
                            for (int i = 0; i < returnItem.sizeOnStackInBytes; i += 4)
                            {
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Dword, Src = "0"
                                });
                            }
                        }
                    }



                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "EAX"
                    });


                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    // - Initially at least 4 for the delegate (method) ref/pointer
                    int bytesToAdd = 4;
                    //Go through all params that must be removed
                    foreach (Type aParam in allParams)
                    {
                        //Pop the paramter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }

                    //If there is a return value on the stack
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //We need to store the return value then pop all the params

                        //We now push the return value onto our stack as,
                        //after all is said and done below, it will be the
                        //top item on the stack
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);

                        //SUPPORT - floats (with above)

                        //Pop the return value, shift it into final position
                        for (int i = 0; i < returnItem.sizeOnStackInBytes; i += 4)
                        {
                            int srcOffset  = returnItem.sizeOnStackInBytes - i - 4;
                            int destOffset = bytesToAdd + srcOffset;

                            conversionState.Append(new ASMOps.Mov()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "EAX", Src = "[ESP+" + srcOffset + "]"
                            });
                            conversionState.Append(new ASMOps.Mov()
                            {
                                Size = ASMOps.OperandSize.Dword, Dest = "[ESP+" + destOffset + "]", Src = "EAX"
                            });
                        }
                    }
                    //Skip over the params
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src = bytesToAdd.ToString(), Dest = "ESP"
                    });
                }
                else
                {
                    //Normal callvirt
                    // - Get object ref from loaded args
                    // - Check object ref not null
                    // - Get type table entry from object ref
                    // - Get method table from type table entry
                    // - Scan method table for the method we want
                    //      - If found, load method address
                    // - Else, check for parent type method table
                    //      - If no parent type method table, throw exception
                    // - Else, scan parent type method table

                    string methodIDValueWanted = methodToCallInfo.IDValue.ToString();
                    int    currOpPosition      = conversionState.PositionOf(theOp);

                    Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType);
                    //DB_Type declaringDBType = DebugDatabase.GetType(conversionState.GetTypeID(methodToCall.DeclaringType));

                    //Get object ref
                    int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum();
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + bytesForAllParams + "]", Dest = "EAX"
                    });

                    //Check object ref
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "EAX", Arg2 = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpNotZero, DestILPosition = currOpPosition, Extension = "NotNull"
                    });
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "GetEIP"
                    });
                    conversionState.AddExternalLabel("GetEIP");
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotNull"
                    });

                    //Get type ref
                    int typeOffset = conversionState.TheILLibrary.GetFieldInfo(declaringTypeInfo, "_Type").OffsetInBytes;
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + typeOffset.ToString() + "]", Dest = "EAX"
                    });

                    //Get method table ref
                    int methodTablePtrOffset = conversionState.GetTypeFieldOffset("MethodTablePtr");
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX+" + methodTablePtrOffset.ToString() + "]", Dest = "EAX"
                    });

                    //Loop through entries
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    //Load ID Val for current entry
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX]", Dest = "EBX"
                    });
                    //Compare to wanted ID value
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "EBX", Arg2 = methodIDValueWanted
                    });
                    //If equal, load method address into EAX
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpNotEqual, DestILPosition = currOpPosition, Extension = "NotEqual"
                    });
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX+4]", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "Call"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotEqual"
                    });
                    //Else, compare to 0 to check for end of table
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "EBX", Arg2 = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpZero, DestILPosition = currOpPosition, Extension = "EndOfTable"
                    });
                    //Not 0? Move to next entry then loop again
                    conversionState.Append(new ASMOps.Add()
                    {
                        Src = "8", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "EndOfTable"
                    });
                    //Compare address value to 0
                    //If not zero, there is a parent method table to check
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "[EAX+4]", Dest = "EBX"
                    });
                    conversionState.Append(new ASMOps.Cmp()
                    {
                        Arg1 = "EBX", Arg2 = "0"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.JumpZero, DestILPosition = currOpPosition, Extension = "NotFound"
                    });
                    //Load parent method table and loop
                    conversionState.Append(new ASMOps.Mov()
                    {
                        Size = ASMOps.OperandSize.Dword, Src = "EBX", Dest = "EAX"
                    });
                    conversionState.Append(new ASMOps.Jmp()
                    {
                        JumpType = ASMOps.JmpOp.Jump, DestILPosition = currOpPosition, Extension = "LoopMethodTable"
                    });
                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "NotFound"
                    });
                    //Throw exception!
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "GetEIP"
                    });
                    conversionState.AddExternalLabel("GetEIP");
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
                    });

                    conversionState.Append(new ASMOps.Label()
                    {
                        ILPosition = currOpPosition, Extension = "Call"
                    });

                    //Allocate space on the stack for the return value as necessary
                    Type           retType     = ((MethodInfo)methodToCall).ReturnType;
                    Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                    StackItem      returnItem  = new StackItem()
                    {
                        isFloat            = Utilities.IsFloat(retType),
                        sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                        isGCManaged        = retTypeInfo.IsGCManaged,
                        isValue            = retTypeInfo.IsValueType
                    };
                    //We do not push the return value onto the stack unless it has size > 0
                    //We do not push the return value onto our stack at this point - it is pushed after the call is done

                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        if (returnItem.isFloat)
                        {
                            //SUPPORT - floats
                            throw new NotSupportedException("Cannot handle float return values!");
                        }
                        else
                        {
                            for (int i = 0; i < returnItem.sizeOnStackInBytes; i += 4)
                            {
                                conversionState.Append(new ASMOps.Push()
                                {
                                    Size = ASMOps.OperandSize.Dword, Src = "0"
                                });
                            }
                        }
                    }


                    //Append the actual call
                    conversionState.Append(new ASMOps.Call()
                    {
                        Target = "EAX"
                    });



                    //After a call, we need to remove the return value and parameters from the stack
                    //This is most easily done by just adding the total number of bytes for params and
                    //return value to the stack pointer (ESP register).

                    //Stores the number of bytes to add
                    int bytesToAdd = 0;
                    //All the parameters for the method that was called
                    List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                    //Go through each one
                    if (!methodToCall.IsStatic)
                    {
                        allParams.Insert(0, methodToCall.DeclaringType);
                    }
                    foreach (Type aParam in allParams)
                    {
                        //Pop the paramter off our stack
                        //(Note: Return value was never pushed onto our stack. See above)
                        conversionState.CurrentStackFrame.Stack.Pop();
                        //Add the size of the paramter to the total number of bytes to pop
                        bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                    }
                    //If the number of bytes to add to skip over params is > 0
                    if (bytesToAdd > 0)
                    {
                        //If there is a return value on the stack
                        if (returnItem.sizeOnStackInBytes != 0)
                        {
                            //We need to store the return value then pop all the params

                            //We now push the return value onto our stack as,
                            //after all is said and done below, it will be the
                            //top item on the stack
                            conversionState.CurrentStackFrame.Stack.Push(returnItem);

                            //SUPPORT - floats (with above)

                            //Pop the return value, shift it into final position
                            for (int i = 0; i < returnItem.sizeOnStackInBytes; i += 4)
                            {
                                int srcOffset  = returnItem.sizeOnStackInBytes - i - 4;
                                int destOffset = bytesToAdd + srcOffset;

                                conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Dword, Dest = "EAX", Src = "[ESP+" + srcOffset + "]"
                                });
                                conversionState.Append(new ASMOps.Mov()
                                {
                                    Size = ASMOps.OperandSize.Dword, Dest = "[ESP+" + destOffset + "]", Src = "EAX"
                                });
                            }
                        }
                        //Skip over the params
                        conversionState.Append(new ASMOps.Add()
                        {
                            Src = bytesToAdd.ToString(), Dest = "ESP"
                        });
                    }
                    //No params to skip over but we might still need to store return value
                    else if (returnItem.sizeOnStackInBytes != 0)
                    {
                        //The return value will be the top item on the stack.
                        //So all we need to do is push the return item onto our stack.
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                throw new NotSupportedException("How the hell are we getting callvirts to constructor methods?!");
            }
        }