Beispiel #1
0
        public static void DoExecute(XSharp.Assembler.Assembler Assembler, _MethodInfo aMethod, ushort aParam)
        {
            var  xDisplacement = GetArgumentDisplacement(aMethod, aParam);
            var  xType         = GetArgumentType(aMethod, aParam);
            uint xArgRealSize  = SizeOfType(xType);
            uint xArgSize      = Align(xArgRealSize, 4);

            XS.Comment("Arg idx = " + aParam);
            XS.Comment("Arg type = " + xType);
            XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize);
            if (IsIntegralType(xType) && xArgRealSize == 1 || xArgRealSize == 2)
            {
                if (TypeIsSigned(xType))
                {
                    XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize));
                }
                else
                {
                    XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize));
                }

                XS.Push(EAX);
            }
            else
            {
                for (int i = 0; i < (xArgSize / 4); i++)
                {
                    XS.Push(EBP, isIndirect: true, displacement: (xDisplacement - (i * 4)));
                }
            }
        }
Beispiel #2
0
 public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
 {
     DoNullReferenceCheck(Assembler, DebugEnabled, 0);
     XS.Pop(ECX);
     XS.MoveSignExtend(EAX, ECX, sourceIsIndirect: true, size: RegisterSize.Short16);
     XS.Push(EAX);
 }
Beispiel #3
0
        public static void DoExecute(Cosmos.Assembler.Assembler Assembler, _MethodInfo aMethod, ushort aParam)
        {
            var  xDisplacement = GetArgumentDisplacement(aMethod, aParam);
            var  xType         = GetArgumentType(aMethod, aParam);
            uint xArgRealSize  = SizeOfType(xType);
            uint xArgSize      = Align(xArgRealSize, 4);

            XS.Comment("Arg idx = " + aParam);
            XS.Comment("Arg type = " + xType);
            XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize);
            if (xArgRealSize < 4)
            {
                if (xArgRealSize == 1)
                {
                    XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: RegisterSize.Byte8);
                }
                else
                {
                    XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: RegisterSize.Short16);
                }
                XS.Push(EAX);
            }
            else
            {
                for (int i = 0; i < (xArgSize / 4); i++)
                {
                    XS.Push(EBP, isIndirect: true, displacement: (xDisplacement - (i * 4)));
                }
            }
        }
Beispiel #4
0
        public static void DoAssemble(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            XS.Pop(EAX);
            var xObjSize = SizeOfType(type);

            if (xObjSize < 4 && TypeIsSigned(type))
            {
                if (xObjSize == 1)
                {
                    XS.MoveSignExtend(EBX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                }
                else if (xObjSize == 2)
                {
                    XS.MoveSignExtend(EBX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16);
                }
                XS.Push(EBX);
                return;
            }

            switch (xObjSize % 4)
            {
            case 1:
            {
                XS.Xor(EBX, EBX);
                XS.Set(BL, EAX, sourceDisplacement: (int)(xObjSize - 1));
                //XS.ShiftLeft(XSRegisters.EBX, 24);
                XS.Push(EBX);
                break;
            }

            case 2:
            {
                XS.Xor(EBX, EBX);
                XS.Set(BX, EAX, sourceDisplacement: (int)(xObjSize - 2));
                //XS.ShiftLeft(XSRegisters.EBX, 16);
                XS.Push(EBX);
                break;
            }

            case 0:
            {
                break;
            }

            default:
                throw new Exception("Remainder not supported!");
            }

            xObjSize -= (xObjSize % 4);

            for (int i = 1; i <= (xObjSize / 4); i++)
            {
                XS.Push(EAX, displacement: (int)(xObjSize - (i * 4)));
            }
        }
Beispiel #5
0
        public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, _MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xBaseLabel     = GetLabel(aMethod, aOpCode) + ".";
            var xSuccessLabel  = xBaseLabel + "Success";
            var xOverflowLabel = xBaseLabel + "Overflow";
            var xPositiveLabel = xBaseLabel + "Positive";
            var xNegativeLabel = xBaseLabel + "Negative";

            if (xSourceSize <= 4)
            {
                if (xSourceIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0);
                    XS.MoveSignExtend(EAX, AL);
                    XS.Set(ESP, EAX, destinationIsIndirect: true);
                }
                else
                {
                    if (checkOverflow)
                    {
                        ConvOverflowChecks.CheckOverflowForSmall(1, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel);
                    }
                    XS.Pop(EAX);
                    XS.MoveSignExtend(EAX, AL);
                    XS.Push(EAX);
                }
            }
            else if (xSourceSize <= 8)
            {
                if (xSourceIsFloat)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0);
                    XS.Set(ESP, EAX, destinationIsIndirect: true);
                }
                else
                {
                    if (checkOverflow)
                    {
                        ConvOverflowChecks.CheckOverflowForLong(1, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel);
                    }
                    XS.Pop(EAX);
                    XS.Add(ESP, 4);
                    XS.MoveSignExtend(EAX, AX);
                    XS.Push(EAX);
                }
            }
            else
            {
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->Error: StackSize > 8 not supported");
            }
        }
Beispiel #6
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xSource        = aOpCode.StackPopTypes[0];
            var xSourceSize    = SizeOfType(xSource);
            var xSourceIsFloat = TypeIsFloat(xSource);

            if (xSourceIsFloat)
            {
                if (xSourceSize == 4)
                {
                    new CPUx86.SSE.MoveSS {
                        SourceReg = CPUx86.RegistersEnum.ESP, DestinationReg = CPUx86.RegistersEnum.XMM0, SourceIsIndirect = true
                    };
                    XS.SSE.ConvertSS2SIAndTruncate(XSRegisters.EAX, XSRegisters.XMM0);
                    XS.Set(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true);
                }
                else if (xSourceSize == 8)
                {
                    XS.SSE3.MoveDoubleAndDuplicate(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
                    XS.SSE2.ConvertSD2SIAndTruncate(XSRegisters.EAX, XSRegisters.XMM0);
                    XS.Set(XSRegisters.ESP, XSRegisters.EAX, destinationIsIndirect: true);
                }
                else
                {
                    throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->Unknown size of floating point value.");
                }
            }

            switch (xSourceSize)
            {
            case 1:
                throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->The size 1 could not exist, because always is pushed Int32 or Int64!");

            case 2:
                throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->The size 2 could not exist, because always is pushed Int32 or Int64!");

            case 4:
                XS.Pop(XSRegisters.EAX);
                XS.MoveSignExtend(XSRegisters.EAX, XSRegisters.AL);
                XS.Push(XSRegisters.EAX);
                break;

            case 8:
                XS.Pop(XSRegisters.EAX);
                XS.Pop(XSRegisters.EBX);
                XS.MoveSignExtend(XSRegisters.EAX, XSRegisters.AL);
                XS.Push(XSRegisters.EAX);
                break;

            default:
                //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I1: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->Unknown size of variable on the top of the stack.");
            }
        }
Beispiel #7
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xSource        = aOpCode.StackPopTypes[0];
            var xSourceSize    = SizeOfType(xSource);
            var xSourceIsFloat = TypeIsFloat(xSource);

            if (xSourceIsFloat)
            {
                if (xSourceSize == 4)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0);
                    XS.Set(ESP, EAX, destinationIsIndirect: true);
                }
                else if (xSourceSize == 8)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0);
                    XS.Set(ESP, EAX, destinationIsIndirect: true);
                }
                else
                {
                    throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_I2.cs->Unknown size of floating point value.");
                }
            }

            switch (xSourceSize)
            {
            case 2:
                //throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_I2.cs->The size 2 could not exist, because always is pushed Int32 or Int64!");
                break;

            case 1:
            //throw new Exception("Cosmos.IL2CPU.x86->IL->Conv_I2.cs->The size 1 could not exist, because always is pushed Int32 or Int64!");
            case 4:
                XS.Pop(XSRegisters.EAX);
                XS.MoveSignExtend(XSRegisters.EAX, XSRegisters.AX);
                XS.Push(XSRegisters.EAX);
                break;

            case 8:
                XS.Pop(XSRegisters.EAX);
                XS.Pop(XSRegisters.EBX);
                XS.MoveSignExtend(XSRegisters.EAX, XSRegisters.AX);
                XS.Push(XSRegisters.EAX);
                break;

            default:
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I2.cs->SourceSize " + xSource + " not supported!");
            }
        }
Beispiel #8
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var  xOpVar      = (OpVar)aOpCode;
            var  xVar        = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value];
            var  xStackCount = (int)GetStackCountForLocal(aMethod, xVar.LocalType);
            var  xEBPOffset  = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value);
            var  xSize       = SizeOfType(xVar.LocalType);
            bool xSigned     = IsIntegerSigned(xVar.LocalType);

            XS.Comment("Local type = " + xVar.LocalType);
            XS.Comment("Local EBP offset = " + xEBPOffset);
            XS.Comment("Local size = " + xSize);

            switch (xSize)
            {
            case 1:
                if (xSigned)
                {
                    XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Byte8);
                }
                else
                {
                    XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Byte8);
                }
                XS.Push(EAX);
                break;

            case 2:
                if (xSigned)
                {
                    XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Short16);
                }
                else
                {
                    XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: (0 - xEBPOffset), size: RegisterSize.Short16);
                }
                XS.Push(EAX);
                break;

            default:
                for (int i = 0; i < xStackCount; i++)
                {
                    XS.Set(EAX, EBP, sourceDisplacement: 0 - (xEBPOffset + (i * 4)));
                    XS.Push(EAX);
                }
                break;
            }
        }
Beispiel #9
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xSource        = aOpCode.StackPopTypes[0];
            var xSourceSize    = SizeOfType(xSource);
            var xSourceIsFloat = TypeIsFloat(xSource);

            if (xSourceSize <= 4)
            {
                if (xSourceIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0);
                    XS.MoveSignExtend(EAX, AL);
                    XS.Set(ESP, EAX, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EAX);
                    XS.MoveSignExtend(EAX, AL);
                    XS.Push(EAX);
                }
            }
            else if (xSourceSize <= 8)
            {
                if (xSourceIsFloat)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0);
                    XS.Set(ESP, EAX, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EAX);
                    XS.Add(ESP, 4);
                    XS.MoveSignExtend(EAX, AL);
                    XS.Push(EAX);
                }
            }
            else
            {
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->Error: StackSize > 8 not supported");
            }
        }
Beispiel #10
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            DoNullReferenceCheck(Assembler, DebugEnabled, 0);

            XS.Pop(EAX);

            switch (aOpCode.OpCode)
            {
            case ILOpCode.Code.Ldind_I1:
                XS.MoveSignExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                XS.Push(EAX);
                break;

            case ILOpCode.Code.Ldind_I2:
                XS.MoveSignExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16);
                XS.Push(EAX);
                break;

            case ILOpCode.Code.Ldind_U1:
                XS.MoveZeroExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                XS.Push(EAX);
                break;

            case ILOpCode.Code.Ldind_U2:
                XS.MoveZeroExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16);
                XS.Push(EAX);
                break;

            case ILOpCode.Code.Ldind_I:
            case ILOpCode.Code.Ldind_I4:
            case ILOpCode.Code.Ldind_U4:
            case ILOpCode.Code.Ldind_R4:
                XS.Push(EAX, isIndirect: true);
                break;

            case ILOpCode.Code.Ldind_I8:
            case ILOpCode.Code.Ldind_R8:
            case ILOpCode.Code.Ldind_Ref:
                XS.Push(EAX, displacement: 4);
                XS.Push(EAX, isIndirect: true);
                break;
            }
        }
Beispiel #11
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xOpCode    = (OpField)aOpCode;
            var xStackType = aOpCode.StackPopTypes[0];

            var xFieldInfo     = ResolveField(xOpCode.Value);
            var xDeclaringType = xFieldInfo.DeclaringType;
            var xFieldType     = xFieldInfo.FieldType;
            var xOffset        = GetFieldOffset(xFieldInfo);

            XS.Comment("Field: " + xFieldInfo.Id);
            XS.Comment("Type: " + xFieldInfo.FieldType.ToString());
            XS.Comment("Size: " + xFieldInfo.Size);
            XS.Comment("DeclaringType: " + xDeclaringType.FullName);
            XS.Comment("TypeOnStack: " + xStackType.FullName);
            XS.Comment("Offset: " + xOffset + " (includes object header)");

            if (xDeclaringType.IsValueType && MemberInfoComparer.Instance.Equals(xDeclaringType, xStackType))
            {
                var xDeclaringTypeStackSize = Align(SizeOfType(xDeclaringType), 4);
                var xFieldSize   = xFieldInfo.Size;
                var xStackOffset = (int)(-xDeclaringTypeStackSize + xOffset + xFieldSize - 4);

                XS.Add(ESP, xDeclaringTypeStackSize);

                if ((xFieldInfo.Size < 4 && IsIntegerBasedType(xFieldType)) ||
                    xFieldType == typeof(bool) ||
                    xFieldType == typeof(char))
                {
                    if (TypeIsSigned(xFieldType))
                    {
                        XS.MoveSignExtend(EAX, ESP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize));
                        XS.Push(EAX);
                    }
                    else
                    {
                        XS.MoveZeroExtend(EAX, ESP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize));
                        XS.Push(EAX);
                    }

                    return;
                }

                for (int i = 0; i < xFieldSize / 4; i++)
                {
                    XS.Push(ESP, displacement: xStackOffset);
                }

                switch (xFieldSize % 4)
                {
                case 0:
                    break;

                case 1:
                    XS.Xor(EAX, EAX);
                    XS.Set(AL, ESP, sourceDisplacement: xStackOffset + 3);
                    XS.Push(EAX);
                    break;

                case 2:
                    XS.Xor(EAX, EAX);
                    XS.Set(AX, ESP, sourceDisplacement: xStackOffset + 2);
                    XS.Push(EAX);
                    break;

                case 3:
                    XS.Xor(EAX, EAX);
                    XS.Set(AX, ESP, sourceDisplacement: xStackOffset + 2);
                    XS.ShiftLeft(EAX, 4);
                    XS.Set(AL, ESP, sourceDisplacement: xStackOffset + 1);
                    XS.Push(EAX);
                    break;

                default:
                    throw new NotImplementedException();
                }

                return;
            }

            // pushed size is always 4 or 8
            var xSize = xFieldInfo.Size;

            if (IsReferenceType(xStackType))
            {
                DoNullReferenceCheck(Assembler, DebugEnabled, 4);
                XS.Add(ESP, 4);
            }
            else
            {
                DoNullReferenceCheck(Assembler, DebugEnabled, 0);
            }
            XS.Pop(ECX);

            XS.Add(ECX, (uint)(xOffset));

            if (xFieldInfo.IsExternalValue)
            {
                XS.Set(ECX, ECX, sourceIsIndirect: true);
            }

            for (int i = 1; i <= (xSize / 4); i++)
            {
                XS.Set(EAX, ECX, sourceDisplacement: (int)(xSize - (i * 4)));
                XS.Push(EAX);
            }

            if (xSize % 4 != 0)
            {
                XS.Set(EAX, 0);
            }

            switch (xSize % 4)
            {
            case 1:
                XS.Set(AL, ECX, sourceIsIndirect: true);
                XS.Push(EAX);
                break;

            case 2:
                XS.Set(AX, ECX, sourceIsIndirect: true);
                XS.Push(EAX);
                break;

            case 3:     //For Release
                XS.Set(EAX, ECX, sourceIsIndirect: true);
                XS.ShiftRight(EAX, 8);
                XS.Push(EAX);
                break;

            case 0:
            {
                break;
            }

            default:
                throw new Exception(string.Format("Remainder size {0} {1:D} not supported!", xFieldInfo.FieldType.ToString(), xSize));
            }
        }
Beispiel #12
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            //  stack     = index
            //  stack + 2 = array
            DoNullReferenceCheck(aAssembler, debugEnabled, 8);

            // calculate element offset into array memory (including header)
            XS.Pop(EAX);
            XS.Set(EDX, aElementSize);
            XS.Multiply(EDX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4);

            if (aElementSize > 4)
            {
                // we start copying the last bytes
                XS.Add(EAX, aElementSize - 4);
            }

            // pop the array now
            XS.Add(ESP, 4);
            XS.Pop(EDX);

            XS.Add(EDX, EAX);

            var xSizeLeft = aElementSize;

            while (xSizeLeft > 0)
            {
                var xCurrentStep = Math.Min(xSizeLeft, 4);
                if (xSizeLeft % 4 != 0)
                {
                    xCurrentStep = xSizeLeft % 4;
                }

                xSizeLeft = xSizeLeft - xCurrentStep;
                switch (xCurrentStep)
                {
                case 1:
                    if (isSigned)
                    {
                        XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                    }
                    else
                    {
                        XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                    }
                    XS.Push(ECX);
                    break;

                case 2:
                    if (isSigned)
                    {
                        XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16);
                    }
                    else
                    {
                        XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16);
                    }
                    XS.Push(ECX);
                    break;

                case 4:
                    // copy a full dword
                    XS.Push(EDX, true);
                    XS.Sub(EDX, 4); // move to previous 4 bytes
                    break;
                    //case 8:
                    //    new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true};
                    //    XS.Push(XSRegisters.EDX, isIndirect: true);
                    //    break;
                }
            }
        }
Beispiel #13
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            //  stack     = index
            //  stack + 2 = array
            DoNullReferenceCheck(aAssembler, debugEnabled, 8);

            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException";
            var xIndexOutOfRangeExeptionLabel   = xBaseLabel + "_IndexOutOfRangeException";

            XS.Pop(EBX);                                     //get Position _, array, 0, index -> _, array, 0
            XS.Push(ESP, true, 4);                           // _, array, 0 => _, array, 0, array
            XS.Push(ESP, true, 12);                          // _, array, 0, array => _, array, 0, array, 0
            Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length
            XS.Pop(EAX);                                     //Length of array _, array, 0, length -> _, array, 0
            XS.Compare(EAX, EBX);
            XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel);

            XS.Compare(EBX, 0);
            XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel);

            XS.Label(xIndexOutOfRangeExeptionLabel);
            XS.Pop(EAX);
            XS.Pop(EAX);
            Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled);

            XS.Label(xNoIndexOutOfRangeExeptionLabel);
            XS.Push(EBX); //_, array, 0 -> _, array, 0, index

            // calculate element offset into array memory (including header)
            XS.Pop(EAX);
            XS.Set(EDX, aElementSize);
            XS.Multiply(EDX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4);

            if (aElementSize > 4)
            {
                // we start copying the last bytes
                XS.Add(EAX, aElementSize - 4);
            }

            // pop the array now
            XS.Add(ESP, 4);
            XS.Pop(EDX);

            XS.Add(EDX, EAX);

            var xSizeLeft = aElementSize;

            while (xSizeLeft > 0)
            {
                var xCurrentStep = Math.Min(xSizeLeft, 4);
                if (xSizeLeft % 4 != 0)
                {
                    xCurrentStep = xSizeLeft % 4;
                }

                xSizeLeft = xSizeLeft - xCurrentStep;
                switch (xCurrentStep)
                {
                case 1:
                    if (isSigned)
                    {
                        XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                    }
                    else
                    {
                        XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8);
                    }
                    XS.Push(ECX);
                    break;

                case 2:
                    if (isSigned)
                    {
                        XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16);
                    }
                    else
                    {
                        XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16);
                    }
                    XS.Push(ECX);
                    break;

                case 4:
                    // copy a full dword
                    XS.Push(EDX, true);
                    XS.Sub(EDX, 4); // move to previous 4 bytes
                    break;
                    //case 8:
                    //    new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true};
                    //    XS.Push(XSRegisters.EDX, isIndirect: true);
                    //    break;
                }
            }
        }