Beispiel #1
0
        // this code is mostly copied from Newarr.cs in Il2CPU, just the code to find the size and length is different
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            string     xTypeID   = ILOp.GetTypeIDLabel(typeof(Array));
            MethodBase xCtor     = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0];
            string     xCtorName = LabelName.Get(xCtor);

            XS.Set(ECX, EBP, sourceDisplacement: 8);  // size
            XS.Set(EDX, EBP, sourceDisplacement: 12); // length



            XS.Push(ECX);                                 // size of element
            XS.Set(EAX, ECX);
            XS.Multiply(EDX);                             // total element size
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size
            XS.Push(EAX);
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Label(".AfterAlloc");
            XS.Pop(EAX);
            XS.Pop(ESI);
            XS.Push(EAX);
            XS.Push(ESP, isIndirect: true);
            XS.Push(ESP, isIndirect: true);
            // it's on the stack 3 times now, once from the return value, twice from the pushes;

            XS.Pop(EAX);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);  // array type id
            XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id
            XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true);
            XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true);
            XS.Set(EAX, ECX);
            XS.Push(0);
            XS.Call(xCtorName);
            XS.Push(0);
        }
Beispiel #2
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            // stack     == the new value
            // stack + 1 == the index
            // stack + 2 == the array
            DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4)));

            uint xStackSize = aElementSize;

            if (xStackSize % 4 != 0)
            {
                xStackSize += 4 - xStackSize % 4;
            }

            // calculate element offset into array memory (including header)
            XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: (int)xStackSize); // the index
            XS.Set(XSRegisters.EDX, aElementSize);
            XS.Multiply(XSRegisters.EDX);
            XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset + 4);

            XS.Set(XSRegisters.EDX, XSRegisters.ESP, sourceDisplacement: (int)xStackSize + 8); // the array
            XS.Add(XSRegisters.EDX, XSRegisters.EAX);
            XS.Push(XSRegisters.EDX);

            XS.Pop(XSRegisters.ECX);
            for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1)
            {
                new Comment(aAssembler, "Start 1 dword");
                XS.Pop(XSRegisters.EBX);
                XS.Set(XSRegisters.ECX, XSRegisters.EBX, destinationIsIndirect: true);
                XS.Add(XSRegisters.ECX, 4);
            }
            switch (aElementSize % 4)
            {
            case 1:
            {
                new Comment(aAssembler, "Start 1 byte");
                XS.Pop(XSRegisters.EBX);
                XS.Set(XSRegisters.ECX, XSRegisters.BL, destinationIsIndirect: true);
                break;
            }

            case 2:
            {
                new Comment(aAssembler, "Start 1 word");
                XS.Pop(XSRegisters.EBX);
                XS.Set(XSRegisters.ECX, XSRegisters.BX, destinationIsIndirect: true);
                break;
            }

            case 0:
            {
                break;
            }

            default:
                throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!");
            }
            XS.Add(XSRegisters.ESP, 12);
        }
Beispiel #3
0
        public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle)
        {
            // Arguments:
            //    Array aArray, RuntimeFieldHandle aFieldHandle
            XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: 0xC); // array
            XS.Set(EDI, EDI, sourceIsIndirect: true);
            XS.Set(XSRegisters.ESI, XSRegisters.EBP, sourceDisplacement: 8);   // aFieldHandle
            XS.Add(XSRegisters.EDI, 8);
            XS.Push(EDI, isIndirect: true);
            XS.Add(XSRegisters.EDI, 4);
            XS.Set(EAX, EDI, sourceIsIndirect: true);
            XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32);
            XS.Pop(XSRegisters.ECX);
            XS.Set(XSRegisters.ECX, XSRegisters.EAX);
            XS.Set(XSRegisters.EAX, 0);
            XS.Add(XSRegisters.EDI, 4);

            XS.Label(".StartLoop");
            XS.Set(DL, ESI, sourceIsIndirect: true);
            XS.Set(EDI, DL, destinationIsIndirect: true);
            XS.Add(XSRegisters.EAX, 1);
            XS.Add(XSRegisters.ESI, 1);
            XS.Add(XSRegisters.EDI, 1);
            XS.Compare(XSRegisters.EAX, XSRegisters.ECX);
            XS.Jump(CPUx86.ConditionalTestEnum.Equal, ".EndLoop");
            XS.Jump(".StartLoop");

            XS.Label(".EndLoop");
        }
Beispiel #4
0
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            // load element size into eax
            // load length into ebx
            // calculate entire size into eax and move to exc
            // load start into edi
            // clear ecx bytes starting at edi

            // load element size into eax
            XS.Set(EAX, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EAX, 8);
            XS.Set(EAX, EAX, sourceIsIndirect: true);

            // load length into ebx
            XS.Set(EBX, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EBX, 12);
            XS.Set(EBX, EBX, sourceIsIndirect: true);

            // calculate size in bytes and move to ecx
            XS.Multiply(EBX);
            XS.Set(ECX, EAX);

            // load start into esi
            XS.Set(EDI, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EDI, 16);

            // clear eax bytes starting at esi
            XS.Set(EAX, 0);
            XS.LiteralCode("rep stosb");
        }
Beispiel #5
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled)
        {
            XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName);
            XS.Comment("Size: " + aElementSize);

            DoNullReferenceCheck(aAssembler, debugEnabled, 4);
            // calculate element offset into array memory (including header)
            XS.Pop(XSRegisters.EAX);
            XS.Set(XSRegisters.EDX, aElementSize);
            XS.Multiply(XSRegisters.EDX);
            XS.Add(XSRegisters.EAX, (uint)(ObjectImpl.FieldDataOffset + 4));

            // pop the array now
            XS.Pop(XSRegisters.EDX);
            // translate it to actual memory
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true);

            if (aOpType.StackPopTypes.Last().GetElementType().IsClass)
            {
                XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true);
            }

            XS.Add(XSRegisters.EDX, XSRegisters.EAX);
            XS.Push(XSRegisters.EDX);
        }
Beispiel #6
0
        public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled, _MethodInfo aMethod, ILOpCode aOpCode)
        {
            XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName);
            XS.Comment("Size: " + aElementSize);

            DoNullReferenceCheck(aAssembler, debugEnabled, 8);

            //Do check for index out of range
            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, (uint)(ObjectUtils.FieldDataOffset + 4));

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

            XS.Add(EDX, EAX);
            XS.Push(EDX);
        }
Beispiel #7
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType = (ILOpCodes.OpType)aOpCode;

            uint xSize = SizeOfType(xType.Value.GetElementType() ?? xType.Value);

            string     xTypeID   = GetTypeIDLabel(xType.Value.GetElementType() ?? xType.Value);
            MethodBase xCtor     = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0];
            string     xCtorName = LabelName.Get(xCtor);

            XS.Comment("Element Size = " + xSize);
            XS.Pop(EAX); // element count
            XS.Push(EAX);
            XS.Set(EDX, xSize);
            XS.Multiply(EDX);                             // total element size
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size
            XS.Push(EAX);
            //XS.Push(0x4E3A44A9);
            //XS.LiteralCode("Call DebugStub_SendSimpleNumber");
            //XS.Pop(EAX);
            //XS.Push(".AfterAlloc");
            //XS.LiteralCode("Call DebugStub_SendSimpleNumber");
            //XS.Pop(EAX);
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Label(".AfterAlloc");
            XS.Pop(EAX); // location
            //XS.LiteralCode("Call DebugStub_SendSimpleNumber");
            XS.Pop(ESI); // element count
            XS.Push(EAX);
            XS.Push(ESP, isIndirect: true);
            XS.Push(ESP, isIndirect: true);
            // it's on the stack 3 times now, once from the return value, twice from the pushes;

            XS.Pop(EAX);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);                                 // array type id
            XS.Set(EAX, EBX, destinationIsIndirect: true);                                // array type id
            XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true);
            XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true);    // element count
            XS.Set(EAX, xSize, destinationDisplacement: 12, destinationIsIndirect: true); // element size
            XS.Push(0);
            XS.Call(xCtorName);
            XS.Push(0);
        }
Beispiel #8
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled)
        {
            XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName);
            XS.Comment("Size: " + aElementSize);

            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, (uint)(ObjectImpl.FieldDataOffset + 4));

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

            XS.Add(EDX, EAX);
            XS.Push(EDX);
        }
        /* void Copy(Array sourceArray,			ebp + 0x1C
         *			 int sourceIndex,			ebp + 0x18
         *			 Array destinationArray,	ebp + 0x14
         *			 int destinationIndex,		ebp + 0x10
         *			 int length,				ebp + 0xC
         *			 bool reliable);			ebp + 0x8
         */
        public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
        {
            XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // dereference memory handle to pointer
            XS.Push(XSRegisters.EAX);
            new CPUx86.Add {
                DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, SourceValue = 12, Size = 32
            };                                                                // pointer is at the element size
            XS.Pop(XSRegisters.EAX);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
            XS.Set(XSRegisters.EBX, XSRegisters.EBP, sourceDisplacement: SourceIndexDisplacement);
            XS.Multiply(XSRegisters.EBX);
            XS.Add(XSRegisters.EAX, 16);
            XS.Set(XSRegisters.ESI, XSRegisters.EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Set(XSRegisters.ESI, XSRegisters.ESI, sourceIsIndirect: true); // dereference memory handle to pointer
            XS.Add(XSRegisters.ESI, XSRegisters.EAX);                         // source ptr
            XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true); // dereference memory handle to pointer
            XS.Push(XSRegisters.EDX);
            new CPUx86.Add {
                DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, SourceValue = 12, Size = 32
            };                                                                // pointer is at element size
            XS.Pop(XSRegisters.EAX);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // dereference handle to pointer
            XS.Set(XSRegisters.ECX, XSRegisters.EBP, sourceDisplacement: DestinationIndexDisplacement);
            XS.Multiply(XSRegisters.ECX);
            XS.Add(XSRegisters.EAX, 16);
            XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceIsIndirect: true); // dereference handle to pointer
            XS.Add(XSRegisters.EDI, XSRegisters.EAX);

            // calculate byte count to copy
            XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // dereference memory handle to pointer
            XS.Add(XSRegisters.EAX, 12);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true);
            XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: LengthDisplacement);
            XS.Multiply(XSRegisters.EDX);
            XS.Set(XSRegisters.ECX, XSRegisters.EAX);
            new CPUx86.Movs {
                Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
            };
        }
Beispiel #10
0
        /* void Copy(
         *           Array sourceArray,			ebp + 36
         *			 int sourceIndex,			ebp + 28
         *			 Array destinationArray,	ebp + 24
         *			 int destinationIndex,		ebp + 16
         *			 int length,				ebp + 12
         *			 bool reliable);			ebp + 8
         */

        public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
        {
            XS.Comment("Source");
            XS.Comment("Element size");
            XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
            XS.Comment("Source ptr");
            XS.Set(XSRegisters.EBX, XSRegisters.EBP, sourceDisplacement: SourceIndexDisplacement);
            XS.Multiply(XSRegisters.EBX);
            XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset + 4); // first element
            XS.Set(XSRegisters.ESI, XSRegisters.EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(XSRegisters.ESI, XSRegisters.EAX);                 // source ptr

            XS.Comment("Destination");
            XS.Comment("Element size");
            XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
            XS.Comment("Destination ptr");
            XS.Set(XSRegisters.ECX, XSRegisters.EBP, sourceDisplacement: DestinationIndexDisplacement);
            XS.Multiply(XSRegisters.ECX);
            XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset + 4); // first element
            XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Add(XSRegisters.EDI, XSRegisters.EAX);                 // destination ptr

            XS.Comment("Copy byte count");
            XS.Comment("Element size");
            XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset);
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
            XS.Comment("Count");
            XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: LengthDisplacement);
            XS.Multiply(XSRegisters.EDX);
            XS.Set(XSRegisters.ECX, XSRegisters.EAX);
            new CPUx86.Movs {
                Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
            };
        }
Beispiel #11
0
        public static void Assemble(Assembler aAssembler, _MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor)
        {
            // call cctor:
            if (aMethod != null)
            {
                var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? Array.Empty <ConstructorInfo>()).SingleOrDefault();
                if (xCctor != null)
                {
                    XS.Call(LabelName.Get(xCctor));
                    EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }

            if (objectType.IsValueType)
            {
                #region Valuetypes

                XS.Comment("ValueType");
                XS.Comment("Type: " + objectType);

                /*
                 * Current sitation on stack:
                 *   $ESP       Arg
                 *   $ESP+..    other items
                 *
                 * What should happen:
                 *  + The stack should be increased to allow space to contain:
                 *         + .ctor arguments
                 *         + struct _pointer_ (ref to start of emptied space)
                 *         + empty space for struct
                 *  + arguments should be copied to the new place
                 *  + old place where arguments were should be cleared
                 *  + pointer should be set
                 *  + call .ctor
                 */

                // Size of return value - we need to make room for this on the stack.
                uint xStorageSize = Align(SizeOfType(objectType), 4);
                XS.Comment("StorageSize: " + xStorageSize);
                if (xStorageSize == 0)
                {
                    throw new Exception("ValueType storage size cannot be 0.");
                }

                uint xArgSize       = 0;
                var  xParameterList = constructor.GetParameters();
                foreach (var xParam in xParameterList)
                {
                    xArgSize = xArgSize + Align(SizeOfType(xParam.ParameterType), 4);
                }
                XS.Comment("ArgSize: " + xArgSize);

                // set source of args copy
                XS.Set(ESI, ESP);

                // allocate space for struct
                XS.Sub(ESP, xStorageSize + 4);

                // set destination and count of args copy
                XS.Set(EDI, ESP);
                XS.Set(ECX, xArgSize / 4);

                // move the args to their new location
                new CPUx86.Movs {
                    Size = 32, Prefixes = CPUx86.InstructionPrefixes.Repeat
                };

                // set struct ptr
                XS.Set(EAX, ESP);
                XS.Add(EAX, xArgSize + 4);
                XS.Set(ESP, EAX, destinationDisplacement: (int)xArgSize);

                XS.Push(EAX);

                var xOpType = new OpType(xMethod.OpCode, xMethod.Position, xMethod.NextPosition, xMethod.Value.DeclaringType, xMethod.CurrentExceptionRegion);
                new Initobj(aAssembler).Execute(aMethod, xOpType);

                new Call(aAssembler).Execute(aMethod, xMethod);

                // Need to put these *after* the call because the Call pops the args from the stack
                // and we have mucked about on the stack, so this makes it right before the next
                // op.

                #endregion Valuetypes
            }
            else
            {
                // If not ValueType, then we need gc

                var xParams = constructor.GetParameters();

                // array length + 8
                bool xHasCalcSize = false;

                #region Special string handling
                // try calculating size:
                if (constructor.DeclaringType == typeof(string))
                {
                    if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char[]))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceDisplacement: 4, sourceIsIndirect: true); // address
                        XS.Set(EAX, EAX, sourceDisplacement: 8, sourceIsIndirect: true); // element count
                        XS.Set(EDX, 2);                                                  // element size
                        XS.Multiply(EDX);
                        XS.Push(EAX);
                    }
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(char[]) || xParams[0].ParameterType == typeof(char *)) &&
                             xParams[1].ParameterType == typeof(int) &&
                             xParams[2].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(EAX, 1);
                        XS.Push(EAX);
                    }
                    else if (xParams.Length == 2 &&
                             xParams[0].ParameterType == typeof(char) &&
                             xParams[1].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(EAX, 1);
                        XS.Push(EAX);
                    }

                    /*
                     * TODO see if something is needed in stack / register to make them really work
                     */
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(sbyte *) &&
                              xParams[1].ParameterType == typeof(int) &&
                              xParams[2].ParameterType == typeof(int)))
                    {
                        xHasCalcSize = true;
                        XS.Push(ESP, isIndirect: true);
                    }
                    else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(sbyte *))
                    {
                        xHasCalcSize = true;
                        /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */
                        var xSByteCountLabel = currentLabel + ".SByteCount";

                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.Or(ECX, 0xFFFFFFFF);

                        XS.Label(xSByteCountLabel);

                        XS.Increment(EAX);
                        XS.Increment(ECX);

                        XS.Compare(EAX, 0, destinationIsIndirect: true);
                        XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel);

                        XS.Push(ECX);
                    }
                    else
                    {
                        throw new NotImplementedException("In NewObj, a string ctor implementation is missing!");
                    }
                }
                #endregion Special string handling

                uint xMemSize   = GetStorageSize(objectType);
                int  xExtraSize = 12; // additional size for set values after alloc
                XS.Push((uint)(xMemSize + xExtraSize));
                if (xHasCalcSize)
                {
                    XS.Pop(EAX);
                    XS.Add(ESP, EAX, destinationIsIndirect: true);
                }

                // todo: probably we want to check for exceptions after calling Alloc
                XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
                XS.Label(".AfterAlloc");
                XS.Push(ESP, isIndirect: true);
                XS.Push(ESP, isIndirect: true);
                // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes

                // todo: use a cleaner approach here. this class shouldnt assemble the string
                string strTypeId = GetTypeIDLabel(constructor.DeclaringType);

                XS.Pop(EAX);
                XS.Set(EBX, strTypeId, sourceIsIndirect: true);
                XS.Set(EAX, EBX, destinationIsIndirect: true);
                XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.NormalObject, destinationDisplacement: 4, destinationIsIndirect: true, size: RegisterSize.Int32);
                XS.Set(EAX, xMemSize, destinationDisplacement: 8, destinationIsIndirect: true, size: RegisterSize.Int32);
                uint xSize = (uint)(from item in xParams
                                    let xQSize = Align(SizeOfType(item.ParameterType), 4)
                                                 select(int) xQSize).Take(xParams.Length).Sum();
                XS.Push(0);

                foreach (var xParam in xParams)
                {
                    uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4);
                    XS.Comment($"Arg {xParam.Name}: {xParamSize}");
                    for (int i = 0; i < xParamSize; i += 4)
                    {
                        XS.Push(ESP, isIndirect: true, displacement: (int)(xSize + 8));
                    }
                }


                XS.Call(LabelName.Get(constructor));
                // should the complete error handling happen by ILOp.EmitExceptionLogic?
                if (aMethod != null)
                {
                    // todo: only happening for real methods now, not for ctor's ?
                    XS.Test(ECX, 2);
                    string xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString();
                    XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel);

                    PushAlignedParameterSize(constructor);

                    // an exception occurred, we need to cleanup the stack, and jump to the exit
                    XS.Add(ESP, 4);

                    new Comment(aAssembler, "[ Newobj.Execute cleanup end ]");
                    Jump_Exception(aMethod);
                    XS.Label(xNoErrorLabel);
                }
                XS.Pop(EAX);

                PushAlignedParameterSize(constructor);

                XS.Push(EAX);
                XS.Push(0);
            }
        }
        /* void Copy(
         *           Array sourceArray,			ebp + 36
         *			 int sourceIndex,			ebp + 28
         *			 Array destinationArray,	ebp + 24
         *			 int destinationIndex,		ebp + 16
         *			 int length,				ebp + 12
         *			 bool reliable);			ebp + 8
         */

        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            var xArrayCopyReverseLabel     = "ArrayCopy_Reverse";
            var xArrayCopyReverseLoopLabel = "ArrayCopy_Reverse_Loop";
            var xArrayCopyEndLabel         = "ArrayCopy_End";

            XS.Comment("Source");
            XS.Comment("Element size");
            XS.Set(EAX, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(EAX, ObjectUtils.FieldDataOffset);
            XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
            XS.Comment("Source ptr");
            XS.Set(EBX, EBP, sourceDisplacement: SourceIndexDisplacement);
            XS.Multiply(EBX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // first element
            XS.Set(ESI, EBP, sourceDisplacement: SourceArrayDisplacement);
            XS.Add(ESI, EAX);                             // source ptr

            XS.Comment("Destination");
            XS.Comment("Element size");
            XS.Set(EAX, EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Add(EAX, ObjectUtils.FieldDataOffset);
            XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
            XS.Comment("Destination ptr");
            XS.Set(ECX, EBP, sourceDisplacement: DestinationIndexDisplacement);
            XS.Multiply(ECX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // first element
            XS.Set(EDI, EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Add(EDI, EAX);                             // destination ptr

            XS.Compare(EDI, ESI);
            XS.Jump(ConditionalTestEnum.Equal, xArrayCopyEndLabel);

            XS.Comment("Copy byte count");
            XS.Comment("Element size");
            XS.Set(EAX, EBP, sourceDisplacement: DestinationArrayDisplacement);
            XS.Add(EAX, ObjectUtils.FieldDataOffset);
            XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
            XS.Comment("Count");
            XS.Set(EDX, EBP, sourceDisplacement: LengthDisplacement);

            // if length is 0, jump to end
            XS.Compare(EDX, 0);
            XS.Jump(ConditionalTestEnum.Equal, xArrayCopyEndLabel);

            XS.Multiply(EDX);
            XS.Set(ECX, EAX);

            XS.Compare(EDI, ESI);
            XS.Jump(ConditionalTestEnum.GreaterThan, xArrayCopyReverseLabel);

            new Movs {
                Size = 8, Prefixes = InstructionPrefixes.Repeat
            };

            XS.Jump(xArrayCopyEndLabel);

            XS.Label(xArrayCopyReverseLabel);

            XS.Add(ESI, ECX);
            XS.Add(EDI, ECX);

            XS.Label(xArrayCopyReverseLoopLabel);

            XS.Decrement(ESI);
            XS.Decrement(EDI);
            XS.Decrement(ECX);

            XS.Set(AL, ESI, sourceIsIndirect: true);
            XS.Set(EDI, AL, destinationIsIndirect: true);

            XS.Compare(ECX, 0);
            XS.Jump(ConditionalTestEnum.NotEqual, xArrayCopyReverseLoopLabel);

            XS.Label(xArrayCopyEndLabel);
        }
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);

            // 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 #14
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, uint aElementSize, bool isSigned, bool debugEnabled)
        {
            DoNullReferenceCheck(aAssembler, debugEnabled, 4);
            //if (aElementSize <= 0 || aElementSize > 8 || (aElementSize > 4 && aElementSize < 8))
            //{
            //    throw new Exception("Unsupported size for Ldelem_Ref: " + aElementSize);
            //}

            XS.Pop(XSRegisters.EAX);
            XS.Set(XSRegisters.EDX, aElementSize);
            XS.Multiply(XSRegisters.EDX);

            XS.Add(XSRegisters.EAX, (ObjectImpl.FieldDataOffset + 4));

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

            // pop the array
            XS.Pop(XSRegisters.EDX);
            // convert to real memory address
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true);

            XS.Add(XSRegisters.EDX, XSRegisters.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)
                    {
                        new CPUx86.MoveSignExtend {
                            DestinationReg = CPUx86.RegistersEnum.ECX, Size = 8, SourceReg = CPUx86.RegistersEnum.EDX, SourceIsIndirect = true
                        };
                    }
                    else
                    {
                        new CPUx86.MoveZeroExtend {
                            DestinationReg = CPUx86.RegistersEnum.ECX, Size = 8, SourceReg = CPUx86.RegistersEnum.EDX, SourceIsIndirect = true
                        };
                    }
                    XS.Push(XSRegisters.ECX);
                    break;

                case 2:
                    if (isSigned)
                    {
                        new CPUx86.MoveSignExtend {
                            DestinationReg = CPUx86.RegistersEnum.ECX, Size = 16, SourceReg = CPUx86.RegistersEnum.EDX, SourceIsIndirect = true
                        };
                    }
                    else
                    {
                        new CPUx86.MoveZeroExtend {
                            DestinationReg = CPUx86.RegistersEnum.ECX, Size = 16, SourceReg = CPUx86.RegistersEnum.EDX, SourceIsIndirect = true
                        };
                    }
                    XS.Push(XSRegisters.ECX);
                    break;

                case 4:
                    // copy a full dword
                    XS.Push(XSRegisters.EDX, isIndirect: true);
                    XS.Sub(XSRegisters.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 #15
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;
                }
            }
        }
Beispiel #16
0
        public static void Assemble(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor)
        {
            // call cctor:
            if (aMethod != null)
            {
                var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();
                if (xCctor != null)
                {
                    XS.Call(LabelName.Get(xCctor));
                    ILOp.EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }

            if (objectType.IsValueType)
            {
                #region Valuetypes

                XS.Comment("ValueType");

                /*
                 * Current sitation on stack:
                 *   $ESP       Arg
                 *   $ESP+..    other items
                 *
                 * What should happen:
                 *  + The stack should be increased to allow space to contain:
                 *         + .ctor arguments
                 *         + struct _pointer_ (ref to start of emptied space)
                 *         + empty space for struct
                 *  + arguments should be copied to the new place
                 *  + old place where arguments were should be cleared
                 *  + pointer should be set
                 *  + call .ctor
                 */

                // Size of return value - we need to make room for this on the stack.
                uint xStorageSize = Align(SizeOfType(objectType), 4);
                XS.Comment("StorageSize: " + xStorageSize);
                if (xStorageSize == 0)
                {
                    throw new Exception("ValueType storage size cannot be 0.");
                }

                //var xStorageSize = aCtorDeclTypeInfo.StorageSize;

                uint xArgSize       = 0;
                var  xParameterList = constructor.GetParameters();
                foreach (var xParam in xParameterList)
                {
                    xArgSize = xArgSize + Align(SizeOfType(xParam.ParameterType), 4);
                }
                XS.Comment("ArgSize: " + xArgSize);

                // Set ESP so we can push the struct ptr
                int xShift = (int)(xArgSize - xStorageSize);
                XS.Comment("Shift: " + xShift);
                if (xShift < 0)
                {
                    XS.Sub(XSRegisters.ESP, (uint)Math.Abs(xShift));
                }
                else if (xShift > 0)
                {
                    XS.Add(XSRegisters.ESP, (uint)xShift);
                }

                // push struct ptr
                XS.Push(XSRegisters.ESP);

                // Shift args
                foreach (var xParam in xParameterList)
                {
                    uint xArgSizeForThis = Align(SizeOfType(xParam.ParameterType), 4);
                    for (int i = 1; i <= xArgSizeForThis / 4; i++)
                    {
                        new CPUx86.Push {
                            DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xStorageSize
                        };
                    }
                }

                new Call(aAssembler).Execute(aMethod, xMethod);

                // Need to put these *after* the call because the Call pops the args from the stack
                // and we have mucked about on the stack, so this makes it right before the next
                // op.

                #endregion Valuetypes
            }
            else
            {
                // If not ValueType, then we need gc

                var xParams = constructor.GetParameters();

                // array length + 8
                bool xHasCalcSize = false;

                #region Special string handling
                // try calculating size:
                if (constructor.DeclaringType == typeof(string))
                {
                    if (xParams.Length == 1 &&
                        xParams[0].ParameterType == typeof(char[]))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);

                        // EAX contains a memory handle now, lets dereference it to a pointer
                        XS.Set(EAX, EAX, sourceIsIndirect: true);
                        XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceDisplacement: 8);
                        XS.Set(XSRegisters.EDX, 2);
                        XS.Multiply(XSRegisters.EDX);
                        XS.Push(XSRegisters.EAX);
                    }
                    else if (xParams.Length == 3 &&
                             (xParams[0].ParameterType == typeof(char[]) || xParams[0].ParameterType == typeof(char *)) &&
                             xParams[1].ParameterType == typeof(int) &&
                             xParams[2].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(XSRegisters.EAX, 1);
                        XS.Push(XSRegisters.EAX);
                    }
                    else if (xParams.Length == 2 &&
                             xParams[0].ParameterType == typeof(char) &&
                             xParams[1].ParameterType == typeof(int))
                    {
                        xHasCalcSize = true;
                        XS.Set(EAX, ESP, sourceIsIndirect: true);
                        XS.ShiftLeft(XSRegisters.EAX, 1);
                        XS.Push(XSRegisters.EAX);
                    }
                    else
                    {
                        throw new NotImplementedException("In NewObj, a string ctor implementation is missing!");
                    }
                }
                #endregion Special string handling

                uint xMemSize   = GetStorageSize(objectType);
                int  xExtraSize = 12; // additional size for set values after alloc
                XS.Push((uint)(xMemSize + xExtraSize));
                if (xHasCalcSize)
                {
                    XS.Pop(XSRegisters.EAX);
                    XS.Add(ESP, EAX, destinationIsIndirect: true);
                }

                // todo: probably we want to check for exceptions after calling Alloc
                XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
                XS.Label(".AfterAlloc");
                XS.Push(ESP, isIndirect: true);
                XS.Push(ESP, isIndirect: true);

                // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes

                //? ?? uint xObjSize;// = 0;
                //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values
                //where item.NeedsGC
                //select item ).Count();

                //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values
                //where item.NeedsGC
                //select item ).Count();
                int xGCFieldCount = objectType.GetFields().Count(x => x.FieldType.IsValueType);

                // todo: use a cleaner approach here. this class shouldnt assemble the string
                string strTypeId = GetTypeIDLabel(constructor.DeclaringType);

                XS.Pop(XSRegisters.EAX);
                XS.Set(EAX, EAX, sourceIsIndirect: true);
                XS.Set(EBX, strTypeId, sourceIsIndirect: true);
                XS.Set(EAX, EBX, destinationIsIndirect: true);
                XS.Set(EAX, (uint)InstanceTypeEnum.NormalObject, destinationDisplacement: 4, size: RegisterSize.Int32);
                XS.Set(EAX, (uint)xGCFieldCount, destinationDisplacement: 8, size: RegisterSize.Int32);
                uint xSize = (uint)(from item in xParams
                                    let xQSize = Align(SizeOfType(item.ParameterType), 4)
                                                 select(int) xQSize).Take(xParams.Length).Sum();

                foreach (var xParam in xParams)
                {
                    uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4);
                    new Comment(aAssembler, String.Format("Arg {0}: {1}", xParam.Name, xParamSize));
                    for (int i = 0; i < xParamSize; i += 4)
                    {
                        new CPUx86.Push {
                            DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize + 4)
                        };
                    }
                }

                XS.Call(LabelName.Get(constructor));
                // should the complete error handling happen by ILOp.EmitExceptionLogic?
                if (aMethod != null)
                {
                    // todo: only happening for real methods now, not for ctor's ?
                    XS.Test(XSRegisters.ECX, 2);
                    string xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString();
                    XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel);

                    //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ )
                    //{
                    //    new CPUx86.Add
                    //    {
                    //        DestinationReg = CPUx86.Registers.ESP,
                    //        SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0
                    //             ? aCtorMethodInfo.Arguments[ i ].Size
                    //             : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 )
                    //    };
                    //}
                    PushAlignedParameterSize(constructor);

                    // an exception occurred, we need to cleanup the stack, and jump to the exit
                    XS.Add(XSRegisters.ESP, 4);

                    //new Comment(aAssembler, "[ Newobj.Execute cleanup start count = " + aAssembler.Stack.Count.ToString() + " ]");
                    //foreach( var xStackInt in Assembler.Stack )
                    //{
                    //    new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = ( uint )xStackInt.Size };
                    //}

                    new Comment(aAssembler, "[ Newobj.Execute cleanup end ]");
                    Jump_Exception(aMethod);
                    XS.Label(xNoErrorLabel);
                }
                XS.Pop(XSRegisters.EAX);

                //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ )
                //{
                //    new CPUx86.Add
                //    {
                //        DestinationReg = CPUx86.Registers.ESP,
                //        SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0
                //             ? aCtorMethodInfo.Arguments[ i ].Size
                //             : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 )
                //    };
                //}
                PushAlignedParameterSize(constructor);

                XS.Push(XSRegisters.EAX);
            }
        }
Beispiel #17
0
        public static void DoExecute(uint xStackContentSize, bool xStackContentIsFloat, string aBaseLabel)
        {
            if (xStackContentSize > 4)
            {
                if (xStackContentIsFloat)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.MulSD(XMM1, XMM0);
                    XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32)
                    string Simple32Multiply = aBaseLabel + "Simple32Multiply";
                    string MoveReturnValue  = aBaseLabel + "MoveReturnValue";

                    // right value
                    // low
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
                    // high
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4

                    // left value
                    // low
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8
                    // high
                    //  SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12

                    // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used
                    //mov RIGHT_HIGH to eax, is useable on Full 64 multiply
                    XS.Set(EAX, ESP, sourceDisplacement: 4);
                    XS.Or(EAX, ESP, sourceDisplacement: 12);
                    XS.Jump(CPUx86.ConditionalTestEnum.Zero, Simple32Multiply);
                    // Full 64 Multiply

                    // copy again, or could change EAX
                    //TODO is there an opcode that does OR without change EAX?
                    XS.Set(EAX, ESP, sourceDisplacement: 4);
                    // eax contains already RIGHT_HIGH
                    // multiply with LEFT_LOW
                    XS.Multiply(ESP, displacement: 8);
                    // save result of LEFT_LOW * RIGHT_HIGH
                    XS.Set(ECX, EAX);

                    //mov RIGHT_LOW to eax
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    // multiply with LEFT_HIGH
                    XS.Multiply(ESP, displacement: 12);
                    // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH
                    XS.Add(ECX, EAX);

                    //mov RIGHT_LOW to eax
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    // multiply with LEFT_LOW
                    XS.Multiply(ESP, displacement: 8);
                    // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result
                    XS.Add(EDX, ECX);

                    XS.Jump(MoveReturnValue);

                    XS.Label(Simple32Multiply);
                    //mov RIGHT_LOW to eax
                    XS.Set(EAX, ESP, sourceIsIndirect: true);
                    // multiply with LEFT_LOW
                    XS.Multiply(ESP, displacement: 8);

                    XS.Label(MoveReturnValue);
                    // move high result to left high
                    XS.Set(ESP, EDX, destinationDisplacement: 12);
                    // move low result to left low
                    XS.Set(ESP, EAX, destinationDisplacement: 8);
                    // pop right 64 value
                    XS.Add(ESP, 8);
                }
            }
            else
            {
                if (xStackContentIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.MulSS(XMM1, XMM0);
                    XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(EAX);
                    XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32);
                    XS.Add(ESP, 4);
                    XS.Push(EAX);
                }
            }
        }
Beispiel #18
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4)));

            uint xStackSize = aElementSize;

            if (xStackSize % 4 != 0)
            {
                xStackSize += 4 - xStackSize % 4;
            }
            // Do index out of range check
            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException";
            var xIndexOutOfRangeExeptionLabel   = xBaseLabel + "_IndexOutOfRangeException";

            XS.Push(ESP, displacement: 4 + 4 + (int)xStackSize); // _, array, 0, index, value * n  => _, array, 0, index, value * n, array
            XS.Push(0);                                          // _, array, 0, index, value * n, array => _, array, 0, index, value * n, array, 0
            Ldlen.Assemble(aAssembler, debugEnabled, false);     // _, array, 0, index, value * n, array, 0 -> _, array, 0, index, value * n, length
            XS.Pop(EAX);                                         //Length of array _, array, 0, index, value * n, length -> _, array, 0, index, value * n
            XS.Compare(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: (int)xStackSize);
            XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel);

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

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

            XS.Label(xNoIndexOutOfRangeExeptionLabel);

            // calculate element offset into array memory (including header)
            XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index
            XS.Set(EDX, aElementSize);
            XS.Multiply(EDX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4);

            XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array
            XS.Add(EDX, EAX);
            XS.Push(EDX);

            XS.Pop(ECX);
            for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1)
            {
                new Comment(aAssembler, "Start 1 dword");
                XS.Pop(EBX);
                XS.Set(ECX, EBX, destinationIsIndirect: true);
                XS.Add(ECX, 4);
            }
            switch (aElementSize % 4)
            {
            case 1:
            {
                new Comment(aAssembler, "Start 1 byte");
                XS.Pop(EBX);
                XS.Set(ECX, BL, destinationIsIndirect: true);
                break;
            }

            case 2:
            {
                new Comment(aAssembler, "Start 1 word");
                XS.Pop(EBX);
                XS.Set(ECX, BX, destinationIsIndirect: true);
                break;
            }

            case 0:
            {
                break;
            }

            default:
                throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!");
            }
            XS.Add(ESP, 12);
        }