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
 protected static void DoNullReferenceCheck(Assembler.Assembler assembler, bool debugEnabled, int stackOffsetToCheck)
 {
     if (stackOffsetToCheck != SignedAlign(stackOffsetToCheck, 4))
     {
         throw new Exception("Stack offset not aligned!");
     }
     if (debugEnabled)
     {
         if (!CompilerEngine.UseGen3Kernel)
         {
             XS.Compare(XSRegisters.ESP, 0, destinationDisplacement: (int)stackOffsetToCheck);
             XS.Jump(CPU.ConditionalTestEnum.NotEqual, ".AfterNullCheck");
             XS.ClearInterruptFlag();
             // don't remove the call. It seems pointless, but we need it to retrieve the EIP value
             XS.Call(".NullCheck_GetCurrAddress");
             XS.Label(".NullCheck_GetCurrAddress");
             XS.Pop(XSRegisters.EAX);
             new CPU.Mov
             {
                 DestinationRef        = ElementReference.New("DebugStub_CallerEIP"),
                 DestinationIsIndirect = true,
                 SourceReg             = CPU.RegistersEnum.EAX
             };
             XS.Call("DebugStub_SendNullReferenceOccurred");
         }
         XS.Halt();
         XS.Label(".AfterNullCheck");
     }
 }
Beispiel #3
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            OpType xType = (OpType)aOpCode;

            if (IsReferenceType(xType.Value))
            {
                return;
            }

            uint   xSize   = Align(SizeOfType(xType.Value), 4);
            string xTypeID = GetTypeIDLabel(xType.Value);

            XS.Push(ObjectUtils.FieldDataOffset + xSize);
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            XS.Pop(ESI);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);
            XS.Set(ESI, EBX, destinationIsIndirect: true);
            XS.Set(ESI, (uint)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationDisplacement: 4, size: RegisterSize.Int32);
            new Comment(Assembler, "xSize is " + xSize);
            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(EDX);
                XS.Set(ESI, EDX, destinationDisplacement: (ObjectUtils.FieldDataOffset + (i * 4)), size: RegisterSize.Int32);
            }
            XS.Push(ESI);
            XS.Push(0);
        }
Beispiel #4
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = (OpType)aOpCode;
            var xTypeID = GetTypeIDLabel(xType.Value);

            var xCurrentMethodLabel       = GetLabel(aMethod, aOpCode);
            var xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call";
            var xInvalidCastLabel         = xCurrentMethodLabel + "_InvalidCast";
            var xNextPositionLabel        = GetLabel(aMethod, aOpCode.NextPosition);

            XS.Set(EAX, ESP, sourceDisplacement: 4);

            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.Zero, xNextPositionLabel);
            XS.Push(EAX, isIndirect: true);
            XS.Push(xTypeID, isIndirect: true);
            XS.Push(Convert.ToUInt32(xType.Value.IsInterface));

            MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef;

            Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled);

            XS.Label(xAfterIsInstanceCallLabel);

            XS.Pop(EAX);

            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.Equal, xInvalidCastLabel);

            XS.Jump(xNextPositionLabel);

            XS.Label(xInvalidCastLabel);
            XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef));
        }
Beispiel #5
0
 public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 12, sourceIsIndirect: true);
     XS.Push(XSRegisters.EAX);
     XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 8, sourceIsIndirect: true);
     XS.Push(XSRegisters.EAX);
     XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 16, sourceIsIndirect: true);
     XS.Call(XSRegisters.EAX);
 }
Beispiel #6
0
 public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
 {
     // TODO: Implement exception
     DoNullReferenceCheck(Assembler, DebugEnabled, 4);
     XS.Add(ESP, 4);
     XS.Pop(EAX);
     XS.Set(LabelName.GetStaticFieldName(ExceptionHelperRefs.CurrentExceptionRef), EAX, destinationIsIndirect: true);
     XS.Call("SystemExceptionOccurred");
     XS.Set(ECX, 3);
     EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null);
 }
Beispiel #7
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
#warning TODO: Implement exception
            DoNullReferenceCheck(Assembler, DebugEnabled, 0);
            XS.Pop(XSRegisters.EAX);
            new CPUx86.Mov {
                DestinationRef = Cosmos.Assembler.ElementReference.New(DataMember.GetStaticFieldName(ExceptionHelperRefs.CurrentExceptionRef)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.EAX
            };
            XS.Call("SystemExceptionOccurred");
            XS.Set(XSRegisters.ECX, 3);
            Call.EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null);
        }
Beispiel #8
0
        public static void DoExecute(Cosmos.Assembler.Assembler assembler, _MethodInfo aMethod, string field, Type declaringType, ILOpCode aCurrentOpCode)
        {
            // call cctor:
            var xCctor = (declaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (xCctor != null)
            {
                XS.Call(LabelName.Get(xCctor));
                if (aCurrentOpCode != null)
                {
                    ILOp.EmitExceptionLogic(assembler, aMethod, aCurrentOpCode, true, null, ".AfterCCTorExceptionCheck");
                    XS.Label(".AfterCCTorExceptionCheck");
                }
            }
            string xDataName = field;

            XS.Push(xDataName);
        }
Beispiel #9
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            Cosmos.IL2CPU.ILOpCodes.OpType xType = (Cosmos.IL2CPU.ILOpCodes.OpType)aOpCode;

            uint xSize = SizeOfType(xType.Value);

            //TODO cache it to reduce calculation
            string     xTypeID   = GetTypeIDLabel(typeof(Array));
            MethodBase xCtor     = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0];
            string     xCtorName = LabelName.Get(xCtor);

            new Comment(Assembler, "Element Size = " + xSize);
            // element count is on the stack
            XS.Pop(XSRegisters.ESI);
            XS.Push(XSRegisters.ESI);
            //Assembler.StackSizes.Push(xElementCountSize);
            XS.Push(xSize);
            new Mul(Assembler).Execute(aMethod, aOpCode);
            // the total items size is now on the stack
            XS.Push((ObjectImpl.FieldDataOffset + 4));
            new Add(Assembler).Execute(aMethod, aOpCode);
            // the total array size is now on the stack.
            XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef));
            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(XSRegisters.EAX);
            XS.Set(EAX, EAX, sourceIsIndirect: true);
            XS.Set(EBX, xTypeID, sourceIsIndirect: true);
            XS.Set(EAX, EBX, destinationIsIndirect: true);
            XS.Add(XSRegisters.EAX, 4);
            new CPUx86.Mov {
                DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, SourceValue = (uint)InstanceTypeEnum.Array, Size = 32
            };
            XS.Add(XSRegisters.EAX, 4);
            XS.Set(EAX, ESI, destinationIsIndirect: true, size: RegisterSize.Int32);
            XS.Add(XSRegisters.EAX, 4);
            new CPUx86.Mov {
                DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, SourceValue = (uint)xSize, Size = 32
            };
            XS.Call(xCtorName);
        }
Beispiel #10
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 #11
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackType = aOpCode.StackPopTypes[0];

            var xNoThrowLabel = GetLabel(aMethod, aOpCode) + ".NoThrow";

            switch (SizeOfType(xStackType))
            {
            case 4:
                XS.Pop(EAX);
                XS.And(EAX, 0x7FFFFFFF);

                XS.Compare(EAX, 0x7F800000);
                XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel);

                XS.SSE2.ConvertSS2SD(XMM0, EAX);
                XS.Sub(ESP, 8);
                XS.SSE2.MoveSD(ESP, XMM0, true);

                break;

            case 8:
                XS.Set(EAX, ESP, sourceDisplacement: 4);

                XS.And(EAX, 0x7FFFFFFF);
                XS.Compare(EAX, 0x7F800000);
                XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel);

                break;

            default:
                throw new NotImplementedException();
            }

            XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowNotFiniteNumberExceptionRef));

            XS.Label(xNoThrowLabel);
        }
Beispiel #12
0
 protected static void DoNullReferenceCheck(Assembler assembler, bool debugEnabled, int stackOffsetToCheck)
 {
     if (stackOffsetToCheck != SignedAlign(stackOffsetToCheck, 4))
     {
         throw new Exception("Stack offset not aligned!");
     }
     if (debugEnabled)
     {
         //if (!CompilerEngine.UseGen3Kernel) {
         XS.Compare(XSRegisters.ESP, 0, destinationDisplacement: (int)stackOffsetToCheck);
         XS.Jump(CPU.ConditionalTestEnum.NotEqual, ".AfterNullCheck");
         XS.ClearInterruptFlag();
         // don't remove the call. It seems pointless, but we need it to retrieve the EIP value
         XS.Call(".NullCheck_GetCurrAddress");
         XS.Label(".NullCheck_GetCurrAddress");
         XS.Pop(XSRegisters.EAX);
         XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], XSRegisters.EAX, destinationIsIndirect: true);
         XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendNullRefEvent]);
         //}
         XS.Halt();
         XS.Label(".AfterNullCheck");
     }
 }
Beispiel #13
0
                public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
                {
                    int start = 0;

                    for (int i = start; i < 256; i++)
                    {
                        if (i == 1 || i == 3)
                        {
                            //continue; // was used for debugging
                        }

                        XS.Set(XSRegisters.EAX, "_isr" + i.ToString("X2"));
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AL, destinationDisplacement: (i * 8) + 0);
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AH, destinationDisplacement: (i * 8) + 1);
                        XS.Set("_NATIVE_IDT_Contents", 0x08, destinationDisplacement: (i * 8) + 2, size: XSRegisters.RegisterSize.Byte8);
                        XS.Set("_NATIVE_IDT_Contents", 0x00, destinationDisplacement: (i * 8) + 4, size: XSRegisters.RegisterSize.Byte8);
                        XS.Set("_NATIVE_IDT_Contents", 0x8E, destinationDisplacement: (i * 8) + 5, size: XSRegisters.RegisterSize.Byte8);
                        XS.ShiftRight(XSRegisters.EAX, 16);
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AL, destinationDisplacement: (i * 8) + 6);
                        XS.Set("_NATIVE_IDT_Contents", XSRegisters.AH, destinationDisplacement: (i * 8) + 7);
                    }
                    XS.Jump("skip_isrhandlers");
                    var xInterruptsWithParam = new[] { 8, 10, 11, 12, 13, 14 };

                    for (int j = start; j < 256; j++)
                    {
                        XS.Label("_isr" + j.ToString("X2"));
                        XS.ClearInterruptFlag();
                        XS.Call("__INTERRUPT_OCCURRED__");

                        if (global::System.Array.IndexOf(xInterruptsWithParam, j) == -1)
                        {
                            XS.Push(0);
                        }
                        XS.Push((uint)j);
                        XS.Jump("CommonISRBase");
                    }
                    XS.Label("CommonISRBase");
                    XS.PushAllRegisters();
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP);
                    XS.Set("static_field__Kernel_System_Core_ISR_old_esp", XSRegisters.EAX, destinationIsIndirect: true);

                    XS.Sub(XSRegisters.ESP, 4);
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP);

                    XS.And(XSRegisters.ESP, 0xfffffff0);
                    XS.Sub(XSRegisters.ESP, 512);
                    XS.SSE.FXSave(XSRegisters.ESP, isIndirect: true);
                    XS.Set(XSRegisters.EAX, XSRegisters.ESP, destinationIsIndirect: true);

                    XS.Push(XSRegisters.EAX);
                    XS.Push(XSRegisters.EAX);

                    XS.Set("static_field__Kernel_System_Core_ISR_Registers", XSRegisters.EAX, destinationIsIndirect: true);
                    MethodBase xHandler = GetMethodDef(typeof(ISR).Assembly, typeof(ISR).FullName, "CommonISRHandler", true);

                    XS.Call(LabelName.Get(xHandler));

                    XS.Pop(XSRegisters.EAX);
                    XS.SSE.FXRestore(XSRegisters.ESP, isIndirect: true);

                    XS.Set(XSRegisters.ESP, XSRegisters.EAX);
                    XS.Add(XSRegisters.ESP, 4);

                    XS.Set(XSRegisters.EAX, "static_field__Kernel_System_Core_ISR_old_esp", sourceIsIndirect: true);
                    XS.Set(XSRegisters.ESP, XSRegisters.EAX);
                    XS.PopAllRegisters();

                    XS.Add(XSRegisters.ESP, 8);
                    XS.InterruptReturn();
                    XS.Label("skip_isrhandlers");
                }
Beispiel #14
0
            public override void AssembleNew(object aAssembler, object aMethodInfo)
            {
                XS.Mov(XSRegisters.BL, 0xa8);

                XS.Call("send_mouse_cmd");

                XS.Call("mouse_read");

                XS.Noop();

                XS.Mov(XSRegisters.BL, 0x20);

                XS.Call("send_mouse_cmd");

                XS.Call("mouse_read");

                XS.Or(XSRegisters.AL, 3);

                XS.Mov(XSRegisters.BL, 0x60);

                XS.Push(XSRegisters.EAX);

                XS.Call("send_mouse_cmd");

                XS.Pop(XSRegisters.EAX);

                XS.Call("mouse_write");

                XS.Noop();

                XS.Mov(XSRegisters.BL, 0xd4);

                XS.Call("send_mouse_cmd");

                XS.Mov(XSRegisters.AL, 0xf4);

                XS.Call("mouse_write");

                XS.Call("mouse_read");

                #region mouse_read
                XS.Label("mouse_read");
                {
                    XS.Push(XSRegisters.ECX);

                    XS.Push(XSRegisters.EDX);

                    XS.Mov(XSRegisters.ECX, 0xffff);

                    XS.Label("mouse_read_loop");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 1);

                        XS.Jump(ConditionalTestEnum.NotZero, "mouse_read_ready");

                        new Loop
                        {
                            DestinationLabel = "mouse_read_loop"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_read_exit");
                    }

                    XS.Label("mouse_read_ready");
                    {
                        XS.Push(XSRegisters.ECX);

                        XS.Mov(XSRegisters.ECX, 32);
                    }

                    XS.Label("mouse_read_delay");
                    {
                        new Loop
                        {
                            DestinationLabel = "mouse_read_delay"
                        };

                        XS.Pop(XSRegisters.ECX);

                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x60,
                            Size           = 8
                        };

                        XS.Xor(XSRegisters.AH, XSRegisters.RegistersEnum.AH);
                    }

                    XS.Label("mouse_read_exit");
                    {
                        XS.Pop(XSRegisters.EDX);

                        XS.Pop(XSRegisters.ECX);

                        XS.Return();
                    }
                }
                #endregion

                #region mouse_write
                XS.Label("mouse_write");
                {
                    XS.Push(XSRegisters.ECX);

                    XS.Push(XSRegisters.EDX);

                    XS.Mov(XSRegisters.BH, XSRegisters.RegistersEnum.AL);

                    XS.Mov(XSRegisters.ECX, 0xffff);

                    XS.Label("mouse_write_loop1");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 32);

                        XS.Jump(ConditionalTestEnum.Zero, "mouse_write_ok1");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop1"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_write_exit");
                    }

                    XS.Label("mouse_write_ok1");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x60,
                            Size           = 8
                        };

                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_write_loop");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 2);

                        XS.Jump(ConditionalTestEnum.Zero, "mouse_write_ok");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_write_exit");
                    }

                    XS.Label("mouse_write_ok");
                    {
                        XS.Mov(XSRegisters.AL, XSRegisters.RegistersEnum.BH);

                        new Out2Port
                        {
                            DestinationValue = 0x60,
                            SourceReg        = RegistersEnum.AL,
                            Size             = 8
                        };

                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_write_loop3");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 2);

                        XS.Jump(ConditionalTestEnum.Zero, "mouse_write_ok3");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop3"
                        };

                        XS.Mov(XSRegisters.AH, 1);

                        XS.Jump("mouse_write_exit");
                    }

                    XS.Label("mouse_write_ok3");
                    {
                        XS.Mov(XSRegisters.AH, 0x08);
                    }

                    XS.Label("mouse_write_loop4");
                    {
                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_write_loop5");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };

                        XS.Test(XSRegisters.AL, 1);

                        XS.Jump(ConditionalTestEnum.NotZero, "mouse_write_ok4");

                        new Loop
                        {
                            DestinationLabel = "mouse_write_loop5"
                        };

                        XS.Dec(XSRegisters.AH);

                        XS.Jump(ConditionalTestEnum.NotZero, "mouse_write_loop4");
                    }

                    XS.Label("mouse_write_ok4");
                    {
                        XS.Xor(XSRegisters.AH, XSRegisters.RegistersEnum.AH);
                    }

                    XS.Label("mouse_write_exit");
                    {
                        XS.Pop(XSRegisters.EDX);

                        XS.Pop(XSRegisters.ECX);

                        XS.Return();
                    }
                }
                #endregion

                #region send_mouse_cmd
                XS.Label("send_mouse_cmd");
                {
                    XS.Mov(XSRegisters.ECX, 0xffff);

                    XS.Label("mouse_cmd_wait");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };
                        XS.Test(XSRegisters.AL, 2);
                        XS.Jump(ConditionalTestEnum.Zero, "mouse_cmd_send");
                        new Loop
                        {
                            DestinationLabel = "mouse_cmd_wait"
                        };
                        XS.Jump("mouse_cmd_error");
                    }

                    XS.Label("mouse_cmd_send");
                    {
                        XS.Mov(XSRegisters.AL, XSRegisters.RegistersEnum.BL);
                        new Out2Port
                        {
#if DebugMouse
                            SourceValue    = 0x64,
                            DestinationReg = RegistersEnum.AL,
#else
                            DestinationValue = 0x64,
                            SourceReg        = RegistersEnum.AL,
#endif
                            Size = 8
                        };
                        XS.Mov(XSRegisters.ECX, 0xffff);
                    }

                    XS.Label("mouse_cmd_accept");
                    {
                        new In2Port
                        {
                            DestinationReg = RegistersEnum.AL,
                            SourceValue    = 0x64,
                            Size           = 8
                        };
                        XS.Test(XSRegisters.AL, 0x02);
                        XS.Jump(ConditionalTestEnum.Zero, "mouse_cmd_ok");
                        new Loop
                        {
                            DestinationLabel = "mouse_cmd_accept"
                        };
                    }

                    XS.Label("mouse_cmd_error");
                    {
                        XS.Mov(XSRegisters.AH, 0x01);
                        XS.Jump("mouse_cmd_exit");
                    }

                    XS.Label("mouse_cmd_ok");
                    {
                        XS.Xor(XSRegisters.AH, XSRegisters.RegistersEnum.AH);
                    }

                    XS.Label("mouse_cmd_exit");
                    {
                        XS.Return();
                    }
                }
                #endregion
            }
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            var xAssembler        = aAssembler;
            var xMethodInfo       = (_MethodInfo)aMethodInfo;
            var xMethodBaseAsInfo = xMethodInfo.MethodBase as global::System.Reflection.MethodInfo;

            if (xMethodBaseAsInfo.ReturnType != typeof(void))
            {
                throw new Exception("Events with return type not yet supported!");
            }

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EDX contains the index at which the EAX is
             * EBX contains the number of items in the array
             * ECX contains the argument size
             */

            XS.ClearInterruptFlag();

            XS.Comment("Get Invoke list count");
            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Call(LabelName.Get(xGetInvocationListMethod));
            XS.Add(XSRegisters.ESP, 4);
            XS.Pop(XSRegisters.EAX);
            XS.Add(XSRegisters.EAX, 8);
            XS.Set(XSRegisters.EBX, XSRegisters.EAX, sourceIsIndirect: true);

            XS.Comment("Get invoke method");
            XS.Add(XSRegisters.EAX, 8);
            XS.Set(XSRegisters.EDI, XSRegisters.EAX, sourceIsIndirect: true, sourceDisplacement: 4);

            XS.Comment("Get ArgSize");
            int xArgSizeOffset = Ldfld.GetFieldOffset(typeof(global::System.Delegate), "$$ArgSize$$");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Add(XSRegisters.ESP, 4);
            XS.Pop(XSRegisters.ECX);
            XS.Add(XSRegisters.ECX, (uint)xArgSizeOffset);
            XS.Set(XSRegisters.ECX, XSRegisters.ECX, sourceIsIndirect: true);

            XS.Comment("Set current invoke list index");
            XS.Set(XSRegisters.EDX, 0);

            XS.Label(".BEGIN_OF_LOOP");
            {
                XS.Compare(XSRegisters.EDX, XSRegisters.EBX);
                XS.Jump(x86.ConditionalTestEnum.GreaterThanOrEqualTo, ".END_OF_INVOKE");

                XS.PushAllRegisters();

                XS.Comment("Check if delegate has $this");
                XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
                XS.Add(XSRegisters.EDI, 4);
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target"));
                XS.Compare(XSRegisters.EDI, 0);
                XS.Jump(x86.ConditionalTestEnum.Zero, ".NO_THIS");
                XS.Label(".HAS_THIS");
                XS.Push(XSRegisters.EDI);
                XS.Push(0);
                XS.Label(".NO_THIS");
                XS.Set(XSRegisters.EDI, XSRegisters.EAX, sourceIsIndirect: true, sourceDisplacement: 4);
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr"));

                XS.Comment("Check if delegate has args");
                XS.Compare(XSRegisters.ECX, 0);
                XS.Jump(x86.ConditionalTestEnum.Zero, ".NO_ARGS");
                XS.Label(".HAS_ARGS");
                XS.Sub(XSRegisters.ESP, XSRegisters.ECX);
                XS.Push(XSRegisters.EDI);
                XS.Set(XSRegisters.EDI, XSRegisters.ESP);
                XS.Add(XSRegisters.EDI, 4);
                XS.Set(XSRegisters.ESI, XSRegisters.EBP);
                XS.Add(XSRegisters.ESI, 8);
                new x86.Movs {
                    Size = 8, Prefixes = x86.InstructionPrefixes.Repeat
                };
                XS.Pop(XSRegisters.EDI);
                XS.Label(".NO_ARGS");
                XS.Call(XSRegisters.EDI);

                XS.PopAllRegisters();
                XS.Increment(XSRegisters.EDX);
                XS.Jump(".BEGIN_OF_LOOP");
            }

            XS.Label(".END_OF_INVOKE");
            XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ReturnsValue$$"));
            XS.Compare(XSRegisters.EDX, 0);
            XS.Jump(x86.ConditionalTestEnum.Equal, ".NO_RETURN");

            XS.Label(".HAS_RETURN");
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationDisplacement: 8);
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationDisplacement: 4);
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationIsIndirect: true);
            XS.Push(XSRegisters.EDX);
            XS.Set(XSRegisters.ESP, XSRegisters.EDI, destinationDisplacement: 12);

            XS.Label(".NO_RETURN");
            XS.EnableInterrupts();
        }
Beispiel #16
0
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            var xMethodInfo = (Il2cpuMethodInfo)aMethodInfo;

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EBX contains the number of items in the array
             * ECX contains the argument size
             * EDX contains the current index in the array
             * ESI contains the size of the return value
             * EDI contains the function pointer
             */

            XS.ClearInterruptFlag();

            XS.Comment("Get Invoke list count");
            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Call(LabelName.Get(xGetInvocationListMethod));
            XS.Add(ESP, 4);
            XS.Pop(EAX);
            XS.Add(EAX, 8);
            XS.Set(EBX, EAX, sourceIsIndirect: true);

            XS.Comment("Get invoke method");
            XS.Add(EAX, 8);
            XS.Set(EDI, EAX, sourceIsIndirect: true, sourceDisplacement: 4); // this line can propably can be removed

            XS.Comment("Get ArgSize");
            int xArgSizeOffset = Ldfld.GetFieldOffset(typeof(Delegate), "$$ArgSize$$");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Add(ESP, 4);
            XS.Pop(ECX);
            XS.Add(ECX, (uint)xArgSizeOffset);
            XS.Set(ECX, ECX, sourceIsIndirect: true);

            XS.Comment("Set current invoke list index");
            XS.Set(EDX, 0);

            XS.Comment("Make space for return value");
            int returnSizeOffset = Ldfld.GetFieldOffset(typeof(Delegate), "$$ReturnSize$$");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Add(ESP, 4);
            XS.Pop(ESI);
            XS.Add(ESI, (uint)returnSizeOffset);
            XS.Set(ESI, ESI, sourceIsIndirect: true);
            XS.Sub(ESP, ESI);

            XS.Label(".BEGIN_OF_LOOP");
            {
                XS.Compare(EDX, EBX);
                XS.Jump(x86.ConditionalTestEnum.GreaterThanOrEqualTo, ".END_OF_INVOKE");
                XS.PushAllRegisters();

                XS.Comment("Check if delegate has $this");
                XS.Set(EDI, EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
                XS.Add(EDI, 4);
                XS.Set(EDI, EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target"));
                XS.Set(EDX, ECX); // edx contains the size of the arguments including $this
                XS.Compare(EDI, 0);
                XS.Jump(x86.ConditionalTestEnum.Zero, ".NO_THIS");
                XS.Label(".HAS_THIS");
                XS.Push(EDI);
                XS.Set(EDI, EDI, sourceIsIndirect: true); // get type of target object
                XS.Add(EDX, 4);                           // we have at least one int of $this

                //TODO: In future we might be able to replace the following call with a check
                //if the object is boxed and in that case assume its a struct

                // safe info from registers which get trashed
                XS.Push(EAX);
                XS.Push(EBX);
                XS.Push(ECX);
                XS.Push(EDX);

                XS.Push(EDI);
                XS.Call(LabelName.Get(VTablesImplRefs.IsStructRef));
                XS.Pop(EDI);

                // restore values
                XS.Pop(EDX);
                XS.Pop(ECX);
                XS.Pop(EBX);
                XS.Pop(EAX);

                // now check if target turned out to be struct
                XS.Compare(EDI, 1);
                XS.Jump(x86.ConditionalTestEnum.Equal, ".Struct"); //structs are just the pointer so we are already done
                XS.Push(0);
                XS.Add(EDX, 4);
                XS.Jump(".NO_THIS");
                XS.Label(".Struct");
                XS.Add(ESP, ObjectUtils.FieldDataOffset, destinationIsIndirect: true);
                XS.Label(".NO_THIS");
                XS.Set(EDI, EAX, sourceIsIndirect: true, sourceDisplacement: 4);
                XS.Set(EDI, EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr"));

                XS.Set(EBX, 0); // initialise required extra space to 0
                XS.Compare(ESI, EDX);
                XS.Jump(x86.ConditionalTestEnum.LessThanOrEqualTo, ".NO_RETURN_VALUE_SPACE");
                XS.Set(EBX, ESI);
                XS.Sub(EBX, ECX);
                XS.Label(".NO_RETURN_VALUE_SPACE");

                XS.Comment("Check if delegate has args");
                XS.Compare(ECX, 0);
                XS.Jump(x86.ConditionalTestEnum.Zero, ".NO_ARGS");
                XS.Label(".HAS_ARGS");
                XS.Sub(ESP, ECX);
                XS.Push(EDI);
                XS.Set(EDI, ESP);
                XS.Add(EDI, 4);
                XS.Set(ESI, EBP);
                XS.Compare(EBX, 0);
                XS.Jump(x86.ConditionalTestEnum.Equal, ".NO_RETURN_EXTRA");
                XS.Add(ESI, EBX); // to skip the extra space reserved for the return value
                XS.Jump(".AFTER_ADJUST_ESI");
                XS.Label(".NO_RETURN_EXTRA");
                XS.Add(ESI, 8);
                XS.Label(".AFTER_ADJUST_ESI");
                new x86.Movs {
                    Size = 8, Prefixes = x86.InstructionPrefixes.Repeat
                };
                XS.Pop(EDI);
                XS.Label(".NO_ARGS");

                XS.Sub(ESP, EBX); // make extra space for the return value
                XS.Call(EDI);

                XS.Comment("If there is a return value copy it to holding place now");
                Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
                XS.Add(ESP, 4);
                XS.Pop(EAX);
                XS.Add(EAX, (uint)returnSizeOffset);
                XS.Set(EAX, EAX, sourceIsIndirect: true); // got size of return value

                XS.Set(EDI, EBP);
                XS.Sub(EDI, EAX);
                XS.Label(".RETURN_VALUE_LOOP_START");
                XS.Compare(EAX, 0);
                XS.Jump(x86.ConditionalTestEnum.LessThanOrEqualTo, ".RETURN_VALUE_LOOP_END");
                XS.Pop(EBX);
                XS.Set(EDI, EBX, destinationIsIndirect: true);
                XS.Add(EDI, 4);
                XS.Sub(EAX, 4);
                XS.Jump(".RETURN_VALUE_LOOP_START");
                XS.Label(".RETURN_VALUE_LOOP_END");

                XS.PopAllRegisters();
                XS.Increment(EDX);
                XS.Jump(".BEGIN_OF_LOOP");
            }

            XS.Label(".END_OF_INVOKE");

            XS.EnableInterrupts();
        }
Beispiel #17
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 #18
0
        public override void AssembleNew(Cosmos.Assembler.Assembler aAssembler, object aMethodInfo)
        {
            var xAssembler        = (Cosmos.Assembler.Assembler)aAssembler;
            var xMethodInfo       = (Cosmos.IL2CPU.MethodInfo)aMethodInfo;
            var xMethodBaseAsInfo = xMethodInfo.MethodBase as global::System.Reflection.MethodInfo;

            if (xMethodBaseAsInfo.ReturnType != typeof(void))
            {
                throw new Exception("Events with return type not yet supported!");
            }
            XS.Comment("XXXXXXX");
            XS.Exchange(XSRegisters.BX, XSRegisters.BX);

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EDX contains the index at which the EAX is
             * EBX contains the number of items in the array
             * ECX contains the argument size
             */
            XS.ClearInterruptFlag();
            XS.Label(".DEBUG");
            //XS.Label("____DEBUG_FOR_MULTICAST___");
            XS.Comment("move address of delegate to eax");
            XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));

            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            XS.Comment("push address of delgate to stack");
            XS.Push(XSRegisters.EAX);//addrof this
            XS.Call(LabelName.Get(xGetInvocationListMethod));
            XS.Comment("get address from return value -> eax");
            XS.Pop(XSRegisters.EAX);
            ;//list
            XS.Comment("eax+=8 is where the offset where an array's count is");
            XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true);
            XS.Add(XSRegisters.EAX, 8);                                       //addrof list.Length
            XS.Comment("store count in ebx");
            XS.Set(XSRegisters.EBX, XSRegisters.EAX, sourceIsIndirect: true); //list.count
            XS.Comment("eax+=8 is where the offset where an array's items start");
            XS.Add(XSRegisters.EAX, 8);                                       // Put pointer at the first item in the list.
            XS.Set(XSRegisters.EDI, 0);
            XS.Comment("ecx = ptr to delegate object");
            XS.Set(XSRegisters.ECX, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));//addrof the delegate
            XS.Comment("ecx points to the size of the delegated methods arguments");
            XS.Set(XSRegisters.ECX, XSRegisters.ECX, sourceIsIndirect: true);
            XS.Set(XSRegisters.ECX, XSRegisters.ECX, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ArgSize$$")); //the size of the arguments to the method? + 12??? -- 12 is the size of the current call stack.. i think
            XS.Xor(XSRegisters.EDX, XSRegisters.EDX);
            ;                                                                                                                                        //make sure edx is 0
            XS.Label(".BEGIN_OF_LOOP");
            {
                XS.Compare(XSRegisters.EDX, XSRegisters.EBX);                                //are we at the end of this list
                XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, ".END_OF_INVOKE_"); //then we better stop
                XS.PushAllRegisters();
                XS.Comment("esi points to where we will copy the methods argumetns from");
                XS.Set(XSRegisters.ESI, XSRegisters.ESP);
                XS.Comment("edi = ptr to delegate object");
                XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceIsIndirect: true); // dereference handle
                XS.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods ");
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target"));
                XS.Compare(XSRegisters.EDI, 0);
                XS.Jump(CPUx86.ConditionalTestEnum.Zero, ".NO_THIS");
                XS.Push(XSRegisters.EDI);

                XS.Label(".NO_THIS");

                XS.Comment("make space for us to copy the arguments too");
                XS.Sub(XSRegisters.ESP, XSRegisters.ECX);
                XS.Comment("move the current delegate to edi");
                XS.Set(XSRegisters.EDI, XSRegisters.EAX, sourceIsIndirect: true);
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceIsIndirect: true);                                                                                                     // dereference
                XS.Comment("move the methodptr from that delegate to edi ");
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr")); //
                XS.Comment("save methodptr on the stack");
                XS.Push(XSRegisters.EDI);
                XS.Comment("move location to copy args to");
                XS.Set(XSRegisters.EDI, XSRegisters.ESP);
                XS.Add(XSRegisters.EDI, 4);
                //new CPU.Comment("get above the saved methodptr");
                //XS.Sub(XSRegisters.ESP, 4);
                //we allocated the argsize on the stack once, and it we need to get above the original args
                XS.Comment("we allocated argsize on the stack once");
                XS.Comment("add 32 for the Pushad + 16 for the current stack + 4 for the return value");
                //uint xToAdd = 32; // skip pushad data
                //xToAdd += 4; // method pointer
                XS.Set(XSRegisters.ESI, XSRegisters.EBP);
                XS.Add(XSRegisters.ESI, 8); // ebp+8 is first argument
                new CPUx86.Movs {
                    Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat
                };
                XS.Pop(XSRegisters.EDI);
                XS.Label(".BeforeCall");
                XS.Call(XSRegisters.EDI);
                XS.Comment("store return -- return stored into edi after popad");
                XS.Comment("edi = ptr to delegate object");
                XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
                XS.Comment("edi = ptr to delegate object should be a pointer to the delgates context ie (this) for the methods ");
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceIsIndirect: true);                                                                                                  // dereference handle
                XS.Set(XSRegisters.EDI, XSRegisters.EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target")); //i really dont get the +12, MtW: that's for the object header
                XS.Label(".noTHIStoPop");
                XS.PopAllRegisters();
                XS.Increment(XSRegisters.EDX);
                XS.Add(XSRegisters.EAX, 4);
                XS.Jump(".BEGIN_OF_LOOP");
            }
            XS.Label(".END_OF_INVOKE_");
            XS.Comment("get the return value");
            XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0)); //addrof the delegate
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceIsIndirect: true);                                            // dereference handle
            XS.Set(XSRegisters.EDX, XSRegisters.EDX, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ReturnsValue$$"));
            XS.Compare(XSRegisters.EDX, 0);
            XS.Jump(CPUx86.ConditionalTestEnum.Equal, ".noReturn");
            //may have to expand the return... idk
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationDisplacement: 8);
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationDisplacement: 4);
            XS.Exchange(XSRegisters.EBP, XSRegisters.EDX, destinationIsIndirect: true);
            XS.Push(XSRegisters.EDX);//ebp
            XS.Set(XSRegisters.ESP, XSRegisters.EDI, destinationDisplacement: 12);
            XS.Label(".noReturn");
            XS.EnableInterrupts();
        }
Beispiel #19
0
 public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
 {//I asked jp2masa
     XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 8);
     XS.Call(XSRegisters.EAX);
 }
Beispiel #20
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = aMethod.MethodBase.DeclaringType;
            var xOpCode = (OpField)aOpCode;

            SysReflection.FieldInfo xField = xOpCode.Value;

            // call cctor:
            var xCctor = (xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic)).SingleOrDefault();

            if (xCctor != null)
            {
                XS.Call(LabelName.Get(xCctor));
                ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck");
                XS.Label(".AfterCCTorExceptionCheck");
            }

            //Assembler.Stack.Pop();
            //int aExtraOffset;// = 0;
            //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType;
            var xSize = SizeOfType(xField.FieldType);
            //if( xNeedsGC )
            //{
            //    aExtraOffset = 12;
            //}

            string xDataName = DataMember.GetStaticFieldName(xField);

            var xTypeNeedsGC = TypeIsReferenceType(xField.FieldType);

            if (xTypeNeedsGC)
            {
                XS.Push(xDataName, isIndirect: true, displacement: 4);
                XS.Push(0);
                return;
            }


            if (xSize >= 4)
            {
                for (int i = 1; i <= (xSize / 4); i++)
                {
                    //	Pop("eax");
                    //	Move(Assembler, "dword [" + mDataName + " + 0x" + (i * 4).ToString("X") + "]", "eax");
                    new CPUx86.Push {
                        DestinationRef = Cosmos.Assembler.ElementReference.New(xDataName), DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize - (i * 4))
                    };
                }
                switch (xSize % 4)
                {
                case 1:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 2:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 0:
                {
                    break;
                }

                default:
                    //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                    throw new NotImplementedException();
                    //break;
                }
            }
            else
            {
                switch (xSize)
                {
                case 1:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 2:
                {
                    XS.Set(XSRegisters.EAX, 0);
                    XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true);
                    XS.Push(XSRegisters.EAX);
                    break;
                }

                case 0:
                {
                    break;
                }

                default:
                    //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
                    throw new NotImplementedException();
                    //break;
                }
            }
        }
        public static void DoExecute(Cosmos.Assembler.Assembler Assembler, _MethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aOp, string currentLabel, string nextLabel, bool debugEnabled)
        {
            var    xMethodInfo    = aTargetMethod as MethodInfo;
            string xNormalAddress = LabelName.Get(aTargetMethod);
            var    xParameters    = aTargetMethod.GetParameters();

            // todo: implement exception support
            uint xExtraStackSize = GetStackSizeToReservate(aTargetMethod);

            if (!aTargetMethod.IsStatic)
            {
                uint xThisOffset = 0;
                foreach (var xItem in xParameters)
                {
                    xThisOffset += Align(SizeOfType(xItem.ParameterType), 4);
                }
                var stackOffsetToCheck = xThisOffset;
                if (TypeIsReferenceType(aTargetMethod.DeclaringType))
                {
                    DoNullReferenceCheck(Assembler, debugEnabled, (int)stackOffsetToCheck + 4);
                }
                else
                {
                    DoNullReferenceCheck(Assembler, debugEnabled, (int)stackOffsetToCheck);
                }
            }

            if (xExtraStackSize > 0)
            {
                XS.Sub(XSRegisters.ESP, (uint)xExtraStackSize);
            }
            XS.Call(xNormalAddress);

            uint xReturnSize = 0;

            if (xMethodInfo != null)
            {
                xReturnSize = SizeOfType(xMethodInfo.ReturnType);
            }
            if (aCurrentMethod != null)
            {
                EmitExceptionLogic(Assembler, aCurrentMethod, aOp, true,
                                   delegate
                {
                    var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value;

                    uint xPopSize = 0;
                    foreach (var type in aOp.StackPopTypes)
                    {
                        xPopSize += Align(SizeOfType(type), 4);
                    }

                    var xResultSize = xReturnSize;
                    if (xResultSize % 4 != 0)
                    {
                        xResultSize += 4 - (xResultSize % 4);
                    }

                    ILOp.EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize);
                }, nextLabel);
            }
        }
Beispiel #22
0
        public static void DoExecute(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, string aFieldId, Type aDeclaringObject, bool aNeedsGC, bool debugEnabled)
        {
            var xType = aMethod.MethodBase.DeclaringType;

            var xFields    = GetFieldsInfo(aDeclaringObject, false);
            var xFieldInfo = (from item in xFields
                              where item.Id == aFieldId
                              select item).Single();
            var xActualOffset = Ldfld.GetFieldOffset(aDeclaringObject, aFieldId);
            var xSize         = xFieldInfo.Size;

            XS.Comment("Field: " + xFieldInfo.Id);
            XS.Comment("Type: " + xFieldInfo.FieldType.ToString());
            XS.Comment("Size: " + xFieldInfo.Size);
            XS.Comment("Offset: " + xActualOffset + " (includes object header)");

            uint xRoundedSize = Align(xSize, 4);

            DoNullReferenceCheck(aAssembler, debugEnabled, xRoundedSize);
            XS.Comment("After Nullref check");
            XS.Set(XSRegisters.ECX, XSRegisters.ESP, sourceDisplacement: (int)xRoundedSize);
            // ECX contains the object pointer now
            if (aNeedsGC)
            {
                // for reference types (or boxed types), ECX actually contains the handle now, so we need to convert it to a memory address
                XS.Comment("Dereference memory handle now");
                XS.Set(XSRegisters.ECX, XSRegisters.ECX, sourceIsIndirect: true);
            }
            if (debugEnabled)
            {
                XS.Push(XSRegisters.ECX);
                XS.Pop(XSRegisters.ECX);
            }
            XS.Add(XSRegisters.ECX, (uint)(xActualOffset));
            //TODO: Can't we use an x86 op to do a byte copy instead and be faster?
            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(XSRegisters.EAX);
                XS.Set(XSRegisters.ECX, XSRegisters.EAX, destinationDisplacement: (int)((i * 4)));
            }

            switch (xSize % 4)
            {
            case 1: {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AL
                };
                break;
            }

            case 2: {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AX
                };
                break;
            }

            case 3: {
                XS.Pop(XSRegisters.EAX);
                // move 2 lower bytes
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AX
                };
                // shift third byte to lowest
                XS.ShiftRight(XSRegisters.EAX, 16);
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4) + 2, SourceReg = CPUx86.RegistersEnum.AL
                };
                break;
            }

            case 0: {
                break;
            }

            default:
                throw new Exception("Remainder size " + (xSize % 4) + " not supported!");
            }

#if !SKIP_GC_CODE
            if (aNeedsGC)
            {
                XS.Push(XSRegisters.ECX);
                XS.Push(XSRegisters.EAX);
                XS.Call(LabelName.Get(GCImplementationRefs.DecRefCountRef));
                XS.Call(LabelName.Get(GCImplementationRefs.DecRefCountRef));
            }
#endif
            XS.Add(XSRegisters.ESP, 4);
        }
Beispiel #23
0
        public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, string nextLabel, bool debugEnabled)
        {
            //if (aTargetMethod.IsVirtual) {
            //  Callvirt.DoExecute(Assembler, aCurrentMethod, aTargetMethod, aTargetMethodUID, aCurrentPosition);
            //  return;
            //}
            var xMethodInfo = aTargetMethod as SysReflection.MethodInfo;

            // mTargetMethodInfo = GetService<IMetaDataInfoService>().GetMethodInfo(mMethod
            //   , mMethod, mMethodDescription, null, mCurrentMethodInfo.DebugMode);
            string xNormalAddress;

            if (aTargetMethod.IsStatic ||
                !aTargetMethod.IsVirtual ||
                aTargetMethod.IsFinal)
            {
                xNormalAddress = LabelName.Get(aTargetMethod);
            }
            else
            {
                xNormalAddress = LabelName.Get(aTargetMethod);

                //throw new Exception("Call: non-concrete method called: '" + aTargetMethod.GetFullName() + "'");
            }
            var xParameters = aTargetMethod.GetParameters();
            int xArgCount   = xParameters.Length;

            // todo: implement exception support
            uint xExtraStackSize = GetStackSizeToReservate(aTargetMethod);

            if (!aTargetMethod.IsStatic && debugEnabled)
            {
                uint xThisOffset = 0;
                foreach (var xItem in xParameters)
                {
                    xThisOffset += Align(SizeOfType(xItem.ParameterType), 4);
                }
                var stackOffsetToCheck = xThisOffset;
                DoNullReferenceCheck(Assembler, debugEnabled, stackOffsetToCheck);
            }

            if (xExtraStackSize > 0)
            {
                XS.Sub(XSRegisters.ESP, (uint)xExtraStackSize);
            }
            XS.Call(xNormalAddress);

            uint xReturnSize = 0;

            if (xMethodInfo != null)
            {
                xReturnSize = SizeOfType(xMethodInfo.ReturnType);
            }
            if (aCurrentMethod != null)
            {
                EmitExceptionLogic(Assembler, aCurrentMethod, aCurrent, true,
                                   delegate()
                {
                    var xStackOffsetBefore = aCurrent.StackOffsetBeforeExecution.Value;

                    uint xPopSize = 0;
                    foreach (var type in aCurrent.StackPopTypes)
                    {
                        xPopSize += Align(SizeOfType(type), 4);
                    }

                    var xResultSize = xReturnSize;
                    if (xResultSize % 4 != 0)
                    {
                        xResultSize += 4 - (xResultSize % 4);
                    }

                    ILOp.EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize);
                }, nextLabel);
            }
            if (xMethodInfo == null ||
                SizeOfType(xMethodInfo.ReturnType) == 0)
            {
                return;
            }
        }
Beispiel #24
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var       xType            = aMethod.MethodBase.DeclaringType;
            var       xOpCode          = (ILOpCodes.OpField)aOpCode;
            FieldInfo xField           = xOpCode.Value;
            var       xIsReferenceType = IsReferenceType(xField.FieldType);

            // call cctor:
            var xCctor = (xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic)).SingleOrDefault();

            if (xCctor != null)
            {
                XS.Call(LabelName.Get(xCctor));
                EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck");
                XS.Label(".AfterCCTorExceptionCheck");
            }

            uint xSize = SizeOfType(xField.FieldType);

            XS.Comment("Type = '" + xField.FieldType.FullName + "'");
            uint xOffset = 0;

            var xFields = xField.DeclaringType.GetFields();

            foreach (FieldInfo xInfo in xFields)
            {
                if (xInfo == xField)
                {
                    break;
                }

                xOffset += SizeOfType(xInfo.FieldType);
            }
            string xDataName = LabelName.GetStaticFieldName(xField);

            if (xIsReferenceType)
            {
                var name = ElementReference.New(xDataName).Name;
                XS.Add(ESP, 4);

                // GC clean up old object
                XS.Compare(name, 0, destinationIsIndirect: true, destinationDisplacement: 4);
                XS.Jump(CPU.ConditionalTestEnum.Equal, ".AfterGC");
                XS.Push(name, isIndirect: true, displacement: 4); // push object as pointer to send to DecRootCount
                XS.Call(LabelName.Get(GCImplementationRefs.DecRootCountRef));
                XS.Label(".AfterGC");

                XS.Pop(EAX);
                XS.Set(name, EAX, destinationIsIndirect: true, destinationDisplacement: 4);

                // Update GC for new object
                XS.Compare(name, 0, destinationIsIndirect: true, destinationDisplacement: 4);
                XS.Jump(CPU.ConditionalTestEnum.Equal, ".SecondAfterGC");
                XS.Push(name, isIndirect: true, displacement: 4); // push object as pointer/uint to send to IncRootCount

                XS.Call(LabelName.Get(GCImplementationRefs.IncRootCountRef));
                XS.Label(".SecondAfterGC");

                return;
            }

            // value types

            if (!xField.FieldType.IsPointer && !xField.FieldType.IsPrimitive && !xField.FieldType.IsEnum)
            {
                // let clean up object deal with it
                XS.Push(xDataName, isIndirect: true, displacement: 4);
                XS.Push(GetTypeIDLabel(xField.FieldType), isIndirect: true);
                XS.Call(LabelName.Get(GCImplementationRefs.DecRootCountsInStructRef));
            }

            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(EAX);
                new CPU.Mov {
                    DestinationRef = ElementReference.New(xDataName, i * 4), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.EAX
                };
            }
            switch (xSize % 4)
            {
            case 1:
            {
                XS.Pop(EAX);
                new CPU.Mov {
                    DestinationRef = ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.AL
                };
                break;
            }

            case 2:
            {
                XS.Pop(EAX);
                new CPU.Mov {
                    DestinationRef = ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.AX
                };
                break;
            }

            case 0:
            {
                break;
            }

            default:
                throw new NotImplementedException();
            }

            if (!xField.FieldType.IsPointer && !xField.FieldType.IsPrimitive && !xField.FieldType.IsEnum)
            {
                // let clean up object deal with it
                XS.Push(xDataName, isIndirect: true, displacement: 4);
                XS.Push(GetTypeIDLabel(xField.FieldType), isIndirect: true);
                XS.Call(LabelName.Get(GCImplementationRefs.IncRootCountsInStructRef));
            }
        }
Beispiel #25
0
        public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
        {
            // IDT is already initialized but just for base hooks, and asm only.
            // ie Int 1, 3 and GPF
            // This routine updates the IDT now that we have C# running to allow C# hooks to handle
            // the other INTs

            // We are updating the IDT, disable interrupts
            XS.ClearInterruptFlag();

            for (int i = 0; i < 256; i++)
            {
                // These are already mapped, don't remap them.
                // Maybe in the future we can look at ones that are present
                // and skip them, but some we may want to overwrite anyways.
                if (i == 1 || i == 3)
                {
                    continue;
                }

                XS.Set(EAX, "__ISR_Handler_" + i.ToString("X2"));
                XS.Set("_NATIVE_IDT_Contents", AL, destinationDisplacement: (i * 8) + 0);
                XS.Set("_NATIVE_IDT_Contents", AH, destinationDisplacement: (i * 8) + 1);
                XS.Set("_NATIVE_IDT_Contents", 0x8, destinationDisplacement: (i * 8) + 2, size: RegisterSize.Byte8);
                XS.Set("_NATIVE_IDT_Contents", 0x8E, destinationDisplacement: (i * 8) + 5, size: RegisterSize.Byte8);
                XS.ShiftRight(EAX, 16);
                XS.Set("_NATIVE_IDT_Contents", AL, destinationDisplacement: (i * 8) + 6);
                XS.Set("_NATIVE_IDT_Contents", AH, destinationDisplacement: (i * 8) + 7);
            }

            XS.Jump("__AFTER__ALL__ISR__HANDLER__STUBS__");
            var xInterruptsWithParam = new[] { 8, 10, 11, 12, 13, 14 };

            for (int j = 0; j < 256; j++)
            {
                XS.Label("__ISR_Handler_" + j.ToString("X2"));
                XS.Call("__INTERRUPT_OCCURRED__");

                if (Array.IndexOf(xInterruptsWithParam, j) == -1)
                {
                    XS.Push(0);
                }
                XS.Push((uint)j);

                if (j != 0x20)
                {
                    XS.PushAllRegisters();

                    XS.Sub(ESP, 4);
                    XS.Set(EAX, ESP); // preserve old stack address for passing to interrupt handler

                    // store floating point data
                    XS.And(ESP, 0xfffffff0);              // fxsave needs to be 16-byte alligned
                    XS.Sub(ESP, 512);                     // fxsave needs 512 bytes
                    XS.SSE.FXSave(ESP, isIndirect: true); // save the registers
                    XS.Set(EAX, ESP, destinationIsIndirect: true);

                    XS.Push(EAX); //
                    XS.Push(EAX); // pass old stack address (pointer to InterruptContext struct) to the interrupt handler

                    XS.JumpToSegment(8, "__ISR_Handler_" + j.ToString("X2") + "_SetCS");
                    XS.Label("__ISR_Handler_" + j.ToString("X2") + "_SetCS");
                    MethodBase xHandler = GetInterruptHandler((byte)j);
                    if (xHandler == null)
                    {
                        xHandler = GetMethodDef(typeof(Cosmos.Core.INTs).Assembly, typeof(Cosmos.Core.INTs).FullName, "HandleInterrupt_Default", true);
                    }
                    XS.Call(LabelName.Get(xHandler));
                    XS.Pop(EAX);
                    XS.SSE.FXRestore(ESP, isIndirect: true);

                    XS.Set(ESP, EAX); // this restores the stack for the FX stuff, except the pointer to the FX data
                    XS.Add(ESP, 4);   // "pop" the pointer

                    XS.PopAllRegisters();
                }
                else
                {
                    new LiteralAssemblerCode("pushad");
                    new LiteralAssemblerCode("mov eax, ds");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov eax, es");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov eax, fs");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov eax, gs");
                    new LiteralAssemblerCode("push eax");
                    new LiteralAssemblerCode("mov ax, 0x10");
                    new LiteralAssemblerCode("mov ds, ax");
                    new LiteralAssemblerCode("mov es, ax");
                    new LiteralAssemblerCode("mov fs, ax");
                    new LiteralAssemblerCode("mov gs, ax");
                    new LiteralAssemblerCode("mov eax, esp");
                    XS.Set("static_field__Cosmos_Core_INTs_mStackContext", EAX, destinationIsIndirect: true);
                    XS.Call(LabelName.Get(GetMethodDef(typeof(Cosmos.Core.Processing.ProcessorScheduler).Assembly, typeof(Cosmos.Core.Processing.ProcessorScheduler).FullName, "SwitchTask", true)));
                    XS.Set(EAX, "static_field__Cosmos_Core_INTs_mStackContext", sourceIsIndirect: true);
                    new LiteralAssemblerCode("mov esp, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov gs, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov fs, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov es, eax");
                    new LiteralAssemblerCode("pop eax");
                    new LiteralAssemblerCode("mov ds, eax");
                    new LiteralAssemblerCode("popad");
                }

                XS.Add(ESP, 8);
                XS.Label("__ISR_Handler_" + j.ToString("X2") + "_END");
                XS.InterruptReturn();
            }
            XS.Label("__INTERRUPT_OCCURRED__");
            XS.Return();
            XS.Label("__AFTER__ALL__ISR__HANDLER__STUBS__");
            XS.Noop();
            XS.Set(EAX, EBP, sourceDisplacement: 8);
            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.Zero, ".__AFTER_ENABLE_INTERRUPTS");

            // reload interrupt list
            XS.Set(EAX, "_NATIVE_IDT_Pointer");
            XS.Set(AsmMarker.Labels[AsmMarker.Type.Processor_IntsEnabled], 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
            XS.LoadIdt(EAX, isIndirect: true);
            // Reenable interrupts
            XS.EnableInterrupts();

            XS.Label(".__AFTER_ENABLE_INTERRUPTS");
        }
Beispiel #26
0
        public static void DoExecute(Assembler Assembler, _MethodInfo aMethod, MethodBase aTargetMethod, uint aTargetMethodUID, ILOpCode aOp, bool debugEnabled)
        {
            string xCurrentMethodLabel = GetLabel(aMethod, aOp.Position);
            Type   xPopType            = aOp.StackPopTypes.Last();

            string xNormalAddress = "";

            if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal)
            {
                xNormalAddress = LabelName.Get(aTargetMethod);
            }

            uint xReturnSize = 0;
            var  xMethodInfo = aTargetMethod as MethodInfo;

            if (xMethodInfo != null)
            {
                xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4);
            }

            uint xExtraStackSize = Call.GetStackSizeToReservate(aTargetMethod, xPopType);
            uint xThisOffset     = 0;
            var  xParameters     = aTargetMethod.GetParameters();

            foreach (var xItem in xParameters)
            {
                xThisOffset += Align(SizeOfType(xItem.ParameterType), 4);
            }

            // This is finding offset to self? It looks like we dont need offsets of other
            // arguments, but only self. If so can calculate without calculating all fields
            // Might have to go to old data structure for the offset...
            // Can we add this method info somehow to the data passed in?
            // mThisOffset = mTargetMethodInfo.Arguments[0].Offset;

            XS.Comment("ThisOffset = " + xThisOffset);

            if (IsReferenceType(xPopType))
            {
                DoNullReferenceCheck(Assembler, debugEnabled, (int)xThisOffset + 4);
            }
            else
            {
                DoNullReferenceCheck(Assembler, debugEnabled, (int)xThisOffset);
            }

            if (!String.IsNullOrEmpty(xNormalAddress))
            {
                if (xExtraStackSize > 0)
                {
                    XS.Sub(ESP, xExtraStackSize);
                }
                XS.Call(xNormalAddress);
            }
            else
            {
                /*
                 * On the stack now:
                 * $esp                 Params
                 * $esp + mThisOffset   This
                 */
                if ((xPopType.IsPointer) || (xPopType.IsByRef))
                {
                    xPopType = xPopType.GetElementType();
                    string xTypeId = GetTypeIDLabel(xPopType);
                    XS.Push(xTypeId, isIndirect: true);
                }
                else
                {
                    XS.Set(EAX, ESP, sourceDisplacement: (int)xThisOffset + 4);
                    XS.Push(EAX, isIndirect: true);
                }
                XS.Push(aTargetMethodUID);
                XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef));
                if (xExtraStackSize > 0)
                {
                    xThisOffset -= xExtraStackSize;
                }

                /*
                 * On the stack now:
                 * $esp                 Params
                 * $esp + mThisOffset   This
                 */
                XS.Pop(ECX);

                XS.Label(xCurrentMethodLabel + ".AfterAddressCheck");

                if (IsReferenceType(xPopType))
                {
                    /*
                     * On the stack now:
                     * $esp + 0              Params
                     * $esp + mThisOffset    This
                     */
                    // we need to see if $this is a boxed object, and if so, we need to box it
                    XS.Set(EAX, ESP, sourceDisplacement: (int)xThisOffset + 4);
                    XS.Compare(EAX, (int)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationIsIndirect: true, destinationDisplacement: 4, size: RegisterSize.Int32);

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * ECX contains the method to call
                     * EAX contains the type pointer (not the handle!!)
                     */
                    XS.Jump(CPU.ConditionalTestEnum.NotEqual, xCurrentMethodLabel + ".NotBoxedThis");

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   This
                     *
                     * ECX contains the method to call
                     * EAX contains the type pointer (not the handle!!)
                     */
                    XS.Add(EAX, (uint)ObjectUtils.FieldDataOffset);
                    XS.Set(ESP, EAX, destinationDisplacement: (int)xThisOffset + 4);

                    /*
                     * On the stack now:
                     * $esp                 Params
                     * $esp + mThisOffset   Pointer to address inside box
                     *
                     * ECX contains the method to call
                     */
                }
                XS.Label(xCurrentMethodLabel + ".NotBoxedThis");
                if (xExtraStackSize > 0)
                {
                    XS.Sub(ESP, xExtraStackSize);
                }
                XS.Call(ECX);
                XS.Label(xCurrentMethodLabel + ".AfterNotBoxedThis");
            }
            EmitExceptionLogic(Assembler, aMethod, aOp, true,
                               delegate
            {
                var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value;

                uint xPopSize = 0;
                foreach (var type in aOp.StackPopTypes)
                {
                    xPopSize += Align(SizeOfType(type), 4);
                }

                var xResultSize = xReturnSize;
                if (xResultSize % 4 != 0)
                {
                    xResultSize += 4 - (xResultSize % 4);
                }

                EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize);
            });
            XS.Label(xCurrentMethodLabel + ".NoExceptionAfterCall");
            XS.Comment("Argument Count = " + xParameters.Length);
        }
Beispiel #27
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);
            }
        }
Beispiel #28
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType   = aMethod.MethodBase.DeclaringType;
            var xOpCode = (ILOpCodes.OpField)aOpCode;

            SysReflection.FieldInfo xField = xOpCode.Value;
            var xIsReferenceType           = TypeIsReferenceType(xField.FieldType);

            // call cctor:
            var xCctor = (xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();

            if (xCctor != null && xCctor.DeclaringType != aMethod.MethodBase.DeclaringType)
            {
                XS.Call(LabelName.Get(xCctor));
                ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck");
                XS.Label(".AfterCCTorExceptionCheck");
            }

            //int aExtraOffset;// = 0;
            //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType;
            uint xSize = SizeOfType(xField.FieldType);

            //if( xNeedsGC )
            //{
            //    aExtraOffset = 12;
            //}
            new Comment(Assembler, "Type = '" + xField.FieldType.FullName /*+ "', NeedsGC = " + xNeedsGC*/);

            uint xOffset = 0;

            var xFields = xField.DeclaringType.GetFields();

            foreach (SysReflection.FieldInfo xInfo in xFields)
            {
                if (xInfo == xField)
                {
                    break;
                }

                xOffset += SizeOfType(xInfo.FieldType);
            }
            string xDataName = DataMember.GetStaticFieldName(xField);

            if (xIsReferenceType)
            {
                XS.Add(XSRegisters.ESP, 4);
                XS.Pop(XSRegisters.EAX);
                XS.Set(ElementReference.New(xDataName).Name, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4);
                return;
            }
            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationRef = ElementReference.New(xDataName, i * 4), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.EAX
                };
            }
            switch (xSize % 4)
            {
            case 1:
            {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationRef = ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.AL
                };
                break;
            }

            case 2:
            {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationRef = Cosmos.Assembler.ElementReference.New(xDataName, (int)((xSize / 4) * 4)), DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.AX
                };
                break;
            }

            case 0:
            {
                break;
            }

            default:
                //EmitNotImplementedException(Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + (xSize % 4) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel);
                throw new NotImplementedException();
                //break;
            }
        }
Beispiel #29
0
        public void Initialize()
        {
            uint xSig = 0x1BADB002;

            DataMembers.Add(new DataIfNotDefined("ELF_COMPILATION"));
            DataMembers.Add(new DataMember("MultibootSignature", new uint[]
            {
                xSig
            }));
            uint xFlags = 0x10007;

            DataMembers.Add(new DataMember("MultibootFlags", xFlags));
            DataMembers.Add(new DataMember("MultibootChecksum", (int)(0 - (xFlags + xSig))));
            DataMembers.Add(new DataMember("MultibootHeaderAddr", ElementReference.New("MultibootSignature")));
            DataMembers.Add(new DataMember("MultibootLoadAddr", ElementReference.New("MultibootSignature")));
            DataMembers.Add(new DataMember("MultibootLoadEndAddr", ElementReference.New("_end_code")));
            DataMembers.Add(new DataMember("MultibootBSSEndAddr", ElementReference.New("_end_code")));
            DataMembers.Add(new DataMember("MultibootEntryAddr", ElementReference.New("Kernel_Start")));
            DataMembers.Add(new DataMember("", 0));
            DataMembers.Add(new DataMember("", 800, 600, 32));
            DataMembers.Add(new DataEndIfDefined());

            DataMembers.Add(new DataIfDefined("ELF_COMPILATION"));
            xFlags = 0x00007;
            DataMembers.Add(new DataMember("MultibootSignature", new uint[]
            {
                xSig
            }));
            DataMembers.Add(new DataMember("MultibootFlags", xFlags));
            DataMembers.Add(new DataMember("MultibootChecksum", (int)(0 - (xFlags + xSig))));
            DataMembers.Add(new DataMember("", 0, 0, 0, 0, 0));
            DataMembers.Add(new DataMember("", 0));
            DataMembers.Add(new DataMember("", 800, 600, 32));
            DataMembers.Add(new DataEndIfDefined());

            //graphics info fields
            DataMembers.Add(new DataMember("MultibootGraphicsRuntime_VbeModeInfoAddr", 1 << 2));
            DataMembers.Add(new DataMember("MultibootGraphicsRuntime_VbeControlInfoAddr", 1 << 0));
            DataMembers.Add(new DataMember("MultibootGraphicsRuntime_VbeMode", 0));

            // memory
            DataMembers.Add(new DataMember("MultiBootInfo_Memory_High", 0));
            DataMembers.Add(new DataMember("MultiBootInfo_Memory_Low", 0));
            DataMembers.Add(new DataMember("Before_Kernel_Stack", new byte[0x50000]));
            DataMembers.Add(new DataMember("Kernel_Stack", new byte[0]));
            DataMembers.Add(new DataMember("MultiBootInfo_Structure", new uint[1]));

            // constants
            DataMembers.Add(new DataMember(@"__uint2double_const", new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x41 }));
            DataMembers.Add(new DataMember(@"__ulong2double_const", 0x5F800000));
            DataMembers.Add(new DataMember(@"__doublesignbit", 0x8000000000000000));
            DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));

            if (mComPort > 0)
            {
                new Define("DEBUGSTUB");
            }

            // This is our first entry point. Multiboot uses this as Cosmos entry point.
            new Label("Kernel_Start", isGlobal: true);
            XS.Set(XSRegisters.ESP, "Kernel_Stack");

            // Displays "Cosmos" in top left. Used to make sure Cosmos is booted in case of hang.
            // ie bootloader debugging. This must be the FIRST code, even before setup so we know
            // we are being called properly by the bootloader and that if there are problems its
            // somwhere in our code, not the bootloader.
            WriteDebugVideo("Cosmos pre boot");

            // For when using Bochs, causes a break ASAP on entry after initial Cosmos display.
            //new LiteralAssemblerCode("xchg bx, bx");

            // CLI ASAP
            WriteDebugVideo("Clearing interrupts.");
            XS.ClearInterruptFlag();


            WriteDebugVideo("Begin multiboot info.");
            new LiteralAssemblerCode("%ifndef EXCLUDE_MULTIBOOT_MAGIC");
            new Comment(this, "MultiBoot compliant loader provides info in registers: ");
            new Comment(this, "EBX=multiboot_info ");
            new Comment(this, "EAX=0x2BADB002 - check if it's really Multiboot-compliant loader ");
            new Comment(this, "                ;- copy mb info - some stuff for you  ");
            new Comment(this, "BEGIN - Multiboot Info");
            new Mov
            {
                DestinationRef        = ElementReference.New("MultiBootInfo_Structure"),
                DestinationIsIndirect = true,
                SourceReg             = RegistersEnum.EBX
            };
            XS.Add(XSRegisters.EBX, 4);
            XS.Set(XSRegisters.EAX, XSRegisters.EBX, sourceIsIndirect: true);
            new Mov
            {
                DestinationRef        = ElementReference.New("MultiBootInfo_Memory_Low"),
                DestinationIsIndirect = true,
                SourceReg             = RegistersEnum.EAX
            };
            XS.Add(XSRegisters.EBX, 4);
            XS.Set(XSRegisters.EAX, XSRegisters.EBX, sourceIsIndirect: true);
            new Mov
            {
                DestinationRef        = ElementReference.New("MultiBootInfo_Memory_High"),
                DestinationIsIndirect = true,
                SourceReg             = RegistersEnum.EAX
            };
            new Comment(this, "END - Multiboot Info");
            new LiteralAssemblerCode("%endif");
            WriteDebugVideo("Creating GDT.");
            CreateGDT();

            WriteDebugVideo("Configuring PIC");
            ConfigurePIC();

            WriteDebugVideo("Creating IDT.");
            CreateIDT();

            new Comment("Set graphics fields");
            new Mov {
                DestinationReg = XSRegisters.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure"), SourceIsIndirect = true
            };
            new Mov {
                DestinationReg = XSRegisters.EAX, SourceReg = XSRegisters.EBX, SourceIsIndirect = true, SourceDisplacement = 72
            };
            new Mov {
                DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeControlInfoAddr"), DestinationIsIndirect = true, SourceReg = XSRegisters.EAX
            };
            new Mov {
                DestinationReg = XSRegisters.EAX, SourceReg = XSRegisters.EBX, SourceIsIndirect = true, SourceDisplacement = 76
            };
            new Mov {
                DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeModeInfoAddr"), DestinationIsIndirect = true, SourceReg = XSRegisters.EAX
            };
            new Mov {
                DestinationReg = XSRegisters.EAX, SourceReg = XSRegisters.EBX, SourceIsIndirect = true, SourceDisplacement = 80
            };
            new Mov {
                DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeMode"), DestinationIsIndirect = true, SourceReg = XSRegisters.EAX
            };

            //WriteDebugVideo("Initializing SSE.");
            //new Comment(this, "BEGIN - SSE Init");
            //// CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
            //XS.Mov(XSRegisters.EAX, XSRegisters.Registers.CR4);
            //XS.Or(XSRegisters.EAX, 0x100);
            //XS.Mov(XSRegisters.CR4, XSRegisters.Registers.EAX);
            //XS.Mov(XSRegisters.EAX, XSRegisters.Registers.CR4);
            //XS.Or(XSRegisters.EAX, 0x200);
            //XS.Mov(XSRegisters.CR4, XSRegisters.Registers.EAX);
            //XS.Mov(XSRegisters.EAX, XSRegisters.Registers.CR0);

            //XS.And(XSRegisters.EAX, 0xfffffffd);
            //XS.Mov(XSRegisters.CR0, XSRegisters.Registers.EAX);
            //XS.Mov(XSRegisters.EAX, XSRegisters.Registers.CR0);

            //XS.And(XSRegisters.EAX, 1);
            //XS.Mov(XSRegisters.CR0, XSRegisters.Registers.EAX);
            //new Comment(this, "END - SSE Init");

            if (mComPort > 0)
            {
                WriteDebugVideo("Initializing DebugStub.");
                XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_Init]);
            }

            // Jump to Kernel entry point
            WriteDebugVideo("Jumping to kernel.");
            XS.Call(EntryPointName);

            new Comment(this, "Kernel done - loop till next IRQ");
            XS.Label(".loop");
            XS.ClearInterruptFlag();
            XS.Halt();
            XS.Jump(".loop");

            if (mComPort > 0)
            {
                var xGen = new AsmGenerator();

                var xGenerateAssembler =
                    new Action <object>(i =>
                {
                    if (i is StreamReader)
                    {
                        var xAsm = xGen.Generate((StreamReader)i);
                        CurrentInstance.Instructions.AddRange(xAsm.Instructions);
                        CurrentInstance.DataMembers.AddRange(xAsm.DataMembers);
                    }
                    else if (i is string)
                    {
                        var xAsm = xGen.Generate((string)i);
                        CurrentInstance.Instructions.AddRange(xAsm.Instructions);
                        CurrentInstance.DataMembers.AddRange(xAsm.DataMembers);
                    }
                    else
                    {
                        throw new Exception("Object type '" + i.ToString() + "' not supported!");
                    }
                });
                if (ReadDebugStubFromDisk)
                {
                    foreach (var xFile in Directory.GetFiles(CosmosPaths.DebugStubSrc, "*.xs"))
                    {
                        xGenerateAssembler(xFile);
                    }
                }
                else
                {
                    foreach (var xManifestName in typeof(ReferenceHelper).Assembly.GetManifestResourceNames())
                    {
                        if (!xManifestName.EndsWith(".xs", StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }
                        using (var xStream = typeof(ReferenceHelper).Assembly.GetManifestResourceStream(xManifestName))
                        {
                            using (var xReader = new StreamReader(xStream))
                            {
                                xGenerateAssembler(xReader);
                            }
                        }
                    }
                }
                OnAfterEmitDebugStub();
            }
            else
            {
                XS.Label(AsmMarker.Labels[AsmMarker.Type.DebugStub_Step]);
                XS.Return();
            }

            // Start emitting assembly labels
            CurrentInstance.EmitAsmLabels = true;
        }
Beispiel #30
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xStackItem = aOpCode.StackPopTypes[0];
            var xSize      = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1]));
            var xIsFloat   = TypeIsFloat(xStackItem);
            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException";

            if (xSize > 8)
            {
                throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div.cs->Error: StackSize > 8 not supported");
            }
            else if (xSize > 4)
            {
                if (xIsFloat)
                {
                    XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 8);
                    XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE2.DivSD(XMM1, XMM0);
                    XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    string BaseLabel       = GetLabel(aMethod, aOpCode) + ".";
                    string LabelShiftRight = BaseLabel + "ShiftRightLoop";
                    string LabelNoLoop     = BaseLabel + "NoLoop";
                    string LabelEnd        = BaseLabel + "End";

                    // divisor
                    // low
                    XS.Pop(ESI);
                    // high
                    XS.Pop(EDI);

                    XS.Xor(EAX, EAX);
                    XS.Or(EAX, ESI);
                    XS.Or(EAX, EDI);
                    XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel);

                    XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef));

                    XS.Label(xNoDivideByZeroExceptionLabel);

                    // dividend
                    // low
                    XS.Pop(EAX);
                    // high
                    XS.Pop(EDX);

                    // set flags
                    XS.Or(EDI, EDI);
                    // if high dword of divisor is already zero, we dont need the loop
                    XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop);

                    // set ecx to zero for counting the shift operations
                    XS.Xor(ECX, ECX);

                    // push most significant bit of result
                    XS.Set(EBX, EDI);
                    XS.Xor(EBX, EDX);
                    XS.Push(EBX);

                    XS.Compare(EDI, 0x80000000);
                    XS.Jump(ConditionalTestEnum.Below, BaseLabel + "divisor_no_neg");

                    XS.Negate(ESI);
                    XS.AddWithCarry(EDI, 0);
                    XS.Negate(EDI);

                    XS.Label(BaseLabel + "divisor_no_neg");

                    XS.Compare(EDX, 0x80000000);
                    XS.Jump(ConditionalTestEnum.Below, BaseLabel + "dividend_no_neg");

                    XS.Negate(EAX);
                    XS.AddWithCarry(EDX, 0);
                    XS.Negate(EDX);

                    XS.Label(BaseLabel + "dividend_no_neg");

                    XS.Label(LabelShiftRight);

                    // shift divisor 1 bit right
                    XS.ShiftRightDouble(ESI, EDI, 1);
                    XS.ShiftRight(EDI, 1);

                    // increment shift counter
                    XS.Increment(ECX);

                    // set flags
                    //XS.Or(EDI, EDI);
                    XS.Set(EBX, ESI);
                    XS.And(EBX, 0x80000000);
                    XS.Or(EBX, EDI);
                    // loop while high dword of divisor is not zero or most significant bit of low dword of divisor is set
                    XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight);

                    // shift the dividend now in one step
                    XS.ShiftRightDouble(EAX, EDX, CL);
                    // shift dividend CL bits right
                    XS.ShiftRight(EDX, CL);

                    // so we shifted both, so we have near the same relation as original values
                    // divide this
                    XS.IntegerDivide(ESI);

                    // pop most significant bit of result
                    XS.Pop(EBX);

                    XS.Compare(EBX, 0x80000000);
                    XS.Jump(ConditionalTestEnum.Below, BaseLabel + "_result_no_neg");

                    XS.Negate(EAX);

                    XS.Label(BaseLabel + "_result_no_neg");

                    // sign extend
                    XS.SignExtendAX(RegisterSize.Int32);

                    // save result to stack
                    XS.Push(EDX);
                    XS.Push(EAX);

                    //TODO: implement proper derivation correction and overflow detection

                    XS.Jump(LabelEnd);

                    XS.Label(LabelNoLoop);
                    // save high dividend
                    XS.Set(ECX, EAX);
                    XS.Set(EAX, EDX);

                    // extend that sign is in edx
                    XS.SignExtendAX(RegisterSize.Int32);
                    // divide high part
                    XS.IntegerDivide(ESI);
                    // save high result
                    XS.Push(EAX);
                    XS.Set(EAX, ECX);
                    // divide low part
                    XS.Divide(ESI);
                    // save low result
                    XS.Push(EAX);

                    XS.Label(LabelEnd);
                }
            }
            else
            {
                if (xIsFloat)
                {
                    XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
                    XS.Add(ESP, 4);
                    XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
                    XS.SSE.DivSS(XMM1, XMM0);
                    XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true);
                }
                else
                {
                    XS.Pop(ECX);

                    XS.Test(ECX, ECX);
                    XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel);

                    XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef));

                    XS.Label(xNoDivideByZeroExceptionLabel);

                    XS.Pop(EAX);

                    XS.SignExtendAX(RegisterSize.Int32);

                    XS.IntegerDivide(ECX);
                    XS.Push(EAX);
                }
            }
        }